From 69965aec393083158dbb05aa435599fc546d893a Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 6 Sep 2023 14:02:04 +0200 Subject: [PATCH 001/137] added best-practices/microsites --- best-practices/bg/@home.texy | 1 + best-practices/bg/microsites.texy | 63 +++++++++++++++++++++++++++++++ best-practices/cs/@home.texy | 1 + best-practices/cs/microsites.texy | 63 +++++++++++++++++++++++++++++++ best-practices/de/@home.texy | 1 + best-practices/de/microsites.texy | 63 +++++++++++++++++++++++++++++++ best-practices/el/@home.texy | 1 + best-practices/el/microsites.texy | 63 +++++++++++++++++++++++++++++++ best-practices/en/@home.texy | 1 + best-practices/en/microsites.texy | 63 +++++++++++++++++++++++++++++++ best-practices/es/@home.texy | 1 + best-practices/es/microsites.texy | 63 +++++++++++++++++++++++++++++++ best-practices/fr/@home.texy | 1 + best-practices/fr/microsites.texy | 63 +++++++++++++++++++++++++++++++ best-practices/hu/@home.texy | 1 + best-practices/hu/microsites.texy | 63 +++++++++++++++++++++++++++++++ best-practices/it/@home.texy | 1 + best-practices/it/microsites.texy | 63 +++++++++++++++++++++++++++++++ best-practices/pl/@home.texy | 1 + best-practices/pl/microsites.texy | 63 +++++++++++++++++++++++++++++++ best-practices/pt/@home.texy | 1 + best-practices/pt/microsites.texy | 63 +++++++++++++++++++++++++++++++ best-practices/ro/@home.texy | 1 + best-practices/ro/microsites.texy | 63 +++++++++++++++++++++++++++++++ best-practices/ru/@home.texy | 1 + best-practices/ru/microsites.texy | 63 +++++++++++++++++++++++++++++++ best-practices/sl/@home.texy | 1 + best-practices/sl/microsites.texy | 63 +++++++++++++++++++++++++++++++ best-practices/tr/@home.texy | 1 + best-practices/tr/microsites.texy | 63 +++++++++++++++++++++++++++++++ best-practices/uk/@home.texy | 1 + best-practices/uk/microsites.texy | 63 +++++++++++++++++++++++++++++++ 32 files changed, 1024 insertions(+) create mode 100644 best-practices/bg/microsites.texy create mode 100644 best-practices/cs/microsites.texy create mode 100644 best-practices/de/microsites.texy create mode 100644 best-practices/el/microsites.texy create mode 100644 best-practices/en/microsites.texy create mode 100644 best-practices/es/microsites.texy create mode 100644 best-practices/fr/microsites.texy create mode 100644 best-practices/hu/microsites.texy create mode 100644 best-practices/it/microsites.texy create mode 100644 best-practices/pl/microsites.texy create mode 100644 best-practices/pt/microsites.texy create mode 100644 best-practices/ro/microsites.texy create mode 100644 best-practices/ru/microsites.texy create mode 100644 best-practices/sl/microsites.texy create mode 100644 best-practices/tr/microsites.texy create mode 100644 best-practices/uk/microsites.texy diff --git a/best-practices/bg/@home.texy b/best-practices/bg/@home.texy index c3d00d8610..d8d9850d9b 100644 --- a/best-practices/bg/@home.texy +++ b/best-practices/bg/@home.texy @@ -36,6 +36,7 @@ Обща ---- - [Как да заредим конфигурационен файл |bootstrap:] +- [Как да пишем микросайтове |microsites] - [Защо Nette използва константна нотация PascalCase? |https://blog.nette.org/bg/za-po-malko-kresene-v-koda] - [Защо Nette не използва суфикса Interface? |https://blog.nette.org/bg/prefiksite-i-sufiksite-ne-prinadlezat-na-imenata-na-interfejsite] - [Съвети за използване на Composer |composer] diff --git a/best-practices/bg/microsites.texy b/best-practices/bg/microsites.texy new file mode 100644 index 0000000000..535babfa3f --- /dev/null +++ b/best-practices/bg/microsites.texy @@ -0,0 +1,63 @@ +Как да пишем микросайтове +************************* + +Представете си, че трябва бързо да създадете малък уебсайт за предстоящо събитие на вашата компания. Той трябва да бъде прост, бърз и без излишни усложнения. Може би си мислите, че такъв малък проект не изисква стабилна рамка. Но какво ще кажете, ако използването на рамката Nette може значително да опрости и ускори този процес? + +Дори когато създавате прости уебсайтове, не искате да се отказвате от комфорта. Не искате да изобретявате колелото наново. Чувствайте се свободни да бъдете мързеливи и да се поглезите. Рамката Nette може да се използва отлично и като микрорамка. + +Как може да изглежда един такъв микросайт? Например, целият код на уебсайта може да бъде поставен в един файл `index.php` в публичната папка: + +```php +<?php + +require __DIR__ . '/../vendor/autoload.php'; + +$configurator = new Nette\Bootstrap\Configurator; +$configurator->enableTracy(__DIR__ . '/../log'); +$configurator->setTempDirectory(__DIR__ . '/../temp'); + +// създаване на контейнер DI въз основа на конфигурацията в config.neon +$configurator->addConfig(__DIR__ . '/../app/config.neon'); +$container = $configurator->createContainer(); + +// настройка на маршрутизацията +$router = new Nette\Application\Routers\RouteList; +$container->addService('router', $router); + +// маршрут за URL https://example.com/ +$router->addRoute('', function ($presenter, Nette\Http\Request $httpRequest) { + // разпознаване на езика на браузъра и пренасочване към URL /en или /de и т.н. + $supportedLangs = ['en', 'de', 'cs']; + $lang = $httpRequest->detectLanguage($supportedLangs) ?: reset($supportedLangs); + $presenter->redirectUrl("/$lang"); +}); + +// маршрут за URL https://example.com/cs или https://example.com/en +$router->addRoute('', function ($presenter, string $lang) { + // покажете съответния шаблон, например ../templates/en.latte + $template = $presenter->createTemplate() + ->setFile(__DIR__ . '/../templates/' . $lang . '.latte'); + return $template; +}); + +// стартирайте приложението! +$container->getByType(Nette\Application\Application::class)->run(); +``` + +Всичко останало ще бъде шаблони, съхранявани в родителската папка `/templates`. + +PHP кодът в `index.php` първо настройва [средата |bootstrap:], след това дефинира [маршрути |application:routing#dynamic-routing-with-callbacks] и накрая стартира приложението. Предимството е, че вторият параметър на функцията `addRoute()` може да бъде извикващо се име, което се изпълнява при отваряне на съответната страница. + + +Защо да използвате Nette за микросайтове? .[#toc-why-use-nette-for-microsites] +------------------------------------------------------------------------------ + +- Разработчиците, които някога са опитвали [Трейси |tracy:], днес не могат да си представят кодирането без него. +- Но преди всичко ще използвате системата за шаблониране [Latte |latte:], защото само от 2 страници ще искате да разделите [оформлението и съдържанието |latte:template-inheritance]. +- И със сигурност искате да разчитате на [автоматичното ескапиране, |latte:safety-first] за да предотвратите XSS уязвимости. +- Nette също така гарантира, че в случай на грешка никога няма да бъдат показвани съобщения за грешка на PHP, а вместо това ще бъде показана удобна за потребителя страница. +- Ако искате да получавате обратна връзка от потребителите, например под формата на форма за контакт, можете да добавите и [форми |forms:] и [база данни |database:]. +- Можете също така лесно да [изпратите |mail:] попълнените формуляри [по имейл |mail:]. +- Понякога може да ви е полезно [кеширането |caching:], например при изтегляне и показване на емисии. + +В днешната епоха, в която скоростта и ефективността са от ключово значение, е важно да разполагате с инструменти, които ви позволяват да постигате резултати без излишни забавяния. Рамката Nette предлага точно това - бърза разработка, сигурност и широк набор от инструменти като Tracy и Latte, които опростяват процеса. Достатъчно е да инсталирате няколко пакета на Nette и изграждането на такъв микросайт се превръща в лесна задача. И знаете, че няма скрити недостатъци в сигурността. diff --git a/best-practices/cs/@home.texy b/best-practices/cs/@home.texy index 5466d6d7fc..b6fdd39ffc 100644 --- a/best-practices/cs/@home.texy +++ b/best-practices/cs/@home.texy @@ -36,6 +36,7 @@ Formuláře Obecné ------ - [Jak načíst konfigurační soubor |bootstrap:] +- [Jak psát mikro-weby |microsites] - [Proč Nette používá PascalCase notaci konstant? |https://blog.nette.org/cs/za-mene-kriku-v-kodu] - [Proč Nette nepoužívá příponu Interface? |https://blog.nette.org/cs/predpony-a-pripony-do-nazvu-rozhrani-nepatri] - [Composer: tipy pro použití |composer] diff --git a/best-practices/cs/microsites.texy b/best-practices/cs/microsites.texy new file mode 100644 index 0000000000..17a9fa7e41 --- /dev/null +++ b/best-practices/cs/microsites.texy @@ -0,0 +1,63 @@ +Jak psát mikro-weby +******************* + +Představte si, že potřebujete rychle vytvořit malý web pro nadcházející akci vaší firmy. Má to být jednoduché, rychlé a bez zbytečných komplikací. Možná si myslíte, že pro tak malý projekt nepotřebujete robustní framework. Ale co když použití Nette frameworku může tento proces zásadně zjednodušit a zrychlit? + +Přece i při tvorbě jednoduchých webů se nechcete vzdát pohodlí. Nechcete vymýšlet to, co už bylo jednou vyřešené. Buďte klidně líný a nechte se rozmazlovat. Nette Framework lze skvěle využít i jako micro framework. + +Jak takový microsite může vypadat? Například tak, že celý kód webu umístíme do jediného souboru `index.php` ve veřejné složce: + +```php +enableTracy(__DIR__ . '/../log'); +$configurator->setTempDirectory(__DIR__ . '/../temp'); + +// vytvoř DI kontejner na základě konfigurace v config.neon +$configurator->addConfig(__DIR__ . '/../app/config.neon'); +$container = $configurator->createContainer(); + +// nastavíme routing +$router = new Nette\Application\Routers\RouteList; +$container->addService('router', $router); + +// routa pro URL https://example.com/ +$router->addRoute('', function ($presenter, Nette\Http\Request $httpRequest) { + // detekujeme jazyk prohlížeče a přesměrujeme na URL /en nebo /de atd. + $supportedLangs = ['en', 'de', 'cs']; + $lang = $httpRequest->detectLanguage($supportedLangs) ?: reset($supportedLangs); + $presenter->redirectUrl("/$lang"); +}); + +// routa pro URL https://example.com/cs nebo https://example.com/en +$router->addRoute('', function ($presenter, string $lang) { + // zobrazíme příslušnou šablonu, například ../templates/en.latte + $template = $presenter->createTemplate() + ->setFile(__DIR__ . '/../templates/' . $lang . '.latte'); + return $template; +}); + +// spusť aplikaci! +$container->getByType(Nette\Application\Application::class)->run(); +``` + +Vše ostatní budou šablony uložené v nadřazené složce `/templates`. + +PHP kód v `index.php` nejprve [připraví prostředí |bootstrap:], poté definuje [routy|application:routing#dynamicke-routovani-s-callbacky] a nakonec spustí aplikaci. Výhodou je, že druhý parametr funkce `addRoute()` může být callable, který se po otevření odpovídající stránky vykoná. + + +Proč používat Nette pro microsite? +---------------------------------- + +- Programátoři, kteří někdy vyzkoušeli [Tracy|tracy:], si dnes neumí představit, že by něco programovali bez ní. +- Především ale využijete šablonovací systém [Latte|latte:], protože už od 2 stránek budete chtít mít oddělený [layout a obsah|latte:template-inheritance]. +- A rozhodně se chcete spolehout na [automatické escapování |latte:safety-first], aby nevznikla zranitelnost XSS +- Nette taky zajistí, že se při chybě nikdy neobrazí programátorské chybové hlášky PHP, ale uživateli srozumitelná stránka. +- Pokud chcete získávat zpětnou vazbu od uživatelů, například v podobě kontaktního formuláře, tak ještě přidáte [formuláře|forms:] a [databázi|database:]. +- Vyplněné formuláře si taktéž můžete nechat snadno [odesílat emailem|mail:]. +- Někdy se vám může hodit [kešování|caching:], například pokud stahujete a zobrazujete feedy. + +V dnešní době, kdy je rychlost a efektivita klíčová, je důležité mít nástroje, které vám umožní dosáhnout výsledků bez zbytečného zdržování. Nette framework vám nabízí právě to - rychlý vývoj, bezpečnost a širokou škálu nástrojů, jako je Tracy a Latte, které zjednodušují proces. Stačí nainstalovat pár Nette balíčků a vybudovat takovou microsite je najednou úplná hračka. A víte, že se nikde neskrývá žádná bezpečnostní díra. diff --git a/best-practices/de/@home.texy b/best-practices/de/@home.texy index 9a057ba919..20b2d44538 100644 --- a/best-practices/de/@home.texy +++ b/best-practices/de/@home.texy @@ -36,6 +36,7 @@ Formulare Allgemein --------- - [Wie man eine Konfigurationsdatei lädt |bootstrap:] +- [Wie man Microsites schreibt |microsites] - [Warum verwendet Nette die Konstantenschreibweise PascalCase? |https://blog.nette.org/de/fuer-weniger-geschrei-im-code] - [Warum verwendet Nette nicht das Suffix Interface? |https://blog.nette.org/de/praefixe-und-suffixe-gehoeren-nicht-in-schnittstellennamen] - [Tipps zur Verwendung des Composers |composer] diff --git a/best-practices/de/microsites.texy b/best-practices/de/microsites.texy new file mode 100644 index 0000000000..f28c89828c --- /dev/null +++ b/best-practices/de/microsites.texy @@ -0,0 +1,63 @@ +Wie man Microsites schreibt +*************************** + +Stellen Sie sich vor, Sie müssen schnell eine kleine Website für eine bevorstehende Veranstaltung Ihres Unternehmens erstellen. Sie soll einfach, schnell und ohne unnötige Komplikationen sein. Sie denken vielleicht, dass ein solch kleines Projekt kein robustes Framework benötigt. Aber was wäre, wenn die Verwendung des Nette-Frameworks diesen Prozess erheblich vereinfachen und beschleunigen könnte? + +Auch bei der Erstellung einfacher Websites wollen Sie nicht auf Komfort verzichten. Sie wollen das Rad nicht neu erfinden. Seien Sie ruhig faul und gönnen Sie sich etwas. Das Nette Framework lässt sich auch hervorragend als Micro-Framework einsetzen. + +Wie könnte eine solche Microsite aussehen? Zum Beispiel kann der gesamte Code der Website in einer einzigen `index.php` Datei im öffentlichen Ordner untergebracht werden: + +```php +<?php + +require __DIR__ . '/../vendor/autoload.php'; + +$configurator = new Nette\Bootstrap\Configurator; +$configurator->enableTracy(__DIR__ . '/../log'); +$configurator->setTempDirectory(__DIR__ . '/../temp'); + +// einen DI-Container auf der Grundlage der Konfiguration in config.neon erstellen +$configurator->addConfig(__DIR__ . '/../app/config.neon'); +$container = $configurator->createContainer(); + +// Routing einrichten +$router = new Nette\Application\Routers\RouteList; +$container->addService('router', $router); + +// Route für URL https://example.com/ +$router->addRoute('', function ($presenter, Nette\Http\Request $httpRequest) { + // Erkennung der Browsersprache und Umleitung auf URL /en oder /de usw. + $supportedLangs = ['en', 'de', 'cs']; + $lang = $httpRequest->detectLanguage($supportedLangs) ?: reset($supportedLangs); + $presenter->redirectUrl("/$lang"); +}); + +// Route für URL https://example.com/cs nebo https://example.com/en +$router->addRoute('', function ($presenter, string $lang) { + // Anzeige der entsprechenden Vorlage, zum Beispiel ../templates/de.latte + $template = $presenter->createTemplate() + ->setFile(__DIR__ . '/../templates/' . $lang . '.latte'); + return $template; +}); + +// Starten Sie die Anwendung! +$container->getByType(Nette\Application\Application::class)->run(); +``` + +Alles andere sind Vorlagen, die im übergeordneten Ordner `/templates` gespeichert werden. + +Der PHP-Code in `index.php` richtet zunächst [die Umgebung |bootstrap:] ein, definiert dann die [Routen |application:routing#dynamic-routing-with-callbacks] und führt schließlich die Anwendung aus. Der Vorteil ist, dass der zweite Parameter der Funktion `addRoute()` eine Callable sein kann, die ausgeführt wird, wenn die entsprechende Seite geöffnet wird. + + +Warum Nette für Microsites verwenden? .[#toc-why-use-nette-for-microsites] +-------------------------------------------------------------------------- + +- Entwickler, die [Tracy |tracy:] einmal ausprobiert haben, können sich heute nicht mehr vorstellen, ohne es zu programmieren. +- Aber vor allem werden Sie das Templating-System [Latte |latte:] nutzen, denn schon ab 2 Seiten werden Sie [Layout und Inhalt |latte:template-inheritance] trennen wollen. +- Und Sie wollen sich auf jeden Fall auf das [automatische Escaping |latte:safety-first] verlassen, um XSS-Schwachstellen zu vermeiden. +- Nette sorgt auch dafür, dass im Falle eines Fehlers niemals PHP-Fehlermeldungen angezeigt werden, sondern eine benutzerfreundliche Seite. +- Wenn Sie Feedback von den Nutzern erhalten möchten, zum Beispiel in Form eines Kontaktformulars, können Sie auch [Formulare |forms:] und eine [Datenbank |database:] hinzufügen. +- Sie können ausgefüllte Formulare auch einfach [per E-Mail versch |mail:]icken lassen. +- In manchen Fällen ist die [Zwischenspeicherung |caching:] nützlich, z. B. beim Herunterladen und Anzeigen von Feeds. + +In der heutigen Zeit, in der Geschwindigkeit und Effizienz entscheidend sind, ist es wichtig, über Werkzeuge zu verfügen, die es Ihnen ermöglichen, Ergebnisse ohne unnötige Verzögerungen zu erzielen. Das Nette-Framework bietet genau das - schnelle Entwicklung, Sicherheit und eine breite Palette von Tools wie Tracy und Latte, die den Prozess vereinfachen. Installieren Sie einfach ein paar Nette-Pakete, und die Erstellung einer solchen Microsite wird zum Kinderspiel. Und Sie wissen, dass es keine versteckten Sicherheitslücken gibt. diff --git a/best-practices/el/@home.texy b/best-practices/el/@home.texy index ba364faa14..e3df7ffbb0 100644 --- a/best-practices/el/@home.texy +++ b/best-practices/el/@home.texy @@ -36,6 +36,7 @@ Κοινό ----- - [Πώς να φορτώσετε το αρχείο ρυθμίσεων |bootstrap:] +- [Πώς να γράφετε microsites |microsites] - [Γιατί η Nette χρησιμοποιεί τη σημειογραφία σταθερών PascalCase; |https://blog.nette.org/el/gia-ligoteres-krauges-ston-kodika] - [Γιατί η Nette δεν χρησιμοποιεί την κατάληξη Interface; |https://blog.nette.org/el/ta-prothemata-kai-ta-epithemata-den-anekoun-sta-onomata-diasyndeses] - [Συμβουλές χρήσης του Composer |composer] diff --git a/best-practices/el/microsites.texy b/best-practices/el/microsites.texy new file mode 100644 index 0000000000..b33d0b10fa --- /dev/null +++ b/best-practices/el/microsites.texy @@ -0,0 +1,63 @@ +Πώς να γράψετε Microsites +************************* + +Φανταστείτε ότι πρέπει να δημιουργήσετε γρήγορα έναν μικρό ιστότοπο για μια επερχόμενη εκδήλωση της εταιρείας σας. Θα πρέπει να είναι απλή, γρήγορη και χωρίς περιττές επιπλοκές. Μπορεί να νομίζετε ότι ένα τόσο μικρό έργο δεν απαιτεί ένα ισχυρό πλαίσιο. Τι γίνεται όμως αν η χρήση του πλαισίου Nette μπορεί να απλοποιήσει και να επιταχύνει σημαντικά αυτή τη διαδικασία; + +Ακόμα και όταν δημιουργείτε απλές ιστοσελίδες, δεν θέλετε να παραιτηθείτε από την άνεση. Δεν θέλετε να ανακαλύψετε ξανά τον τροχό. Νιώστε ελεύθεροι να είστε τεμπέληδες και να περιποιηθείτε τον εαυτό σας. Το πλαίσιο Nette μπορεί επίσης να χρησιμοποιηθεί άριστα ως μικροπλαίσιο. + +Πώς θα μπορούσε να μοιάζει μια τέτοια μικροσελίδα; Για παράδειγμα, ολόκληρος ο κώδικας της ιστοσελίδας μπορεί να τοποθετηθεί σε ένα μόνο αρχείο `index.php` στον δημόσιο φάκελο: + +```php +<?php + +require __DIR__ . '/../vendor/autoload.php'; + +$configurator = new Nette\Bootstrap\Configurator; +$configurator->enableTracy(__DIR__ . '/../log'); +$configurator->setTempDirectory(__DIR__ . '/../temp'); + +// δημιουργία ενός DI container με βάση τη διαμόρφωση στο config.neon +$configurator->addConfig(__DIR__ . '/../app/config.neon'); +$container = $configurator->createContainer(); + +// να ρυθμίσετε τη δρομολόγηση +$router = new Nette\Application\Routers\RouteList; +$container->addService('router', $router); + +// διαδρομή για τη διεύθυνση URL https://example.com/ +$router->addRoute('', function ($presenter, Nette\Http\Request $httpRequest) { + // ανιχνεύει τη γλώσσα του προγράμματος περιήγησης και ανακατευθύνει στη διεύθυνση URL /en ή /de κ.λπ. + $supportedLangs = ['en', 'de', 'cs']; + $lang = $httpRequest->detectLanguage($supportedLangs) ?: reset($supportedLangs); + $presenter->redirectUrl("/$lang"); +}); + +// διαδρομή για τη διεύθυνση URL https://example.com/cs nebo https://example.com/en +$router->addRoute('', function ($presenter, string $lang) { + // εμφάνιση του κατάλληλου προτύπου, για παράδειγμα ../templates/en.latte + $template = $presenter->createTemplate() + ->setFile(__DIR__ . '/../templates/' . $lang . '.latte'); + return $template; +}); + +// εκτελέστε την εφαρμογή! +$container->getByType(Nette\Application\Application::class)->run(); +``` + +Όλα τα υπόλοιπα θα είναι πρότυπα που θα αποθηκεύονται στον γονικό φάκελο `/templates`. + +Ο κώδικας PHP στο `index.php` [ρυθμίζει |bootstrap:] πρώτα [το περιβάλλον |bootstrap:], στη συνέχεια ορίζει τις [διαδρομές |application:routing#dynamic-routing-with-callbacks] και τέλος εκτελεί την εφαρμογή. Το πλεονέκτημα είναι ότι η δεύτερη παράμετρος της συνάρτησης `addRoute()` μπορεί να είναι ένα callable που εκτελείται όταν ανοίγει η αντίστοιχη σελίδα. + + +Γιατί να χρησιμοποιήσετε τη Nette για μικροσελίδες; .[#toc-why-use-nette-for-microsites] +---------------------------------------------------------------------------------------- + +- Οι προγραμματιστές που δοκίμασαν ποτέ [το Tracy |tracy:] δεν μπορούν να φανταστούν σήμερα την κωδικοποίηση χωρίς αυτό. +- Αλλά πάνω απ' όλα, θα αξιοποιήσετε το σύστημα templating [Latte |latte:], επειδή από μόλις 2 σελίδες, θα θέλετε να διαχωρίσετε τη [διάταξη και το περιεχόμενο |latte:template-inheritance]. +- Και σίγουρα θέλετε να βασιστείτε στην [αυτόματη διαφυγή |latte:safety-first] για να αποφύγετε τα τρωτά σημεία XSS. +- Η Nette διασφαλίζει επίσης ότι σε περίπτωση σφάλματος, δεν θα εμφανίζονται ποτέ μηνύματα σφάλματος PHP, αλλά, αντίθετα, μια φιλική προς τον χρήστη σελίδα. +- Αν θέλετε να λαμβάνετε σχόλια από τους χρήστες, για παράδειγμα με τη μορφή φόρμας επικοινωνίας, μπορείτε επίσης να προσθέσετε [φόρμες |forms:] και [βάση δεδομένων |database:]. +- Μπορείτε επίσης εύκολα να έχετε συμπληρωμένες φόρμες που [αποστέλλονται μέσω ηλεκτρονικού ταχυδρομείου |mail:]. +- Ορισμένες φορές μπορεί να βρείτε την [προσωρινή αποθήκευση δεδομένων |caching:] χρήσιμη, για παράδειγμα, κατά τη λήψη και την εμφάνιση τροφοδοσιών. + +Στη σημερινή εποχή, όπου η ταχύτητα και η αποδοτικότητα είναι το κλειδί, είναι σημαντικό να έχετε εργαλεία που σας επιτρέπουν να επιτυγχάνετε αποτελέσματα χωρίς περιττές καθυστερήσεις. Το πλαίσιο Nette προσφέρει ακριβώς αυτό - γρήγορη ανάπτυξη, ασφάλεια και ένα ευρύ φάσμα εργαλείων όπως το Tracy και το Latte που απλοποιούν τη διαδικασία. Απλά εγκαταστήστε μερικά πακέτα Nette και η κατασκευή ενός τέτοιου microsite γίνεται παιχνιδάκι. Και ξέρετε ότι δεν υπάρχουν κρυφά κενά ασφαλείας. diff --git a/best-practices/en/@home.texy b/best-practices/en/@home.texy index 43f088951b..a83fdeb24e 100644 --- a/best-practices/en/@home.texy +++ b/best-practices/en/@home.texy @@ -36,6 +36,7 @@ Forms Common ------ - [How to load configuration file |bootstrap:] +- [How to write microsites |microsites] - [Why Nette uses PascalCase constant notation? |https://blog.nette.org/en/for-less-screaming-in-the-code] - [Why Nette doesn't use the Interface suffix? |https://blog.nette.org/en/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer usage tips |composer] diff --git a/best-practices/en/microsites.texy b/best-practices/en/microsites.texy new file mode 100644 index 0000000000..846ddbe96d --- /dev/null +++ b/best-practices/en/microsites.texy @@ -0,0 +1,63 @@ +How to Write Microsites +*********************** + +Imagine that you need to quickly create a small website for an upcoming event of your company. It should be simple, fast, and without unnecessary complications. You might think that such a small project doesn't require a robust framework. But what if using the Nette framework can significantly simplify and speed up this process? + +Even when creating simple websites, you don't want to give up comfort. You don't want to reinvent the wheel. Feel free to be lazy and pamper yourself. The Nette Framework can also be excellently used as a micro framework. + +What might such a microsite look like? For example, the entire code of the website can be placed in a single `index.php` file in the public folder: + +```php +enableTracy(__DIR__ . '/../log'); +$configurator->setTempDirectory(__DIR__ . '/../temp'); + +// create a DI container based on the configuration in config.neon +$configurator->addConfig(__DIR__ . '/../app/config.neon'); +$container = $configurator->createContainer(); + +// set up routing +$router = new Nette\Application\Routers\RouteList; +$container->addService('router', $router); + +// route for URL https://example.com/ +$router->addRoute('', function ($presenter, Nette\Http\Request $httpRequest) { + // detect browser language and redirect to URL /en or /de etc. + $supportedLangs = ['en', 'de', 'cs']; + $lang = $httpRequest->detectLanguage($supportedLangs) ?: reset($supportedLangs); + $presenter->redirectUrl("/$lang"); +}); + +// route for URL https://example.com/cs nebo https://example.com/en +$router->addRoute('', function ($presenter, string $lang) { + // display the appropriate template, for example ../templates/en.latte + $template = $presenter->createTemplate() + ->setFile(__DIR__ . '/../templates/' . $lang . '.latte'); + return $template; +}); + +// run the application! +$container->getByType(Nette\Application\Application::class)->run(); +``` + +Everything else will be templates stored in the parent `/templates` folder. + +The PHP code in `index.php` first [sets up the environment |bootstrap:], then defines [routes|application:routing#dynamic-routing-with-callbacks], and finally runs the application. The advantage is that the second parameter of the `addRoute()` function can be a callable that is executed when the corresponding page is opened. + + +Why use Nette for Microsites? +----------------------------- + +- Developers who have ever tried [Tracy|tracy:] can't imagine coding without it today. +- But above all, you will utilize the templating system [Latte|latte:], because from just 2 pages, you will want to separate [layout and content|latte:template-inheritance]. +- And you definitely want to rely on [automatic escaping |latte:safety-first] to prevent XSS vulnerabilities. +- Nette also ensures that in case of an error, PHP error messages will never be displayed, but instead, a user-friendly page will. +- If you want to get feedback from users, for example in the form of a contact form, you can also add [forms|forms:] and [database|database:]. +- You can also easily have filled-out forms [sent by email|mail:]. +- Sometimes you might find [caching|caching:] useful, for instance, when downloading and displaying feeds. + +In today's age, where speed and efficiency are key, it's important to have tools that allow you to achieve results without unnecessary delays. The Nette framework offers just that - fast development, security, and a wide range of tools like Tracy and Latte that simplify the process. Just install a few Nette packages, and building such a microsite becomes a breeze. And you know there are no hidden security flaws. diff --git a/best-practices/es/@home.texy b/best-practices/es/@home.texy index 2bbf67aa4b..2b8c641620 100644 --- a/best-practices/es/@home.texy +++ b/best-practices/es/@home.texy @@ -36,6 +36,7 @@ Formularios Común ----- - [Cómo cargar el fichero de configuración |bootstrap:] +- [Cómo escribir micrositios |microsites] - [¿Por qué Nette utiliza la notación constante PascalCase? |https://blog.nette.org/es/para-menos-gritos-en-el-codigo] - [¿Por qué Nette no utiliza el sufijo Interface? |https://blog.nette.org/es/los-prefijos-y-sufijos-no-pertenecen-a-los-nombres-de-interfaz] - [Consejos de uso de Composer |composer] diff --git a/best-practices/es/microsites.texy b/best-practices/es/microsites.texy new file mode 100644 index 0000000000..6899e693df --- /dev/null +++ b/best-practices/es/microsites.texy @@ -0,0 +1,63 @@ +Cómo escribir micrositios +************************* + +Imagine que necesita crear rápidamente un pequeño sitio web para un próximo evento de su empresa. Debe ser simple, rápido y sin complicaciones innecesarias. Podrías pensar que un proyecto tan pequeño no requiere un framework robusto. Pero, ¿y si el uso del framework Nette puede simplificar y acelerar significativamente este proceso? + +Incluso cuando se crean sitios web sencillos, no se quiere renunciar a la comodidad. No quieres reinventar la rueda. Siéntase libre de ser perezoso y mimarse. Nette Framework también puede utilizarse de forma excelente como micro framework. + +¿Qué aspecto podría tener un micrositio de este tipo? Por ejemplo, todo el código del sitio web puede colocarse en un único archivo `index.php` en la carpeta pública: + +```php +<?php + +require __DIR__ . '/../vendor/autoload.php'; + +$configurator = new Nette\Bootstrap\Configurator; +$configurator->enableTracy(__DIR__ . '/../log'); +$configurator->setTempDirectory(__DIR__ . '/../temp'); + +// crear un contenedor DI basado en la configuración en config.neon +$configurator->addConfig(__DIR__ . '/../app/config.neon'); +$container = $configurator->createContainer(); + +// configurar el enrutamiento +$router = new Nette\Application\Routers\RouteList; +$container->addService('router', $router); + +// ruta para la URL https://example.com/ +$router->addRoute('', function ($presenter, Nette\Http\Request $httpRequest) { + // detectar el idioma del navegador y redirigir a la URL /en o /de etc. + $supportedLangs = ['en', 'de', 'cs']; + $lang = $httpRequest->detectLanguage($supportedLangs) ?: reset($supportedLangs); + $presenter->redirectUrl("/$lang"); +}); + +// ruta para URL https://example.com/cs nebo https://example.com/en +$router->addRoute('', function ($presenter, string $lang) { + // mostrar la plantilla adecuada, por ejemplo ../templates/es.latte + $template = $presenter->createTemplate() + ->setFile(__DIR__ . '/../templates/' . $lang . '.latte'); + return $template; +}); + +// ejecutar la aplicación +$container->getByType(Nette\Application\Application::class)->run(); +``` + +Todo lo demás serán plantillas almacenadas en la carpeta padre `/templates`. + +El código PHP en `index.php` primero [configura el entorno |bootstrap:], luego define las [rutas |application:routing#dynamic-routing-with-callbacks] y finalmente ejecuta la aplicación. La ventaja es que el segundo parámetro de la función `addRoute()` puede ser un callable que se ejecuta cuando se abre la página correspondiente. + + +¿Por qué utilizar Nette para los micrositios? .[#toc-why-use-nette-for-microsites] +---------------------------------------------------------------------------------- + +- Los desarrolladores que hayan probado alguna vez [Tracy |tracy:] no se imaginan hoy en día codificar sin él. +- Pero sobre todo, utilizarán el sistema de plantillas [Latte |latte:], porque a partir de sólo 2 páginas, querrán separar [maquetación y contenido |latte:template-inheritance]. +- Y sin duda querrá confiar en el [escape automático |latte:safety-first] para evitar vulnerabilidades XSS. +- Nette también garantiza que, en caso de error, nunca se mostrarán mensajes de error de PHP, sino una página fácil de usar. +- Si desea obtener comentarios de los usuarios, por ejemplo en forma de formulario de contacto, también puede añadir [formularios |forms:] y [base de datos |database:]. +- También puedes hacer que los formularios rellenados se envíen fácilmente [por correo electrónico |mail:]. +- A veces puede resultarte útil [el almacenamiento en caché |caching:], por ejemplo, al descargar y mostrar feeds. + +En la era actual, en la que la velocidad y la eficacia son fundamentales, es importante contar con herramientas que permitan obtener resultados sin retrasos innecesarios. El framework Nette ofrece precisamente eso: desarrollo rápido, seguridad y una amplia gama de herramientas como Tracy y Latte que simplifican el proceso. Basta con instalar algunos paquetes de Nette, y construir un micrositio de este tipo se convierte en un juego de niños. Y sabes que no hay fallos de seguridad ocultos. diff --git a/best-practices/fr/@home.texy b/best-practices/fr/@home.texy index 0b3d8c26f6..2721f09ca9 100644 --- a/best-practices/fr/@home.texy +++ b/best-practices/fr/@home.texy @@ -36,6 +36,7 @@ Formulaires Commun ------ - [Comment charger le fichier de configuration |bootstrap:] +- [Comment rédiger des microsites |microsites] - [Pourquoi Nette utilise la notation constante PascalCase ? |https://blog.nette.org/fr/pour-moins-crier-dans-le-code] - [Pourquoi Nette n'utilise pas le suffixe Interface ? |https://blog.nette.org/fr/les-prefixes-et-les-suffixes-n-ont-pas-leur-place-dans-les-noms-d-interface] - [Conseils d'utilisation de Composer |composer] diff --git a/best-practices/fr/microsites.texy b/best-practices/fr/microsites.texy new file mode 100644 index 0000000000..cdc28d162b --- /dev/null +++ b/best-practices/fr/microsites.texy @@ -0,0 +1,63 @@ +Comment rédiger des microsites +****************************** + +Imaginez que vous ayez besoin de créer rapidement un petit site web pour un événement à venir de votre entreprise. Il doit être simple, rapide et sans complications inutiles. Vous pourriez penser qu'un si petit projet ne nécessite pas un framework robuste. Et si l'utilisation du framework Nette pouvait considérablement simplifier et accélérer ce processus ? + +Même lors de la création de sites web simples, vous ne voulez pas renoncer au confort. Vous ne voulez pas réinventer la roue. N'hésitez pas à être paresseux et à vous faire plaisir. Le cadre Nette peut également être utilisé de manière optimale en tant que micro-cadre. + +À quoi pourrait ressembler un tel microsite ? Par exemple, l'ensemble du code du site web peut être placé dans un seul fichier `index.php` dans le dossier public : + +```php +<?php + +require __DIR__ . '/../vendor/autoload.php'; + +$configurator = new Nette\Bootstrap\Configurator; +$configurator->enableTracy(__DIR__ . '/../log'); +$configurator->setTempDirectory(__DIR__ . '/../temp'); + +// créer un conteneur DI basé sur la configuration dans config.neon +$configurator->addConfig(__DIR__ . '/../app/config.neon'); +$container = $configurator->createContainer(); + +// mettre en place le routage +$router = new Nette\Application\Routers\RouteList; +$container->addService('router', $router); + +// route pour l'URL https://example.com/ +$router->addRoute('', function ($presenter, Nette\Http\Request $httpRequest) { + // détecter la langue du navigateur et rediriger vers l'URL /en ou /de etc. + $supportedLangs = ['en', 'de', 'cs']; + $lang = $httpRequest->detectLanguage($supportedLangs) ?: reset($supportedLangs); + $presenter->redirectUrl("/$lang"); +}); + +// route pour l'URL https://example.com/cs nebo https://example.com/en +$router->addRoute('', function ($presenter, string $lang) { + // affiche le modèle approprié, par exemple ../templates/en.latte + $template = $presenter->createTemplate() + ->setFile(__DIR__ . '/../templates/' . $lang . '.latte'); + return $template; +}); + +// Exécutez l'application ! +$container->getByType(Nette\Application\Application::class)->run(); +``` + +Tout le reste sera des modèles stockés dans le dossier parent `/templates`. + +Le code PHP dans `index.php` configure d'abord l'[environnement |bootstrap:], puis définit les [itinéraires |application:routing#dynamic-routing-with-callbacks] et enfin exécute l'application. L'avantage est que le deuxième paramètre de la fonction `addRoute()` peut être un appel qui est exécuté lorsque la page correspondante est ouverte. + + +Pourquoi utiliser Nette pour les microsites ? .[#toc-why-use-nette-for-microsites] +---------------------------------------------------------------------------------- + +- Les développeurs qui ont déjà essayé [Tracy |tracy:] ne peuvent imaginer coder sans lui aujourd'hui. +- Mais surtout, vous utiliserez le système de templates [Latte |latte:], parce qu'à partir de 2 pages seulement, vous voudrez séparer la [mise en page et le contenu |latte:template-inheritance]. +- Et vous voudrez certainement compter sur l'[échappement automatique |latte:safety-first] pour éviter les vulnérabilités XSS. +- Nette garantit également qu'en cas d'erreur, les messages d'erreur PHP ne seront jamais affichés, mais qu'une page conviviale le sera. +- Si vous souhaitez obtenir un retour d'information de la part des utilisateurs, par exemple sous la forme d'un formulaire de contact, vous pouvez également ajouter des [formulaires |forms:] et une [base de données |database:]. +- Vous pouvez également faire en sorte que les formulaires remplis soient [envoyés par courrier électronique |mail:]. +- La [mise en cache |caching:] peut parfois s'avérer utile, par exemple lors du téléchargement et de l'affichage de flux. + +À notre époque, où la rapidité et l'efficacité sont essentielles, il est important de disposer d'outils qui vous permettent d'obtenir des résultats sans retards inutiles. C'est précisément ce qu'offre le cadre Nette : un développement rapide, la sécurité et une large gamme d'outils tels que Tracy et Latte qui simplifient le processus. Il suffit d'installer quelques paquets Nette pour que la création d'un microsite devienne un jeu d'enfant. Et vous savez qu'il n'y a pas de failles de sécurité cachées. diff --git a/best-practices/hu/@home.texy b/best-practices/hu/@home.texy index 5d9c323f64..b647c32f9f 100644 --- a/best-practices/hu/@home.texy +++ b/best-practices/hu/@home.texy @@ -36,6 +36,7 @@ Nyomtatványok Közös ----- - [Konfigurációs fájl betöltése |bootstrap:] +- [Hogyan írjunk microsite-okat |microsites] - [Miért használ a Nette PascalCase konstans jelölést? |https://blog.nette.org/hu/kevesebb-sikolyert-a-kodban] - [Miért nem használja a Nette az Interface utótagot? |https://blog.nette.org/hu/az-elotagok-es-utotagok-nem-tartoznak-az-interfesznevekbe] - [Composer használati tippek |composer] diff --git a/best-practices/hu/microsites.texy b/best-practices/hu/microsites.texy new file mode 100644 index 0000000000..13c9024a32 --- /dev/null +++ b/best-practices/hu/microsites.texy @@ -0,0 +1,63 @@ +Hogyan írjunk mikrooldalakat +**************************** + +Képzelje el, hogy gyorsan létre kell hoznia egy kis weboldalt a cégének egy közelgő eseményéhez. Egyszerűnek, gyorsnak és felesleges bonyodalmak nélkülinek kell lennie. Azt gondolhatod, hogy egy ilyen kis projekt nem igényel robusztus keretrendszert. De mi van akkor, ha a Nette keretrendszer használatával jelentősen leegyszerűsítheti és felgyorsíthatja ezt a folyamatot? + +Még egyszerű weboldalak készítésekor sem szeretne lemondani a kényelemről. Nem akarja újra feltalálni a kereket. Legyen nyugodtan lusta és kényeztesse magát. A Nette keretrendszer mikro keretrendszerként is kiválóan használható. + +Hogyan nézhet ki egy ilyen mikrooldal? Például a weboldal teljes kódja egyetlen `index.php` fájlba helyezhető a nyilvános mappában: + +```php +<?php + +require __DIR__ . '/../vendor/autoload.php'; + +$configurator = new Nette\Bootstrap\Configurator; +$configurator->enableTracy(__DIR__ . '/../log'); +$configurator->setTempDirectory(__DIR__ . '/../temp'); + +// létrehoz egy DI konténert a config.neon konfiguráció alapján +$configurator->addConfig(__DIR__ . '/../app/config.neon'); +$container = $configurator->createContainer(); + +// útválasztás beállítása +$router = new Nette\Application\Routers\RouteList; +$container->addService('router', $router); + +// útvonal az URL https://example.com/ URL-hez +$router->addRoute('', function ($presenter, Nette\Http\Request $httpRequest) { + // a böngésző nyelvének felismerése és átirányítás az URL /en vagy /de stb. címre. + $supportedLangs = ['en', 'de', 'cs']; + $lang = $httpRequest->detectLanguage($supportedLangs) ?: reset($supportedLangs); + $presenter->redirectUrl("/$lang"); +}); + +// útvonal az URL-hez https://example.com/cs nebo https://example.com/en +$router->addRoute('', function ($presenter, string $lang) { + // a megfelelő sablon megjelenítése, például ../templates/en.latte + $template = $presenter->createTemplate() + ->setFile(__DIR__ . '/../templates/' . $lang . '.latte'); + return $template; +}); + +// futtassuk az alkalmazást! +$container->getByType(Nette\Application\Application::class)->run(); +``` + +Minden más a `/templates` szülőmappában tárolt sablonok lesznek. + +A `index.php` oldalon található PHP-kód először beállítja [a környezetet |bootstrap:], majd definiálja az [útvonalakat |application:routing#dynamic-routing-with-callbacks], végül pedig futtatja az alkalmazást. Ennek előnye, hogy a `addRoute()` függvény második paramétere lehet egy hívható, amely a megfelelő oldal megnyitásakor végrehajtódik. + + +Miért használja a Nette-et a mikrooldalakhoz? .[#toc-why-use-nette-for-microsites] +---------------------------------------------------------------------------------- + +- Azok a fejlesztők, akik valaha is kipróbálták a [Tracy-t |tracy:], ma már el sem tudják képzelni a kódolást nélküle. +- De mindenekelőtt a [Latte |latte:] templating rendszert fogja kihasználni, mert mindössze 2 oldalról akarja szétválasztani [az elrendezést és a tartalmat |latte:template-inheritance]. +- És mindenképpen az [automatikus escapingre |latte:safety-first] akarsz támaszkodni az XSS sebezhetőségek elkerülése érdekében. +- A Nette gondoskodik arról is, hogy hiba esetén soha ne jelenjenek meg PHP hibaüzenetek, hanem egy felhasználóbarát oldal jelenjen meg. +- Ha visszajelzést szeretne kapni a felhasználóktól, például kapcsolatfelvételi űrlap formájában, akkor [űrlapokat |forms:] és [adatbázist |database:] is hozzáadhat. +- A kitöltött űrlapokat is könnyen [elküldheti e-mailben |mail:]. +- Néha hasznos lehet a [gyorsítótárazás |caching:], például a feedek letöltésekor és megjelenítésekor. + +A mai korban, amikor a gyorsaság és a hatékonyság kulcsfontosságú, fontos, hogy olyan eszközökkel rendelkezzen, amelyekkel felesleges késedelmek nélkül érhet el eredményeket. A Nette keretrendszer pontosan ezt kínálja: gyors fejlesztést, biztonságot és olyan eszközök széles skáláját, mint a Tracy és a Latte, amelyek leegyszerűsítik a folyamatot. Csak telepítsen néhány Nette csomagot, és egy ilyen microsite építése gyerekjátékká válik. És tudja, hogy nincsenek rejtett biztonsági hibák. diff --git a/best-practices/it/@home.texy b/best-practices/it/@home.texy index 10f16cec1d..bb15638c9d 100644 --- a/best-practices/it/@home.texy +++ b/best-practices/it/@home.texy @@ -36,6 +36,7 @@ Moduli Comune ------ - [Come caricare il file di configurazione |bootstrap:] +- [Come scrivere micrositi |microsites] - [Perché Nette usa la notazione costante PascalCase? |https://blog.nette.org/it/per-non-urlare-nel-codice] - [Perché Nette non usa il suffisso Interface? |https://blog.nette.org/it/i-prefissi-e-i-suffissi-non-appartengono-ai-nomi-delle-interfacce] - [Suggerimenti per l'uso di Composer |composer] diff --git a/best-practices/it/microsites.texy b/best-practices/it/microsites.texy new file mode 100644 index 0000000000..d023f24d7d --- /dev/null +++ b/best-practices/it/microsites.texy @@ -0,0 +1,63 @@ +Come scrivere micrositi +*********************** + +Immaginate di dover creare rapidamente un piccolo sito web per un evento imminente della vostra azienda. Dovrebbe essere semplice, veloce e senza inutili complicazioni. Potreste pensare che un progetto così piccolo non richieda un framework robusto. Ma se l'utilizzo del framework Nette semplificasse e velocizzasse notevolmente questo processo? + +Anche quando si creano siti web semplici, non si vuole rinunciare al comfort. Non volete reinventare la ruota. Sentitevi liberi di essere pigri e di coccolarvi. Il framework Nette può essere utilizzato in modo eccellente anche come micro framework. + +Come potrebbe essere un microsito di questo tipo? Ad esempio, l'intero codice del sito web può essere inserito in un singolo file `index.php` nella cartella pubblica: + +```php +<?php + +require __DIR__ . '/../vendor/autoload.php'; + +$configurator = new Nette\Bootstrap\Configurator; +$configurator->enableTracy(__DIR__ . '/../log'); +$configurator->setTempDirectory(__DIR__ . '/../temp'); + +// creare un contenitore DI basato sulla configurazione in config.neon +$configurator->addConfig(__DIR__ . '/../app/config.neon'); +$container = $configurator->createContainer(); + +// impostare l'instradamento +$router = new Nette\Application\Routers\RouteList; +$container->addService('router', $router); + +// rotta per l'URL https://example.com/ +$router->addRoute('', function ($presenter, Nette\Http\Request $httpRequest) { + // rilevare la lingua del browser e reindirizzare all'URL /en o /de ecc. + $supportedLangs = ['en', 'de', 'cs']; + $lang = $httpRequest->detectLanguage($supportedLangs) ?: reset($supportedLangs); + $presenter->redirectUrl("/$lang"); +}); + +// rotta per l'URL https://example.com/cs nebo https://example.com/en +$router->addRoute('', function ($presenter, string $lang) { + // visualizza il modello appropriato, ad esempio ../templates/it.latte + $template = $presenter->createTemplate() + ->setFile(__DIR__ . '/../templates/' . $lang . '.latte'); + return $template; +}); + +// eseguire l'applicazione! +$container->getByType(Nette\Application\Application::class)->run(); +``` + +Tutto il resto saranno modelli memorizzati nella cartella madre `/templates`. + +Il codice PHP in `index.php` imposta prima l'[ambiente |bootstrap:], poi definisce le [rotte |application:routing#dynamic-routing-with-callbacks] e infine esegue l'applicazione. Il vantaggio è che il secondo parametro della funzione `addRoute()` può essere un callable che viene eseguito quando viene aperta la pagina corrispondente. + + +Perché usare Nette per i micrositi? .[#toc-why-use-nette-for-microsites] +------------------------------------------------------------------------ + +- Gli sviluppatori che hanno provato [Tracy |tracy:] non possono immaginare di codificare senza di esso oggi. +- Ma soprattutto, utilizzerete il sistema di template [Latte |latte:], perché da sole 2 pagine, vorrete separare [layout e contenuti |latte:template-inheritance]. +- E sicuramente vorrete affidarvi all'[escape automatico |latte:safety-first] per prevenire le vulnerabilità XSS. +- Nette garantisce inoltre che, in caso di errore, non vengano mai visualizzati messaggi di errore PHP, ma una pagina di facile consultazione. +- Se si desidera ottenere un feedback dagli utenti, ad esempio sotto forma di modulo di contatto, è possibile aggiungere [moduli |forms:] e [database |database:]. +- È anche possibile [inviare |mail:] facilmente [via e-mail |mail:] i moduli compilati. +- A volte può essere utile la [cache |caching:], ad esempio quando si scaricano e si visualizzano i feed. + +Nell'era odierna, in cui velocità ed efficienza sono fondamentali, è importante disporre di strumenti che consentano di ottenere risultati senza inutili ritardi. Il framework Nette offre proprio questo: sviluppo veloce, sicurezza e un'ampia gamma di strumenti come Tracy e Latte che semplificano il processo. Basta installare alcuni pacchetti Nette e la costruzione di un microsito di questo tipo diventa un gioco da ragazzi. E si sa che non ci sono falle di sicurezza nascoste. diff --git a/best-practices/pl/@home.texy b/best-practices/pl/@home.texy index 32416cbcfb..71e32b1075 100644 --- a/best-practices/pl/@home.texy +++ b/best-practices/pl/@home.texy @@ -36,6 +36,7 @@ Formularze Wspólne ------- - [Jak załadować plik konfiguracyjny |bootstrap:] +- [Jak pisać mikrowitryny |microsites] - [Dlaczego Nette używa notacji stałej PascalCase? |https://blog.nette.org/pl/aby-mniej-krzyczec-w-kodzie] - [Dlaczego Nette nie używa przyrostka Interface? |https://blog.nette.org/pl/przedrostki-i-przyrostki-nie-sa-czescia-nazw-interfejsow] - [Kompozytor: wskazówki dotyczące użytkowania |composer] diff --git a/best-practices/pl/microsites.texy b/best-practices/pl/microsites.texy new file mode 100644 index 0000000000..64a7bfcc71 --- /dev/null +++ b/best-practices/pl/microsites.texy @@ -0,0 +1,63 @@ +Jak pisać mikrostrony internetowe +********************************* + +Wyobraź sobie, że musisz szybko stworzyć małą stronę internetową na nadchodzące wydarzenie Twojej firmy. Powinna być prosta, szybka i bez zbędnych komplikacji. Można by pomyśleć, że tak mały projekt nie wymaga solidnego frameworka. Ale co, jeśli użycie frameworka Nette może znacznie uprościć i przyspieszyć ten proces? + +Nawet tworząc proste strony internetowe, nie chcesz rezygnować z wygody. Nie chcesz wymyślać koła na nowo. Możesz być leniwy i rozpieszczać samego siebie. Nette Framework może być również doskonale wykorzystywany jako mikro framework. + +Jak może wyglądać taka mikrostrona? Na przykład, cały kod strony może być umieszczony w pojedynczym pliku `index.php` w folderze publicznym: + +```php +<?php + +require __DIR__ . '/../vendor/autoload.php'; + +$configurator = new Nette\Bootstrap\Configurator; +$configurator->enableTracy(__DIR__ . '/../log'); +$configurator->setTempDirectory(__DIR__ . '/../temp'); + +// utworzenie kontenera DI na podstawie konfiguracji w config.neon +$configurator->addConfig(__DIR__ . '/../app/config.neon'); +$container = $configurator->createContainer(); + +// skonfigurować routing +$router = new Nette\Application\Routers\RouteList; +$container->addService('router', $router); + +// trasa dla adresu URL https://example.com/ +$router->addRoute('', function ($presenter, Nette\Http\Request $httpRequest) { + // wykrywanie języka przeglądarki i przekierowanie na URL /en lub /de itp. + $supportedLangs = ['en', 'de', 'cs']; + $lang = $httpRequest->detectLanguage($supportedLangs) ?: reset($supportedLangs); + $presenter->redirectUrl("/$lang"); +}); + +// trasa dla adresu URL https://example.com/cs nebo https://example.com/en +$router->addRoute('', function ($presenter, string $lang) { + // wyświetla odpowiedni szablon, na przykład ../templates/en.latte + $template = $presenter->createTemplate() + ->setFile(__DIR__ . '/../templates/' . $lang . '.latte'); + return $template; +}); + +// uruchom aplikację! +$container->getByType(Nette\Application\Application::class)->run(); +``` + +Cała reszta będzie szablonami przechowywanymi w folderze nadrzędnym `/templates`. + +Kod PHP w `index.php` najpierw konfiguruje [środowisko |bootstrap:], następnie definiuje [trasy |application:routing#dynamic-routing-with-callbacks], a na końcu uruchamia aplikację. Zaletą jest to, że drugim parametrem funkcji `addRoute()` może być wywołanie, które jest wykonywane po otwarciu odpowiedniej strony. + + +Dlaczego warto używać Nette dla mikrostron? .[#toc-why-use-nette-for-microsites] +-------------------------------------------------------------------------------- + +- Programiści, którzy kiedykolwiek wypróbowali [Tracy |tracy:], nie wyobrażają sobie dziś kodowania bez niego. +- Ale przede wszystkim będziesz korzystać z systemu szablonów [Latte |latte:], ponieważ z zaledwie 2 stron będziesz chciał oddzielić [układ i zawartość |latte:template-inheritance]. +- I zdecydowanie chcesz polegać na [automatycznym uciekaniu |latte:safety-first], aby zapobiec lukom w zabezpieczeniach XSS. +- Nette zapewnia również, że w przypadku błędu komunikaty o błędach PHP nigdy nie będą wyświetlane, ale zamiast tego pojawi się przyjazna dla użytkownika strona. +- Jeśli chcesz uzyskać informacje zwrotne od użytkowników, na przykład w formie formularza kontaktowego, możesz również dodać [formularze |forms:] i [bazę danych |database:]. +- Możesz także łatwo wysyłać wypełnione formularze [pocztą e-mail |mail:]. +- Czasami przydatne może okazać się [buforowanie |caching:], na przykład podczas pobierania i wyświetlania kanałów. + +W dzisiejszych czasach, gdzie szybkość i wydajność są kluczowe, ważne jest, aby mieć narzędzia, które pozwalają osiągnąć wyniki bez zbędnych opóźnień. Framework Nette oferuje właśnie to - szybki rozwój, bezpieczeństwo i szeroką gamę narzędzi, takich jak Tracy i Latte, które upraszczają proces. Wystarczy zainstalować kilka pakietów Nette, a zbudowanie takiej mikrostrony staje się dziecinnie proste. I wiesz, że nie ma żadnych ukrytych luk w zabezpieczeniach. diff --git a/best-practices/pt/@home.texy b/best-practices/pt/@home.texy index 5435e5eceb..6eba10e4ea 100644 --- a/best-practices/pt/@home.texy +++ b/best-practices/pt/@home.texy @@ -36,6 +36,7 @@ Formulários Comum ----- - [Como carregar o arquivo de configuração |bootstrap:] +- [Como escrever microsites |microsites] - [Por que a Nette usa a notação constante PascalCase? |https://blog.nette.org/pt/por-menos-gritos-no-codigo] - [Por que Nette não usa o sufixo Interface? |https://blog.nette.org/pt/prefixos-e-sufixos-nao-pertencem-a-nomes-de-interface] - [Dicas de uso do compositor |composer] diff --git a/best-practices/pt/microsites.texy b/best-practices/pt/microsites.texy new file mode 100644 index 0000000000..d436664b88 --- /dev/null +++ b/best-practices/pt/microsites.texy @@ -0,0 +1,63 @@ +Como escrever microsites +************************ + +Imagine que você precise criar rapidamente um pequeno site para um evento futuro da sua empresa. Ele deve ser simples, rápido e sem complicações desnecessárias. Você pode pensar que um projeto tão pequeno não requer uma estrutura robusta. Mas e se o uso da estrutura Nette pudesse simplificar e acelerar significativamente esse processo? + +Mesmo ao criar sites simples, você não quer abrir mão do conforto. Você não quer reinventar a roda. Sinta-se à vontade para ser preguiçoso e se mimar. O Nette Framework também pode ser usado de forma excelente como uma microestrutura. + +Como seria esse microsite? Por exemplo, todo o código do site pode ser colocado em um único arquivo `index.php` na pasta pública: + +```php +<?php + +require __DIR__ . '/../vendor/autoload.php'; + +$configurator = new Nette\Bootstrap\Configurator; +$configurator->enableTracy(__DIR__ . '/../log'); +$configurator->setTempDirectory(__DIR__ . '/../temp'); + +// Crie um contêiner DI com base na configuração em config.neon +$configurator->addConfig(__DIR__ . '/../app/config.neon'); +$container = $configurator->createContainer(); + +// configurar o roteamento +$router = new Nette\Application\Routers\RouteList; +$container->addService('router', $router); + +// rota para o URL https://example.com/ +$router->addRoute('', function ($presenter, Nette\Http\Request $httpRequest) { + // detectar o idioma do navegador e redirecionar para o URL /en ou /de etc. + $supportedLangs = ['en', 'de', 'cs']; + $lang = $httpRequest->detectLanguage($supportedLangs) ?: reset($supportedLangs); + $presenter->redirectUrl("/$lang"); +}); + +// rota para o URL https://example.com/cs nebo https://example.com/en +$router->addRoute('', function ($presenter, string $lang) { + // exibir o modelo apropriado, por exemplo, ../templates/en.latte + $template = $presenter->createTemplate() + ->setFile(__DIR__ . '/../templates/' . $lang . '.latte'); + return $template; +}); + +// Execute o aplicativo! +$container->getByType(Nette\Application\Application::class)->run(); +``` + +Todo o resto serão modelos armazenados na pasta principal `/templates`. + +O código PHP em `index.php` primeiro [configura o ambiente |bootstrap:], depois define [as rotas |application:routing#dynamic-routing-with-callbacks] e, por fim, executa o aplicativo. A vantagem é que o segundo parâmetro da função `addRoute()` pode ser um chamável que é executado quando a página correspondente é aberta. + + +Por que usar o Nette para microsites? .[#toc-why-use-nette-for-microsites] +-------------------------------------------------------------------------- + +- Os desenvolvedores que já experimentaram [o Tracy |tracy:] não conseguem imaginar a codificação sem ele hoje. +- Mas, acima de tudo, você utilizará o sistema de modelos [Latte |latte:], pois a partir de apenas duas páginas, você desejará separar [o layout do conteúdo |latte:template-inheritance]. +- E, com certeza, você vai querer contar com o [escape automático |latte:safety-first] para evitar vulnerabilidades de XSS. +- O Nette também garante que, em caso de erro, as mensagens de erro do PHP nunca serão exibidas, mas, em vez disso, será exibida uma página de fácil utilização. +- Se quiser obter feedback dos usuários, por exemplo, na forma de um formulário de contato, também é possível adicionar [formulários |forms:] e [banco de dados |database:]. +- Os formulários preenchidos também podem ser facilmente [enviados por e-mail |mail:]. +- Às vezes, o armazenamento [em cache |caching:] pode ser útil, por exemplo, ao baixar e exibir feeds. + +Na era atual, em que velocidade e eficiência são fundamentais, é importante ter ferramentas que permitam obter resultados sem atrasos desnecessários. A estrutura Nette oferece exatamente isso: desenvolvimento rápido, segurança e uma ampla variedade de ferramentas, como Tracy e Latte, que simplificam o processo. Basta instalar alguns pacotes Nette e criar um microsite como esse se torna muito fácil. E você sabe que não há falhas de segurança ocultas. diff --git a/best-practices/ro/@home.texy b/best-practices/ro/@home.texy index 823591e492..5a2a254154 100644 --- a/best-practices/ro/@home.texy +++ b/best-practices/ro/@home.texy @@ -36,6 +36,7 @@ Formulare Comună ------ - [Cum se încarcă fișierul de configurare |bootstrap:] +- [Cum să scrieți microsite-uri |microsites] - [De ce Nette folosește notația constantă PascalCase? |https://blog.nette.org/ro/pentru-mai-putine-tipete-in-cod] - [De ce Nette nu folosește sufixul Interface? |https://blog.nette.org/ro/prefixele-si-sufixele-nu-se-regasesc-in-numele-interfetelor] - [Sfaturi pentru utilizarea Composer |composer] diff --git a/best-practices/ro/microsites.texy b/best-practices/ro/microsites.texy new file mode 100644 index 0000000000..bdeb94a83c --- /dev/null +++ b/best-practices/ro/microsites.texy @@ -0,0 +1,63 @@ +Cum să scrieți microsite-uri +**************************** + +Imaginați-vă că trebuie să creați rapid un mic site web pentru un eveniment viitor al companiei dumneavoastră. Acesta trebuie să fie simplu, rapid și fără complicații inutile. S-ar putea să vă gândiți că un proiect atât de mic nu necesită un framework robust. Dar dacă utilizarea cadrului Nette ar putea simplifica și accelera semnificativ acest proces? + +Chiar și atunci când creați site-uri web simple, nu doriți să renunțați la confort. Nu doriți să reinventați roata. Simțiți-vă liber să fiți leneș și să vă răsfățați. Cadrul Nette Framework poate fi folosit excelent și ca microcadru. + +Cum ar putea arăta un astfel de microsite? De exemplu, întregul cod al site-ului poate fi plasat într-un singur fișier `index.php` în folderul public: + +```php +<?php + +require __DIR__ . '/../vendor/autoload.php'; + +$configurator = new Nette\Bootstrap\Configurator; +$configurator->enableTracy(__DIR__ . '/../log'); +$configurator->setTempDirectory(__DIR__ . '/../temp'); + +// creați un container DI pe baza configurației din config.neon +$configurator->addConfig(__DIR__ . '/../app/config.neon'); +$container = $configurator->createContainer(); + +// configurați rutarea +$router = new Nette\Application\Routers\RouteList; +$container->addService('router', $router); + +// ruta pentru URL https://example.com/ +$router->addRoute('', function ($presenter, Nette\Http\Request $httpRequest) { + // detectează limba browserului și redirecționează la URL /en sau /de etc. + $supportedLangs = ['en', 'de', 'cs']; + $lang = $httpRequest->detectLanguage($supportedLangs) ?: reset($supportedLangs); + $presenter->redirectUrl("/$lang"); +}); + +// ruta pentru URL https://example.com/cs nebo https://example.com/en +$router->addRoute('', function ($presenter, string $lang) { + // afișează șablonul corespunzător, de exemplu ../template/ro.latte + $template = $presenter->createTemplate() + ->setFile(__DIR__ . '/../templates/' . $lang . '.latte'); + return $template; +}); + +// rulați aplicația! +$container->getByType(Nette\Application\Application::class)->run(); +``` + +Restul vor fi șabloane stocate în dosarul părinte `/templates`. + +Codul PHP din `index.php` [stabilește |bootstrap:] mai întâi [mediul |bootstrap:], apoi definește [rutele |application:routing#dynamic-routing-with-callbacks] și, în final, rulează aplicația. Avantajul este că al doilea parametru al funcției `addRoute()` poate fi un callable care este executat atunci când se deschide pagina corespunzătoare. + + +De ce să folosiți Nette pentru microsite-uri? .[#toc-why-use-nette-for-microsites] +---------------------------------------------------------------------------------- + +- Dezvoltatorii care au încercat vreodată [Tracy |tracy:] nu-și pot imagina astăzi codarea fără el. +- Dar, mai presus de toate, veți utiliza sistemul de template-uri [Latte |latte:], deoarece de la doar 2 pagini, veți dori să separați [aspectul și conținutul |latte:template-inheritance]. +- Și, cu siguranță, veți dori să vă bazați pe [escape-ul automat |latte:safety-first] pentru a preveni vulnerabilitățile XSS. +- De asemenea, Latte se asigură că, în caz de eroare, nu vor fi afișate niciodată mesaje de eroare PHP, ci în schimb, o pagină ușor de utilizat. +- Dacă doriți să obțineți feedback de la utilizatori, de exemplu sub forma unui formular de contact, puteți adăuga, de asemenea, [formulare |forms:] și [bază de date |database:]. +- De asemenea, puteți face cu ușurință ca formularele completate să fie [trimise prin e-mail |mail:]. +- Uneori s-ar putea să vă fie utilă [memoria cache |caching:], de exemplu, atunci când descărcați și afișați fluxuri. + +În epoca actuală, în care viteza și eficiența sunt esențiale, este important să dispuneți de instrumente care vă permit să obțineți rezultate fără întârzieri inutile. Cadrul Nette oferă exact acest lucru - dezvoltare rapidă, securitate și o gamă largă de instrumente precum Tracy și Latte, care simplifică procesul. Este suficient să instalați câteva pachete Nette, iar construirea unui astfel de microsite devine o joacă de copii. Și știți că nu există defecte de securitate ascunse. diff --git a/best-practices/ru/@home.texy b/best-practices/ru/@home.texy index 05f2905032..69eed2aa87 100644 --- a/best-practices/ru/@home.texy +++ b/best-practices/ru/@home.texy @@ -36,6 +36,7 @@ Общие ----- - [Как загрузить файл конфигурации |bootstrap:] +- [Как писать микросайты |microsites] - [Почему Nette использует константную нотацию PascalCase? |https://blog.nette.org/ru/ctoby-men-se-kricat-v-kode] - [Почему Nette не использует суффикс Interface? |https://blog.nette.org/ru/prefiksy-i-suffiksy-ne-dolzny-prisutstvovat-v-imenah-interfejsov] - [Советы по использованию Composer |composer] diff --git a/best-practices/ru/microsites.texy b/best-practices/ru/microsites.texy new file mode 100644 index 0000000000..4db9a76100 --- /dev/null +++ b/best-practices/ru/microsites.texy @@ -0,0 +1,63 @@ +Как писать микросайты +********************* + +Представьте себе, что вам нужно быстро создать небольшой сайт для предстоящего мероприятия вашей компании. Он должен быть простым, быстрым и без лишних сложностей. Вы можете подумать, что для такого небольшого проекта не нужен надежный фреймворк. Но что если использование фреймворка Nette значительно упростит и ускорит этот процесс? + +Даже при создании простых сайтов не стоит отказываться от удобства. Не стоит изобретать колесо. Не стесняйтесь лениться и баловать себя. Фреймворк Nette Framework можно прекрасно использовать и в качестве микрофреймворка. + +Как может выглядеть такой микросайт? Например, весь код сайта может быть размещен в одном файле `index.php` в общей папке: + +```php +<?php + +require __DIR__ . '/../vendor/autoload.php'; + +$configurator = new Nette\Bootstrap\Configurator; +$configurator->enableTracy(__DIR__ . '/../log'); +$configurator->setTempDirectory(__DIR__ . '/../temp'); + +// создание DI-контейнера на основе конфигурации в config.neon +$configurator->addConfig(__DIR__ . '/../app/config.neon'); +$container = $configurator->createContainer(); + +// настройка маршрутизации +$router = new Nette\Application\Routers\RouteList; +$container->addService('router', $router); + +// маршрут для URL https://example.com/ +$router->addRoute('', function ($presenter, Nette\Http\Request $httpRequest) { + // определять язык браузера и перенаправлять на URL /en или /de и т.д. + $supportedLangs = ['en', 'de', 'cs']; + $lang = $httpRequest->detectLanguage($supportedLangs) ?: reset($supportedLangs); + $presenter->redirectUrl("/$lang"); +}); + +// маршрут для URL https://example.com/cs nebo https://example.com/en +$router->addRoute('', function ($presenter, string $lang) { + // отобразить соответствующий шаблон, например ../templates/en.latte + $template = $presenter->createTemplate() + ->setFile(__DIR__ . '/../templates/' . $lang . '.latte'); + return $template; +}); + +// запустите приложение! +$container->getByType(Nette\Application\Application::class)->run(); +``` + +Все остальное будет представлять собой шаблоны, хранящиеся в родительской папке `/templates`. + +PHP-код в папке `index.php` сначала устанавливает [окружение |bootstrap:], затем определяет [маршруты |application:routing#dynamic-routing-with-callbacks] и, наконец, запускает приложение. Преимуществом является то, что вторым параметром функции `addRoute()` может быть вызываемая переменная, которая выполняется при открытии соответствующей страницы. + + +Почему стоит использовать Nette для микросайтов? .[#toc-why-use-nette-for-microsites] +------------------------------------------------------------------------------------- + +- Разработчики, которые когда-либо пробовали [Tracy |tracy:], сегодня не могут представить себе кодирование без нее. +- Но прежде всего вам пригодится система шаблонов [Latte |latte:], поскольку всего с 2 страниц вы захотите разделить [верстку и контент |latte:template-inheritance]. +- А для предотвращения XSS-уязвимостей вам обязательно понадобится [автоматическое экранирование |latte:safety-first]. +- Nette также гарантирует, что в случае ошибки никогда не будут выводиться сообщения об ошибках PHP, а вместо них будет отображаться удобная для пользователя страница. +- Если вы хотите получать обратную связь от пользователей, например, в виде контактной формы, вы также можете добавить [формы |forms:] и [базу данных |database:]. +- Кроме того, заполненные формы можно легко отправить по [электронной почте |mail:]. +- Иногда может пригодиться [кэширование |caching:], например, при загрузке и отображении лент. + +В наше время, когда скорость и эффективность являются ключевыми факторами, важно иметь инструменты, позволяющие достигать результатов без лишних задержек. Фреймворк Nette предлагает именно такие инструменты - быструю разработку, безопасность и широкий набор средств, таких как Tracy и Latte, которые упрощают процесс. Достаточно установить несколько пакетов Nette, и создание такого микросайта превращается в легкое дело. При этом вы будете уверены, что в системе безопасности нет никаких скрытых недостатков. diff --git a/best-practices/sl/@home.texy b/best-practices/sl/@home.texy index ea4899f2ec..f89b8a74a1 100644 --- a/best-practices/sl/@home.texy +++ b/best-practices/sl/@home.texy @@ -36,6 +36,7 @@ Obrazci Skupna spletna stran -------------------- - [Kako naložiti konfiguracijsko datoteko |bootstrap:] +- [Kako napisati mikrostrani |microsites] - [Zakaj Nette uporablja konstantni zapis PascalCase |https://blog.nette.org/sl/za-manj-kricanja-v-kodi]? - [Zakaj Nette ne uporablja končnice Interface |https://blog.nette.org/sl/predpone-in-pripone-ne-sodijo-v-imena-vmesnikov]? - [Nasveti za uporabo programa Composer |composer] diff --git a/best-practices/sl/microsites.texy b/best-practices/sl/microsites.texy new file mode 100644 index 0000000000..ce6af7d0da --- /dev/null +++ b/best-practices/sl/microsites.texy @@ -0,0 +1,63 @@ +Kako napisati mikrostrani +************************* + +Predstavljajte si, da morate na hitro ustvariti majhno spletno stran za prihajajoči dogodek vašega podjetja. Biti mora preprosta, hitra in brez nepotrebnih zapletov. Morda mislite, da tako majhen projekt ne zahteva robustnega ogrodja. Kaj pa, če lahko z uporabo ogrodja Nette ta postopek bistveno poenostavite in pospešite? + +Tudi pri ustvarjanju preprostih spletnih mest se ne želite odpovedati udobju. Ne želite na novo izumljati kolesa. Privoščite si, da ste leni in se razvajate. Okvir Nette je mogoče odlično uporabiti tudi kot mikrookvir. + +Kako je lahko videti takšna mikrostrani? Celotno kodo spletnega mesta lahko na primer postavite v eno samo datoteko `index.php` v javni mapi: + +```php +<?php + +require __DIR__ . '/../vendor/autoload.php'; + +$configurator = new Nette\Bootstrap\Configurator; +$configurator->enableTracy(__DIR__ . '/../log'); +$configurator->setTempDirectory(__DIR__ . '/../temp'); + +// ustvarite vsebnik DI na podlagi konfiguracije v config.neon +$configurator->addConfig(__DIR__ . '/../app/config.neon'); +$container = $configurator->createContainer(); + +// nastavi usmerjanje +$router = new Nette\Application\Routers\RouteList; +$container->addService('router', $router); + +// pot za URL https://example.com/ +$router->addRoute('', function ($presenter, Nette\Http\Request $httpRequest) { + // zaznajo jezik brskalnika in preusmerijo na URL /en ali /de itd. + $supportedLangs = ['en', 'de', 'cs']; + $lang = $httpRequest->detectLanguage($supportedLangs) ?: reset($supportedLangs); + $presenter->redirectUrl("/$lang"); +}); + +// pot za URL https://example.com/cs ali https://example.com/en +$router->addRoute('', function ($presenter, string $lang) { + // prikaže ustrezno predlogo, na primer ../templates/en.latte + $template = $presenter->createTemplate() + ->setFile(__DIR__ . '/../templates/' . $lang . '.latte'); + return $template; +}); + +// zaženite aplikacijo! +$container->getByType(Nette\Application\Application::class)->run(); +``` + +Vse drugo bodo predloge, shranjene v nadrejeni mapi `/templates`. + +Koda PHP v mapi `index.php` najprej vzpostavi [okolje |bootstrap:], nato definira [poti |application:routing#dynamic-routing-with-callbacks] in nazadnje zažene aplikacijo. Prednost je, da je lahko drugi parameter funkcije `addRoute()` klicni ukaz, ki se izvede, ko se odpre ustrezna stran. + + +Zakaj uporabljati Nette za mikrostrani? .[#toc-why-use-nette-for-microsites] +---------------------------------------------------------------------------- + +- Razvijalci, ki so kdaj preizkusili [Tracy |tracy:], si danes ne morejo predstavljati kodiranja brez njega. +- Predvsem pa boste uporabili sistem za oblikovanje predlog [Latte |latte:], saj boste iz samo dveh strani želeli ločiti [postavitev in vsebino |latte:template-inheritance]. +- In vsekakor se boste želeli zanesti na [samodejno pobeganje, |latte:safety-first] da bi preprečili ranljivosti XSS. +- Nette zagotavlja tudi, da se v primeru napake ne bodo nikoli prikazala sporočila o napaki PHP, temveč bo namesto tega prikazana uporabniku prijazna stran. +- Če želite od uporabnikov pridobiti povratne informacije, na primer v obliki kontaktnega obrazca, lahko dodate tudi [obrazce |forms:] in [zbirko podatkov |database:]. +- Izpolnjene obrazce lahko preprosto [pošljete |mail:] tudi po [elektronski pošti |mail:]. +- Včasih se vam lahko zdi koristno [predpomnjenje |caching:], na primer pri prenašanju in prikazovanju virov. + +V današnjem času, ko sta hitrost in učinkovitost ključnega pomena, je pomembno imeti orodja, ki vam omogočajo doseganje rezultatov brez nepotrebnih zamud. Okvir Nette ponuja prav to - hiter razvoj, varnost in široko paleto orodij, kot sta Tracy in Latte, ki poenostavljajo postopek. Samo namestite nekaj paketov Nette in gradnja takšne mikrostrani bo postala enostavna. Poleg tega veste, da ni nobenih skritih varnostnih pomanjkljivosti. diff --git a/best-practices/tr/@home.texy b/best-practices/tr/@home.texy index 1cc97db6f5..f773189fcb 100644 --- a/best-practices/tr/@home.texy +++ b/best-practices/tr/@home.texy @@ -36,6 +36,7 @@ Formlar Ortak ----- - [Yapılandırma dosyası nasıl yüklenir |bootstrap:] +- [Mikro siteler nasıl yazılır |microsites] - [Nette neden PascalCase sabit gösterimini kullanıyor? |https://blog.nette.org/tr/kodda-daha-az-ciglik-atmak-icin] - [Nette neden Interface son ekini kullanmıyor? |https://blog.nette.org/tr/oenek-ve-sonekler-arayuez-adlarina-ait-degildir] - [Composer kullanım ipuçları |composer] diff --git a/best-practices/tr/microsites.texy b/best-practices/tr/microsites.texy new file mode 100644 index 0000000000..977df38b40 --- /dev/null +++ b/best-practices/tr/microsites.texy @@ -0,0 +1,63 @@ +Mikro Siteler Nasıl Yazılır +*************************** + +Şirketinizin yaklaşan bir etkinliği için hızlı bir şekilde küçük bir web sitesi oluşturmanız gerektiğini düşünün. Basit, hızlı ve gereksiz komplikasyonlardan uzak olmalı. Bu kadar küçük bir projenin sağlam bir framework gerektirmediğini düşünebilirsiniz. Peki ya Nette çerçevesini kullanmak bu süreci önemli ölçüde basitleştirip hızlandırabilirse? + +Basit web siteleri oluştururken bile konfordan vazgeçmek istemezsiniz. Tekerleği yeniden icat etmek istemezsiniz. Tembel olmaktan ve kendinizi şımartmaktan çekinmeyin. Nette Framework mikro framework olarak da mükemmel bir şekilde kullanılabilir. + +Böyle bir mikro site neye benzeyebilir? Örneğin, web sitesinin tüm kodu genel klasördeki tek bir `index.php` dosyasına yerleştirilebilir: + +```php +<?php + +require __DIR__ . '/../vendor/autoload.php'; + +$configurator = new Nette\Bootstrap\Configurator; +$configurator->enableTracy(__DIR__ . '/../log'); +$configurator->setTempDirectory(__DIR__ . '/../temp'); + +// config.neon dosyasındaki yapılandırmaya göre bir DI konteyneri oluşturun +$configurator->addConfig(__DIR__ . '/../app/config.neon'); +$container = $configurator->createContainer(); + +// Yönlendirmeyi ayarlayın +$router = new Nette\Application\Routers\RouteList; +$container->addService('router', $router); + +// URL için rota https://example.com/ +$router->addRoute('', function ($presenter, Nette\Http\Request $httpRequest) { + // tarayıcı dilini algılar ve /en veya /de vb. URL'ye yönlendirir. + $supportedLangs = ['en', 'de', 'cs']; + $lang = $httpRequest->detectLanguage($supportedLangs) ?: reset($supportedLangs); + $presenter->redirectUrl("/$lang"); +}); + +// URL için rota https://example.com/cs nebo https://example.com/en +$router->addRoute('', function ($presenter, string $lang) { + // uygun şablonu görüntüleyin, örneğin ../templates/en.latte + $template = $presenter->createTemplate() + ->setFile(__DIR__ . '/../templates/' . $lang . '.latte'); + return $template; +}); + +// uygulamayı çalıştırın! +$container->getByType(Nette\Application\Application::class)->run(); +``` + +Diğer her şey üst `/templates` klasöründe depolanan şablonlar olacaktır. + + `index.php` adresindeki PHP kodu önce [ortamı kur |bootstrap:]ar, sonra [rotaları |application:routing#dynamic-routing-with-callbacks] tanımlar ve son olarak uygulamayı çalıştırır. Bunun avantajı, `addRoute()` işlevinin ikinci parametresinin, ilgili sayfa açıldığında çalıştırılan bir çağrılabilir olmasıdır. + + +Mikro Siteler için Neden Nette Kullanılmalı? .[#toc-why-use-nette-for-microsites] +--------------------------------------------------------------------------------- + +- [Tracy |tracy:] 'yi denemiş olan geliştiriciler bugün onsuz kodlama yapmayı hayal bile edemezler. +- Ancak her şeyden önce, [Latte |latte:] şablonlama sistemini kullanacaksınız, çünkü sadece 2 sayfadan [düzen ve içeriği |latte:template-inheritance] ayırmak isteyeceksiniz. +- Ve XSS güvenlik açıklarını önlemek için kesinlikle [otomatik kaçışa |latte:safety-first] güvenmek isteyeceksiniz. +- Nette ayrıca bir hata durumunda PHP hata mesajlarının asla görüntülenmemesini, bunun yerine kullanıcı dostu bir sayfanın görüntülenmesini sağlar. +- Kullanıcılardan geri bildirim almak istiyorsanız, örneğin bir iletişim formu şeklinde, [formlar |forms:] ve [veritabanı |database:] da ekleyebilirsiniz. +- Doldurulan formların [e-posta ile gönderilmesini |mail:] de kolayca sağlayabilirsiniz. +- Bazen, örneğin beslemeleri indirirken ve görüntülerken [önbelleğe |caching:] almayı yararlı bulabilirsiniz. + +Hız ve verimliliğin kilit önem taşıdığı günümüzde, gereksiz gecikmeler olmadan sonuçlara ulaşmanızı sağlayan araçlara sahip olmak önemlidir. Nette framework tam da bunu sunuyor - hızlı geliştirme, güvenlik ve süreci basitleştiren Tracy ve Latte gibi çok çeşitli araçlar. Sadece birkaç Nette paketi kurun ve böyle bir mikro site oluşturmak çocuk oyuncağı haline gelsin. Ve hiçbir gizli güvenlik açığı olmadığını bilirsiniz. diff --git a/best-practices/uk/@home.texy b/best-practices/uk/@home.texy index 25d1fa8493..cfbe213cbd 100644 --- a/best-practices/uk/@home.texy +++ b/best-practices/uk/@home.texy @@ -36,6 +36,7 @@ Спільне ------- - [Як завантажити конфігураційний файл |bootstrap:] +- [Як писати мікросайти |microsites] - [Чому Nette використовує нотацію констант у регістрі PascalCase? |https://blog.nette.org/uk/sob-mense-kriku-v-kodi] - [Чому Nette не використовує суфікс Interface? |https://blog.nette.org/uk/prefiksi-ta-sufiksi-ne-potribni-v-nazvah-interfejsiv] - [Поради щодо використання Composer |composer] diff --git a/best-practices/uk/microsites.texy b/best-practices/uk/microsites.texy new file mode 100644 index 0000000000..05599232db --- /dev/null +++ b/best-practices/uk/microsites.texy @@ -0,0 +1,63 @@ +Як писати мікросайти +******************** + +Уявіть, що вам потрібно швидко створити невеликий сайт для майбутньої події вашої компанії. Він повинен бути простим, швидким і без зайвих складнощів. Ви можете подумати, що такий невеликий проект не потребує надійного фреймворку. Але що, якщо використання фреймворку Nette може значно спростити і прискорити цей процес? + +Навіть при створенні простих веб-сайтів не хочеться відмовлятися від комфорту. Ви не хочете винаходити велосипед. Не соромтеся лінуватися і балувати себе. Nette Framework також можна чудово використовувати як мікрофреймворк. + +Як може виглядати такий мікросайт? Наприклад, весь код сайту можна розмістити в одному файлі `index.php` в загальній папці: + +```php +<?php + +require __DIR__ . '/../vendor/autoload.php'; + +$configurator = new Nette\Bootstrap\Configurator; +$configurator->enableTracy(__DIR__ . '/../log'); +$configurator->setTempDirectory(__DIR__ . '/../temp'); + +// створити контейнер DI на основі конфігурації в config.neon +$configurator->addConfig(__DIR__ . '/../app/config.neon'); +$container = $configurator->createContainer(); + +// налаштуйте маршрутизацію +$router = new Nette\Application\Routers\RouteList; +$container->addService('router', $router); + +// маршрут для URL https://example.com/ +$router->addRoute('', function ($presenter, Nette\Http\Request $httpRequest) { + // визначити мову браузера і перенаправити на URL /en або /de і т.д. + $supportedLangs = ['en', 'de', 'cs']; + $lang = $httpRequest->detectLanguage($supportedLangs) ?: reset($supportedLangs); + $presenter->redirectUrl("/$lang"); +}); + +// маршрут для URL https://example.com/cs nebo https://example.com/en +$router->addRoute('', function ($presenter, string $lang) { + // відобразити відповідний шаблон, наприклад ../templates/en.latte + $template = $presenter->createTemplate() + ->setFile(__DIR__ . '/../templates/' . $lang . '.latte'); + return $template; +}); + +// запускаємо додаток! +$container->getByType(Nette\Application\Application::class)->run(); +``` + +Все інше буде шаблонами, що зберігаються в батьківській папці `/templates`. + +PHP-код в `index.php` спочатку налаштовує [середовище |bootstrap:], потім визначає [маршрути |application:routing#dynamic-routing-with-callbacks] і, нарешті, запускає додаток. Перевага полягає в тому, що другим параметром функції `addRoute()` може бути виклик, який виконується при відкритті відповідної сторінки. + + +Чому варто використовувати Nette для мікросайтів? .[#toc-why-use-nette-for-microsites] +-------------------------------------------------------------------------------------- + +- Розробники, які хоч раз спробували [Tracy |tracy:], не можуть уявити собі кодування без нього сьогодні. +- Але перш за все, ви будете використовувати систему шаблонів [Latte |latte:], тому що всього з 2 сторінок ви захочете відокремити [макет і контент |latte:template-inheritance]. +- І ви точно захочете покластися на [автоматичне |latte:safety-first] екранування, щоб запобігти XSS-уразливостям. +- Nette також гарантує, що у випадку помилки, повідомлення про помилки PHP ніколи не будуть відображатися, а натомість буде показана зручна для користувача сторінка. +- Якщо ви хочете отримати зворотній зв'язок від користувачів, наприклад, у вигляді контактної форми, ви також можете додати [форми |forms:] і [базу даних |database:]. +- Ви також можете легко надсилати заповнені форми [електронною |mail:] поштою. +- Іноді вам може стати в нагоді [кешування |caching:], наприклад, при завантаженні та відображенні новин. + +У наш час, коли швидкість та ефективність є ключовими, важливо мати інструменти, які дозволяють досягати результатів без зайвих затримок. Фреймворк Nette пропонує саме це - швидку розробку, безпеку та широкий спектр інструментів, таких як Tracy та Latte, які спрощують процес. Просто встановіть кілька пакетів Nette, і створення такого мікросайту стане легкою справою. І ви знаєте, що немає ніяких прихованих вразливостей у безпеці. From 7d347b406d84dc885a3aa8a3801031e7d8cebd25 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Fri, 8 Sep 2023 11:08:24 +0200 Subject: [PATCH 002/137] latte 3.0.9 --- latte/bg/develop.texy | 19 ++++++++++++++----- latte/bg/syntax.texy | 14 ++++++++++++++ latte/bg/tags.texy | 2 ++ latte/cs/develop.texy | 19 ++++++++++++++----- latte/cs/syntax.texy | 14 ++++++++++++++ latte/cs/tags.texy | 2 ++ latte/de/develop.texy | 21 +++++++++++++++------ latte/de/syntax.texy | 14 ++++++++++++++ latte/de/tags.texy | 2 ++ latte/el/develop.texy | 19 ++++++++++++++----- latte/el/syntax.texy | 14 ++++++++++++++ latte/el/tags.texy | 2 ++ latte/en/develop.texy | 19 ++++++++++++++----- latte/en/syntax.texy | 14 ++++++++++++++ latte/en/tags.texy | 2 ++ latte/es/develop.texy | 19 ++++++++++++++----- latte/es/syntax.texy | 14 ++++++++++++++ latte/es/tags.texy | 2 ++ latte/fr/develop.texy | 21 +++++++++++++++------ latte/fr/syntax.texy | 14 ++++++++++++++ latte/fr/tags.texy | 2 ++ latte/hu/develop.texy | 19 ++++++++++++++----- latte/hu/syntax.texy | 14 ++++++++++++++ latte/hu/tags.texy | 2 ++ latte/it/develop.texy | 19 ++++++++++++++----- latte/it/syntax.texy | 14 ++++++++++++++ latte/it/tags.texy | 2 ++ latte/ja/develop.texy | 25 +++++++++++++++++-------- latte/ja/syntax.texy | 14 ++++++++++++++ latte/ja/tags.texy | 2 ++ latte/pl/develop.texy | 19 ++++++++++++++----- latte/pl/syntax.texy | 14 ++++++++++++++ latte/pl/tags.texy | 2 ++ latte/pt/develop.texy | 19 ++++++++++++++----- latte/pt/syntax.texy | 14 ++++++++++++++ latte/pt/tags.texy | 2 ++ latte/ro/develop.texy | 19 ++++++++++++++----- latte/ro/syntax.texy | 14 ++++++++++++++ latte/ro/tags.texy | 2 ++ latte/ru/develop.texy | 21 +++++++++++++++------ latte/ru/syntax.texy | 14 ++++++++++++++ latte/ru/tags.texy | 2 ++ latte/sl/develop.texy | 19 ++++++++++++++----- latte/sl/syntax.texy | 14 ++++++++++++++ latte/sl/tags.texy | 2 ++ latte/tr/develop.texy | 19 ++++++++++++++----- latte/tr/syntax.texy | 14 ++++++++++++++ latte/tr/tags.texy | 2 ++ latte/uk/develop.texy | 21 +++++++++++++++------ latte/uk/syntax.texy | 14 ++++++++++++++ latte/uk/tags.texy | 2 ++ 51 files changed, 517 insertions(+), 92 deletions(-) diff --git a/latte/bg/develop.texy b/latte/bg/develop.texy index e947567ea5..ee1700be03 100644 --- a/latte/bg/develop.texy +++ b/latte/bg/develop.texy @@ -274,16 +274,25 @@ vendor/bin/latte-lint // въведете действителния път до файла autoload.php require __DIR__ . '/vendor/autoload.php'; -$engine = new Latte\Engine; -// добавете отделни разширения тук -$engine->addExtension(/* ... */); +$path = $argv[1] ?? '.'; + +$linter = new Latte\Tools\Linter; +$latte = $linter->getEngine(); +// добавете индивидуалните си разширения тук +$latte->addExtension(/* ... */); -$path = $argv[1]; -$linter = new Latte\Tools\Linter(engine: $engine); $ok = $linter->scanDirectory($path); exit($ok ? 0 : 1); ``` +Като алтернатива можете да предадете свой собствен обект `Latte\Engine` на Linter: + +```php +$latte = new Latte\Engine; +// тук конфигурираме обекта $latte +$linter = new Latte\Tools\Linter(engine: $latte); +``` + Зареждане на шаблони от низ .[#toc-loading-templates-from-a-string] =================================================================== diff --git a/latte/bg/syntax.texy b/latte/bg/syntax.texy index fe5dce9df2..5a5eb32559 100644 --- a/latte/bg/syntax.texy +++ b/latte/bg/syntax.texy @@ -155,6 +155,20 @@ Latte ви позволява да извиквате филтри със зна ``` +Динамични HTML етикети .[#toc-dynamic-html-tags] +================================================ + +Latte поддържа динамични HTML тагове, които са полезни, когато се нуждаете от гъвкавост в имената на таговете: + +```latte +Heading +``` + +Например, кодът по-горе може да генерира `

Heading

` или `

Heading

` в зависимост от стойността на променливата `$level`. Динамичните HTML тагове в Latte трябва винаги да бъдат сдвоени. Тяхната алтернатива е [n:tag |tags#n:tag]. + +Тъй като Latte е сигурна система за шаблониране, тя проверява дали полученото име на тага е валидно и не съдържа нежелани или злонамерени стойности. Тя също така гарантира, че името на крайния таг винаги е същото като името на началния таг. + + Коментарите са изключени за .[#toc-comments] ============================================ diff --git a/latte/bg/tags.texy b/latte/bg/tags.texy index 99e8382a9a..0ab9c59ade 100644 --- a/latte/bg/tags.texy +++ b/latte/bg/tags.texy @@ -991,6 +991,8 @@ n:tag .[#toc-n-tag]

...

``` +Тъй като Latte е сигурна система за шаблониране, тя проверява дали името на новия таг е валидно и не съдържа нежелани или злонамерени стойности. + n:ifcontent .[#toc-n-ifcontent] ------------------------------- diff --git a/latte/cs/develop.texy b/latte/cs/develop.texy index 32e43894a7..396ba77813 100644 --- a/latte/cs/develop.texy +++ b/latte/cs/develop.texy @@ -274,16 +274,25 @@ Pokud používáte vlastní značky, vytvořte si také vlastní verzi Linteru, // zadejte skutečnou cestu k soubor autoload.php require __DIR__ . '/vendor/autoload.php'; -$engine = new Latte\Engine; -// tady přidejte jednotlivá rozšíření -$engine->addExtension(/* ... */); +$path = $argv[1] ?? '.'; + +$linter = new Latte\Tools\Linter; +$latte = $linter->getEngine(); +// tady přidejte jednotlivá svá rozšíření +$latte->addExtension(/* ... */); -$path = $argv[1]; -$linter = new Latte\Tools\Linter(engine: $engine); $ok = $linter->scanDirectory($path); exit($ok ? 0 : 1); ``` +Alternativně můžete vlastní objekt `Latte\Engine` předat do Linteru: + +```php +$latte = new Latte\Engine; +// tady nakonfigurujeme objekt $latte +$linter = new Latte\Tools\Linter(engine: $latte); +``` + Načítání šablon z řetězce ========================= diff --git a/latte/cs/syntax.texy b/latte/cs/syntax.texy index 8ddca234ec..d90970c534 100644 --- a/latte/cs/syntax.texy +++ b/latte/cs/syntax.texy @@ -155,6 +155,20 @@ Nebo přímo na hodnotu (v kombinaci s tagem [`{=expr}`| https://latte.nette.org ``` +Dynamické HTML značky .{data-version:3.0.9} +=========================================== + +Latte podporuje dynamické HTML značky, které jsou užitečné, když potřebujete flexibilitu v názvech značek: + +```latte +Heading +``` + +Výše uvedený kód může například generovat `

Heading

` nebo `

Heading

` v závislosti na hodnotě proměnné `$level`. Dynamické HTML značky v Latte musí být vždy párové. Jejich alternativou je [n:tag |tags#n:tag]. + +Protože Latte je bezpečný šablonovací systém, kontroluje, zda je výsledný název značky platný a neobsahuje žádné nežádoucí nebo škodlivé hodnoty. Dále zajistí, že název koncové značky bude vždy stejný jako název otevírací značky. + + Komentáře ========= diff --git a/latte/cs/tags.texy b/latte/cs/tags.texy index e0cf7e30b6..343ffaa172 100644 --- a/latte/cs/tags.texy +++ b/latte/cs/tags.texy @@ -991,6 +991,8 @@ Pokud je `$heading === null`, vypíše se beze změny tag `

`. Jinak se změn

...

``` +Protože Latte je bezpečný šablonovací systém, kontroluje, zda je nový název značky platný a neobsahuje žádné nežádoucí nebo škodlivé hodnoty. + n:ifcontent ----------- diff --git a/latte/de/develop.texy b/latte/de/develop.texy index 5f99949089..a845db1fd3 100644 --- a/latte/de/develop.texy +++ b/latte/de/develop.texy @@ -271,19 +271,28 @@ Wenn Sie benutzerdefinierte Tags verwenden, erstellen Sie auch Ihren eigenen Lin #!/usr/bin/env php addExtension(/* ... */); +$path = $argv[1] ?? '.'; + +$linter = new Latte\Tools\Linter; +$latte = $linter->getEngine(); +// fügen Sie hier Ihre individuellen Erweiterungen hinzu +$latte->addExtension(/* ... */); -$path = $argv[1]; -$linter = new Latte\Tools\Linter(engine: $engine); $ok = $linter->scanDirectory($path); exit($ok ? 0 : 1); ``` +Alternativ können Sie dem Linter auch Ihr eigenes `Latte\Engine` Objekt übergeben: + +```php +$latte = new Latte\Engine; +// hier konfigurieren wir das $latte-Objekt +$linter = new Latte\Tools\Linter(engine: $latte); +``` + Laden von Templates aus einem String .[#toc-loading-templates-from-a-string] ============================================================================ diff --git a/latte/de/syntax.texy b/latte/de/syntax.texy index d86f0c4f5e..33a208a405 100644 --- a/latte/de/syntax.texy +++ b/latte/de/syntax.texy @@ -155,6 +155,20 @@ Oder direkt beim Wert (in Kombination mit [`{=expr}` | https://latte.nette.org/d ``` +Dynamische HTML-Tags .[#toc-dynamic-html-tags] +============================================== + +Latte unterstützt dynamische HTML-Tags, die nützlich sind, wenn Sie Flexibilität bei den Tag-Namen benötigen: + +```latte +Heading +``` + +Der obige Code kann zum Beispiel Folgendes erzeugen `

Heading

` oder `

Heading

` erzeugen, je nach dem Wert der Variablen `$level`. Dynamische HTML-Tags in Latte müssen immer gepaart sein. Ihre Alternative ist der [n:tag |tags#n:tag]. + +Da Latte ein sicheres Schablonensystem ist, prüft es, ob der resultierende Tag-Name gültig ist und keine unerwünschten oder bösartigen Werte enthält. Es stellt auch sicher, dass der Name des End-Tags immer mit dem Namen des Anfangs-Tags übereinstimmt. + + Kommentare .[#toc-comments] =========================== diff --git a/latte/de/tags.texy b/latte/de/tags.texy index e067725f42..67e8baecf9 100644 --- a/latte/de/tags.texy +++ b/latte/de/tags.texy @@ -991,6 +991,8 @@ Wenn `$heading === null`, wird das `

` Tag ohne Änderung gedruckt. Andernfal

...

``` +Da es sich bei Latte um ein sicheres Templating-System handelt, wird überprüft, ob der neue Tag-Name gültig ist und keine unerwünschten oder bösartigen Werte enthält. + n:ifcontent ----------- diff --git a/latte/el/develop.texy b/latte/el/develop.texy index 5d380b79ba..76342e9f87 100644 --- a/latte/el/develop.texy +++ b/latte/el/develop.texy @@ -274,16 +274,25 @@ vendor/bin/latte-lint // εισάγετε την πραγματική διαδρομή προς το αρχείο autoload.php require __DIR__ . '/vendor/autoload.php'; -$engine = new Latte\Engine; -// προσθέστε μεμονωμένες επεκτάσεις εδώ -$engine->addExtension(/* ... */); +$path = $argv[1] ?? '.'; + +$linter = new Latte\Tools\Linter; +$latte = $linter->getEngine(); +// προσθέστε τις μεμονωμένες επεκτάσεις σας εδώ +$latte->addExtension(/* ... */); -$path = $argv[1]; -$linter = new Latte\Tools\Linter(engine: $engine); $ok = $linter->scanDirectory($path); exit($ok ? 0 : 1); ``` +Εναλλακτικά, μπορείτε να περάσετε το δικό σας αντικείμενο `Latte\Engine` στον Linter: + +```php +$latte = new Latte\Engine; +// εδώ ρυθμίζουμε το αντικείμενο $latte +$linter = new Latte\Tools\Linter(engine: $latte); +``` + Φόρτωση προτύπων από μια συμβολοσειρά .[#toc-loading-templates-from-a-string] ============================================================================= diff --git a/latte/el/syntax.texy b/latte/el/syntax.texy index 35288cdaf6..8f36653703 100644 --- a/latte/el/syntax.texy +++ b/latte/el/syntax.texy @@ -155,6 +155,20 @@ n:attributes .[#toc-n-attributes] ``` +Δυναμικές ετικέτες HTML .[#toc-dynamic-html-tags] +================================================= + +Το Latte υποστηρίζει δυναμικές ετικέτες HTML, οι οποίες είναι χρήσιμες όταν χρειάζεστε ευελιξία στα ονόματα των ετικετών: + +```latte +Heading +``` + +Για παράδειγμα, ο παραπάνω κώδικας μπορεί να δημιουργήσει `

Heading

` ή `

Heading

` ανάλογα με την τιμή της μεταβλητής `$level`. Οι δυναμικές ετικέτες HTML στο Latte πρέπει πάντα να είναι ζευγαρωμένες. Η εναλλακτική τους είναι η [n:tag |tags#n:tag]. + +Επειδή το Latte είναι ένα ασφαλές σύστημα διαμόρφωσης προτύπων, ελέγχει ότι το όνομα της ετικέτας που προκύπτει είναι έγκυρο και δεν περιέχει ανεπιθύμητες ή κακόβουλες τιμές. Εξασφαλίζει επίσης ότι το όνομα της τελικής ετικέτας είναι πάντα το ίδιο με το όνομα της ετικέτας έναρξης. + + Σχόλια .[#toc-comments] ======================= diff --git a/latte/el/tags.texy b/latte/el/tags.texy index 05958f0e18..80acc64da8 100644 --- a/latte/el/tags.texy +++ b/latte/el/tags.texy @@ -991,6 +991,8 @@ n:tag .[#toc-n-tag]

...

``` +Επειδή το Latte είναι ένα ασφαλές σύστημα διαμόρφωσης προτύπων, ελέγχει ότι το όνομα της νέας ετικέτας είναι έγκυρο και δεν περιέχει ανεπιθύμητες ή κακόβουλες τιμές. + n:ifcontent .[#toc-n-ifcontent] ------------------------------- diff --git a/latte/en/develop.texy b/latte/en/develop.texy index 87ecc92636..d3b27885de 100644 --- a/latte/en/develop.texy +++ b/latte/en/develop.texy @@ -274,16 +274,25 @@ If you use custom tags, also create your customized Linter, e.g. `custom-latte-l // enter the actual path to the autoload.php file require __DIR__ . '/vendor/autoload.php'; -$engine = new Latte\Engine; -// add individual extensions here -$engine->addExtension(/* ... */); +$path = $argv[1] ?? '.'; + +$linter = new Latte\Tools\Linter; +$latte = $linter->getEngine(); +// add your individual extensions here +$latte->addExtension(/* ... */); -$path = $argv[1]; -$linter = new Latte\Tools\Linter(engine: $engine); $ok = $linter->scanDirectory($path); exit($ok ? 0 : 1); ``` +Alternatively, you can pass your own `Latte\Engine` object to the Linter: + +```php +$latte = new Latte\Engine; +// here we configure the $latte object +$linter = new Latte\Tools\Linter(engine: $latte); +``` + Loading Templates from a String =============================== diff --git a/latte/en/syntax.texy b/latte/en/syntax.texy index 7358007478..17841ecd58 100644 --- a/latte/en/syntax.texy +++ b/latte/en/syntax.texy @@ -155,6 +155,20 @@ Or directly on value (in combination with [`{=expr}`| https://latte.nette.org/en ``` +Dynamic HTML Tags +================= + +Latte supports dynamic HTML tags, which are useful when you need flexibility in tag names: + +```latte +Heading +``` + +For example, the code above can generate `

Heading

` or `

Heading

` depending on the value of the variable `$level`. Dynamic HTML tags in Latte must always be paired. Their alternative is the [n:tag |tags#n:tag]. + +Because Latte is a secure templating system, it checks that the resulting tag name is valid and contains no unwanted or malicious values. It also ensures that the end tag name is always the same as the opening tag name. + + Comments ======== diff --git a/latte/en/tags.texy b/latte/en/tags.texy index fcecb2a3c1..08f4d516db 100644 --- a/latte/en/tags.texy +++ b/latte/en/tags.texy @@ -991,6 +991,8 @@ If `$heading === null`, the `

` tag is printed without change. Otherwise, the

...

``` +Because Latte is a secure templating system, it checks that the new tag name is valid and does not contain any unwanted or malicious values. + n:ifcontent ----------- diff --git a/latte/es/develop.texy b/latte/es/develop.texy index 83802ea072..e925b76524 100644 --- a/latte/es/develop.texy +++ b/latte/es/develop.texy @@ -274,16 +274,25 @@ Si utiliza etiquetas personalizadas, cree también su Linter personalizado, por // introduzca la ruta real al archivo autoload.php require __DIR__ . '/vendor/autoload.php'; -$engine = new Latte\Engine; -// añada aquí las extensiones individuales -$engine->addExtension(/* ... */); +$path = $argv[1] ?? '.'; + +$linter = new Latte\Tools\Linter; +$latte = $linter->getEngine(); +// añada aquí sus extensiones individuales +$latte->addExtension(/* ... */); -$path = $argv[1]; -$linter = new Latte\Tools\Linter(engine: $engine); $ok = $linter->scanDirectory($path); exit($ok ? 0 : 1); ``` +Alternativamente, puede pasar su propio objeto `Latte\Engine` al Linter: + +```php +$latte = new Latte\Engine; +// aquí configuramos el objeto $latte +$linter = new Latte\Tools\Linter(engine: $latte); +``` + Carga de plantillas desde una cadena .[#toc-loading-templates-from-a-string] ============================================================================ diff --git a/latte/es/syntax.texy b/latte/es/syntax.texy index 54e1ea2fcc..8adcf5e086 100644 --- a/latte/es/syntax.texy +++ b/latte/es/syntax.texy @@ -155,6 +155,20 @@ O directamente sobre el valor (en combinación con [`{=expr}` | https://latte.ne ``` +Etiquetas HTML dinámicas .[#toc-dynamic-html-tags] +================================================== + +Latte soporta etiquetas HTML dinámicas, que son útiles cuando se necesita flexibilidad en los nombres de las etiquetas: + +```latte +Heading +``` + +Por ejemplo, el código anterior puede generar `

Heading

` o `

Heading

` en función del valor de la variable `$level`. Las etiquetas HTML dinámicas en Latte deben ir siempre emparejadas. Su alternativa es la [n:tag |tags#n:tag]. + +Como Latte es un sistema de plantillas seguro, comprueba que el nombre de la etiqueta resultante sea válido y no contenga valores no deseados o maliciosos. También se asegura de que el nombre de la etiqueta final sea siempre el mismo que el de la etiqueta inicial. + + Comentarios .[#toc-comments] ============================ diff --git a/latte/es/tags.texy b/latte/es/tags.texy index 26ab3fbe9d..3e2381c8fe 100644 --- a/latte/es/tags.texy +++ b/latte/es/tags.texy @@ -991,6 +991,8 @@ Si `$heading === null`, la etiqueta `

` se imprime sin cambios. De lo contrar

...

``` +Como Latte es un sistema de plantillas seguro, comprueba que el nuevo nombre de la etiqueta sea válido y no contenga valores no deseados o maliciosos. + n:ifcontent .[#toc-n-ifcontent] ------------------------------- diff --git a/latte/fr/develop.texy b/latte/fr/develop.texy index 4ba666fd93..e444e942ed 100644 --- a/latte/fr/develop.texy +++ b/latte/fr/develop.texy @@ -271,19 +271,28 @@ Si vous utilisez des balises personnalisées, créez également votre Linter per #!/usr/bin/env php addExtension(/* ... */); +$path = $argv[1] ?? '.'; + +$linter = new Latte\Tools\Linter; +$latte = $linter->getEngine(); +// ajoutez vos extensions individuelles ici +$latte->addExtension(/* ... */); -$path = $argv[1]; -$linter = new Latte\Tools\Linter(engine: $engine); $ok = $linter->scanDirectory($path); exit($ok ? 0 : 1); ``` +Vous pouvez également transmettre votre propre objet `Latte\Engine` au Linter : + +```php +$latte = new Latte\Engine; +// nous configurons ici l'objet $latte +$linter = new Latte\Tools\Linter(engine: $latte); +``` + Chargement de modèles à partir d'une chaîne .[#toc-loading-templates-from-a-string] =================================================================================== diff --git a/latte/fr/syntax.texy b/latte/fr/syntax.texy index 7c7d182727..eda154bdf5 100644 --- a/latte/fr/syntax.texy +++ b/latte/fr/syntax.texy @@ -155,6 +155,20 @@ Ou directement sur la valeur (en combinaison avec [`{=expr}` | https://latte.net ``` +Balises HTML dynamiques .[#toc-dynamic-html-tags] +================================================= + +Latte supporte les balises HTML dynamiques, qui sont utiles lorsque vous avez besoin de flexibilité dans les noms de balises : + +```latte +Heading +``` + +Par exemple, le code ci-dessus peut générer `

Heading

` ou `

Heading

` en fonction de la valeur de la variable `$level`. Les balises HTML dynamiques dans Latte doivent toujours être appariées. Leur alternative est la [balise n:tag |tags#n:tag]. + +Latte étant un système de création de modèles sécurisé, il vérifie que le nom de balise résultant est valide et ne contient pas de valeurs indésirables ou malveillantes. Il s'assure également que le nom de la balise de fin est toujours le même que le nom de la balise d'ouverture. + + Commentaires .[#toc-comments] ============================= diff --git a/latte/fr/tags.texy b/latte/fr/tags.texy index b4f22df9c9..f884a996fd 100644 --- a/latte/fr/tags.texy +++ b/latte/fr/tags.texy @@ -991,6 +991,8 @@ Si `$heading === null`, la balise `

` est imprimé sans changement. Sinon, le

...

``` +Latte étant un système de templates sécurisé, il vérifie que le nouveau nom de balise est valide et ne contient pas de valeurs indésirables ou malveillantes. + n:ifcontent ----------- diff --git a/latte/hu/develop.texy b/latte/hu/develop.texy index 15d8116068..80a77b993c 100644 --- a/latte/hu/develop.texy +++ b/latte/hu/develop.texy @@ -274,16 +274,25 @@ Ha egyéni címkéket használ, hozza létre az egyéni Lintert is, például `c // adja meg az autoload.php fájl tényleges elérési útvonalát require __DIR__ . '/vendor/autoload.php'; -$engine = new Latte\Engine; -// egyedi kiterjesztések hozzáadása itt -$engine->addExtension(/* ... */); +$path = $argv[1] ?? '.'; + +$linter = new Latte\Tools\Linter; +$latte = $linter->getEngine(); +// itt adja hozzá az egyéni kiterjesztéseket +$latte->addExtension(/* ... */); -$path = $argv[1]; -$linter = new Latte\Tools\Linter(engine: $engine); $ok = $linter->scanDirectory($path); exit($ok ? 0 : 1); ``` +Alternatívaként átadhatja saját `Latte\Engine` objektumát is a Linter-nek: + +```php +$latte = new Latte\Engine; +// itt konfiguráljuk a $latte objektumot +$linter = new Latte\Tools\Linter(engine: $latte); +``` + Sablonok betöltése egy karakterláncból .[#toc-loading-templates-from-a-string] ============================================================================== diff --git a/latte/hu/syntax.texy b/latte/hu/syntax.texy index fb7a5ba3aa..f0fdbbae0e 100644 --- a/latte/hu/syntax.texy +++ b/latte/hu/syntax.texy @@ -155,6 +155,20 @@ Vagy közvetlenül az értékre (a [`{=expr}` | https://latte.nette.org/hu/tags# ``` +Dinamikus HTML címkék .[#toc-dynamic-html-tags] +=============================================== + +A Latte támogatja a dinamikus HTML címkéket, amelyek akkor hasznosak, ha a címkék nevének rugalmasságára van szükség: + +```latte +Heading +``` + +Például a fenti kód képes generálni `

Heading

` vagy `

Heading

` a `$level` változó értékétől függően. A Latte dinamikus HTML-címkéket mindig párosítani kell. Alternatívájuk az [n:tag |tags#n:tag]. + +Mivel a Latte egy biztonságos templating rendszer, ellenőrzi, hogy a kapott tag neve érvényes-e, és nem tartalmaz-e nem kívánt vagy rosszindulatú értékeket. Azt is biztosítja, hogy a végcímke neve mindig megegyezik a nyitócímke nevével. + + Hozzászólások .[#toc-comments] ============================== diff --git a/latte/hu/tags.texy b/latte/hu/tags.texy index d718df8e62..ca5930c18c 100644 --- a/latte/hu/tags.texy +++ b/latte/hu/tags.texy @@ -991,6 +991,8 @@ Ha a `$heading === null`, a `

` címke változatlanul kiírásra kerül. Elle

...

``` +Mivel a Latte egy biztonságos templating rendszer, ellenőrzi, hogy az új tag neve érvényes-e, és nem tartalmaz-e nem kívánt vagy rosszindulatú értékeket. + n:ifcontent .[#toc-n-ifcontent] ------------------------------- diff --git a/latte/it/develop.texy b/latte/it/develop.texy index 4f9fc093a1..39e2d89dab 100644 --- a/latte/it/develop.texy +++ b/latte/it/develop.texy @@ -274,16 +274,25 @@ Se si usano tag personalizzati, creare anche un Linter personalizzato, ad esempi // inserire il percorso effettivo del file autoload.php require __DIR__ . '/vendor/autoload.php'; -$engine = new Latte\Engine; -// aggiungere qui le singole estensioni -$engine->addExtension(/* ... */); +$path = $argv[1] ?? '.'; + +$linter = new Latte\Tools\Linter; +$latte = $linter->getEngine(); +// aggiungere qui le estensioni individuali +$latte->addExtension(/* ... */); -$path = $argv[1]; -$linter = new Latte\Tools\Linter(engine: $engine); $ok = $linter->scanDirectory($path); exit($ok ? 0 : 1); ``` +In alternativa, è possibile passare il proprio oggetto `Latte\Engine` a Linter: + +```php +$latte = new Latte\Engine; +// Qui configuriamo l'oggetto $latte +$linter = new Latte\Tools\Linter(engine: $latte); +``` + Caricare modelli da una stringa .[#toc-loading-templates-from-a-string] ======================================================================= diff --git a/latte/it/syntax.texy b/latte/it/syntax.texy index c96747b66d..eef05b2ef3 100644 --- a/latte/it/syntax.texy +++ b/latte/it/syntax.texy @@ -155,6 +155,20 @@ O direttamente sul valore (in combinazione con [`{=expr}` | https://latte.nette. ``` +Tag HTML dinamici .[#toc-dynamic-html-tags] +=========================================== + +Latte supporta i tag HTML dinamici, utili quando si ha bisogno di flessibilità nei nomi dei tag: + +```latte +Heading +``` + +Ad esempio, il codice qui sopra può generare `

Heading

` o `

Heading

` a seconda del valore della variabile `$level`. I tag HTML dinamici in Latte devono sempre essere accoppiati. L'alternativa è il [n:tag |tags#n:tag]. + +Poiché Latte è un sistema di template sicuro, controlla che il nome del tag risultante sia valido e non contenga valori indesiderati o dannosi. Inoltre, garantisce che il nome del tag finale sia sempre uguale a quello del tag di apertura. + + Commenti .[#toc-comments] ========================= diff --git a/latte/it/tags.texy b/latte/it/tags.texy index 3411ee7656..8748ff6adc 100644 --- a/latte/it/tags.texy +++ b/latte/it/tags.texy @@ -991,6 +991,8 @@ Se `$heading === null`, il tag `

` viene stampato senza modifiche. Altrimenti

...

``` +Poiché Latte è un sistema di template sicuro, controlla che il nome del nuovo tag sia valido e non contenga valori indesiderati o dannosi. + n:ifcontent .[#toc-n-ifcontent] ------------------------------- diff --git a/latte/ja/develop.texy b/latte/ja/develop.texy index 6ce5a51c8d..3a63e03253 100644 --- a/latte/ja/develop.texy +++ b/latte/ja/develop.texy @@ -271,18 +271,27 @@ vendor/bin/latte-lint #!/usr/bin/env php addExtension(/* ... */); +$path = $argv[1] ?? '.'; + +$linter = new Latte\Tools\Linter; +$latte = $linter->getEngine(); +//$latte->addExtension(/* ... */); -$path = $argv[1]; -$linter = new Latte\Tools\Linter(engine: $engine); $ok = $linter->scanDirectory($path); -exit($ok ? 0 : 1); -``` +exit($ok ? 0 : 1);``` + +あるいは、独自の`Latte\Engine` オブジェクトを Linter に渡すこともできます: + +```php +$latte = new Latte\Engine; +// ここでは、$latteオブジェクトを設定します。 + +$linter = new Latte\Tools\Linter(engine: $latte);``` 文字列からテンプレートを読み込む .[#toc-loading-templates-from-a-string] diff --git a/latte/ja/syntax.texy b/latte/ja/syntax.texy index ff6904aeaa..6aa80cb7a5 100644 --- a/latte/ja/syntax.texy +++ b/latte/ja/syntax.texy @@ -155,6 +155,20 @@ Latteでは、パイプ記号を使った記法でフィルタを呼び出すこ ``` +ダイナミックHTMLタグ .[#toc-dynamic-html-tags] +====================================== + +Latteは動的HTMLタグをサポートしており、タグ名に柔軟性が必要な場合に便利です: + +```latte +Heading +``` + +例えば、上記のコードでは `

Heading

`または `

Heading

``$level`を生成することができる。LatteのダイナミックHTMLタグは常にペアでなければなりません。その代わりとなるのが[n:tag |tags#n:tag]です。 + +Latteは安全なテンプレートシステムであるため、生成されるタグ名が有効で、不要な値や悪意のある値を含まないことをチェックします。また、終了タグ名が常に開始タグ名と同じであることを保証します。 + + コメント .[#toc-comments] ===================== diff --git a/latte/ja/tags.texy b/latte/ja/tags.texy index c543dd89bc..b01cdb18d9 100644 --- a/latte/ja/tags.texy +++ b/latte/ja/tags.texy @@ -991,6 +991,8 @@ n:タグ .[#toc-n-tag]

...

``` +Latteは安全なテンプレートシステムなので、新しいタグ名が有効で、不要な値や悪意のある値が含まれていないことをチェックします。 + n:ifcontent .[#toc-n-ifcontent] ------------------------------- diff --git a/latte/pl/develop.texy b/latte/pl/develop.texy index bb2dbd5253..99c9975f81 100644 --- a/latte/pl/develop.texy +++ b/latte/pl/develop.texy @@ -274,16 +274,25 @@ Jeśli używasz niestandardowych znaczników, utwórz również swój niestandar // wprowadź rzeczywistą ścieżkę do pliku autoload.php require __DIR__ . '/vendor/autoload.php'; -$engine = new Latte\Engine; -// dodaj tutaj indywidualne rozszerzenia -$engine->addExtension(/* ... */); +$path = $argv[1] ?? '.'; + +$linter = new Latte\Tools\Linter; +$latte = $linter->getEngine(); +// dodaj tutaj swoje indywidualne rozszerzenia +$latte->addExtension(/* ... */); -$path = $argv[1]; -$linter = new Latte\Tools\Linter(engine: $engine); $ok = $linter->scanDirectory($path); exit($ok ? 0 : 1); ``` +Alternatywnie, można przekazać własny obiekt `Latte\Engine` do aplikacji Linter: + +```php +$latte = new Latte\Engine; +// tutaj konfigurujemy obiekt $latte +$linter = new Latte\Tools\Linter(engine: $latte); +``` + Ładowanie szablonów z łańcucha .[#toc-loading-templates-from-a-string] ====================================================================== diff --git a/latte/pl/syntax.texy b/latte/pl/syntax.texy index 60e450adc9..106fc68597 100644 --- a/latte/pl/syntax.texy +++ b/latte/pl/syntax.texy @@ -155,6 +155,20 @@ Lub bezpośrednio na wartość (w połączeniu z tagiem [`{=expr}` | https://lat ``` +Dynamiczne znaczniki HTML .[#toc-dynamic-html-tags] +=================================================== + +Latte obsługuje dynamiczne znaczniki HTML, które są przydatne, gdy potrzebujesz elastyczności w nazwach znaczników: + +```latte +Heading +``` + +Na przykład, powyższy kod może wygenerować `

Heading

` lub `

Heading

` w zależności od wartości zmiennej `$level`. Dynamiczne znaczniki HTML w Latte muszą być zawsze sparowane. Ich alternatywą jest [n:tag |tags#n:tag]. + +Ponieważ Latte jest bezpiecznym systemem szablonów, sprawdza, czy wynikowa nazwa tagu jest prawidłowa i nie zawiera niepożądanych lub złośliwych wartości. Zapewnia również, że końcowa nazwa tagu jest zawsze taka sama jak nazwa tagu otwierającego. + + Uwagi .[#toc-comments] ====================== diff --git a/latte/pl/tags.texy b/latte/pl/tags.texy index a37e64df2e..42a72ab36b 100644 --- a/latte/pl/tags.texy +++ b/latte/pl/tags.texy @@ -991,6 +991,8 @@ Jeśli jest to `$heading === null`, tag jest drukowany bez zmian. `

`. W prze

...

``` +Ponieważ Latte jest bezpiecznym systemem szablonów, sprawdza, czy nowa nazwa tagu jest poprawna i nie zawiera żadnych niepożądanych lub złośliwych wartości. + n:ifcontent .[#toc-n-ifcontent] ------------------------------- diff --git a/latte/pt/develop.texy b/latte/pt/develop.texy index 88d9e11d82..85ed5ef920 100644 --- a/latte/pt/develop.texy +++ b/latte/pt/develop.texy @@ -274,16 +274,25 @@ Se você usa etiquetas personalizadas, crie também seu Linter personalizado, po // digite o caminho real para o arquivo autoload.php require __DIR__ . '/vendor/autoload.php'; -$engine = new Latte\Engine; -// adicione extensões individuais aqui -$engine->addExtension(/* ... */); +$path = $argv[1] ?? '.'; + +$linter = new Latte\Tools\Linter; +$latte = $linter->getEngine(); +// adicione suas extensões individuais aqui +$latte->addExtension(/* ... */); -$path = $argv[1]; -$linter = new Latte\Tools\Linter(engine: $engine); $ok = $linter->scanDirectory($path); exit($ok ? 0 : 1); ``` +Como alternativa, você pode passar seu próprio objeto `Latte\Engine` para o Linter: + +```php +$latte = new Latte\Engine; +// Aqui configuramos o objeto $latte +$linter = new Latte\Tools\Linter(engine: $latte); +``` + Carregando modelos a partir de uma corda .[#toc-loading-templates-from-a-string] ================================================================================ diff --git a/latte/pt/syntax.texy b/latte/pt/syntax.texy index 17a85222fd..47772ddec6 100644 --- a/latte/pt/syntax.texy +++ b/latte/pt/syntax.texy @@ -155,6 +155,20 @@ Ou diretamente sobre o valor (em combinação com [`{=expr}` | https://latte.net ``` +Tags HTML dinâmicas .[#toc-dynamic-html-tags] +============================================= + +O Latte oferece suporte a tags HTML dinâmicas, que são úteis quando você precisa de flexibilidade nos nomes das tags: + +```latte +Heading +``` + +Por exemplo, o código acima pode gerar `

Heading

` ou `

Heading

` dependendo do valor da variável `$level`. As tags HTML dinâmicas no Latte devem ser sempre emparelhadas. Sua alternativa é a [n:tag |tags#n:tag]. + +Como o Latte é um sistema de modelos seguro, ele verifica se o nome da tag resultante é válido e não contém valores indesejados ou maliciosos. Ele também garante que o nome da tag final seja sempre o mesmo que o nome da tag de abertura. + + Comentários .[#toc-comments] ============================ diff --git a/latte/pt/tags.texy b/latte/pt/tags.texy index ded11b8ed1..e61802b29a 100644 --- a/latte/pt/tags.texy +++ b/latte/pt/tags.texy @@ -991,6 +991,8 @@ Se `$heading === null`, o `

` é impresso sem alterações. Caso contrário,

...

``` +Como o Latte é um sistema de modelos seguro, ele verifica se o novo nome da tag é válido e não contém valores indesejados ou maliciosos. + n:secontente .[#toc-n-ifcontent] -------------------------------- diff --git a/latte/ro/develop.texy b/latte/ro/develop.texy index 08a790a567..9f63037d6a 100644 --- a/latte/ro/develop.texy +++ b/latte/ro/develop.texy @@ -274,16 +274,25 @@ Dacă utilizați etichete personalizate, creați și Linterul personalizat, de e // introduceți calea reală către fișierul autoload.php require __DIR__ . '/vendor/autoload.php'; -$engine = new Latte\Engine; -// adăugați extensii individuale aici -$engine->addExtension(/* ... */); +$path = $argv[1] ?? '.'; + +$linter = new Latte\Tools\Linter; +$latte = $linter->getEngine(); +// adăugați extensiile individuale aici +$latte->addExtension(/* ... */); -$path = $argv[1]; -$linter = new Latte\Tools\Linter(engine: $engine); $ok = $linter->scanDirectory($path); exit($ok ? 0 : 1); ``` +Alternativ, puteți transmite propriul obiect `Latte\Engine` către Linter: + +```php +$latte = new Latte\Engine; +// aici configurăm obiectul $latte +$linter = new Latte\Tools\Linter(engine: $latte); +``` + Încărcarea șabloanelor dintr-un șir de caractere .[#toc-loading-templates-from-a-string] ======================================================================================== diff --git a/latte/ro/syntax.texy b/latte/ro/syntax.texy index 77ba5ec1f0..baefef14b5 100644 --- a/latte/ro/syntax.texy +++ b/latte/ro/syntax.texy @@ -155,6 +155,20 @@ Sau direct pe valoare (în combinație cu [`{=expr}` | https://latte.nette.org/r ``` +Etichete HTML dinamice .[#toc-dynamic-html-tags] +================================================ + +Latte acceptă etichete HTML dinamice, care sunt utile atunci când aveți nevoie de flexibilitate în ceea ce privește numele etichetelor: + +```latte +Heading +``` + +De exemplu, codul de mai sus poate genera `

Heading

` sau `

Heading

` în funcție de valoarea variabilei `$level`. Etichetele HTML dinamice din Latte trebuie să fie întotdeauna asociate. Alternativa lor este [n:tag |tags#n:tag]. + +Deoarece Latte este un sistem securizat de creare de șabloane, acesta verifică dacă numele tag-ului rezultat este valid și nu conține valori nedorite sau rău intenționate. De asemenea, se asigură că numele tag-ului final este întotdeauna același cu numele tag-ului de deschidere. + + Comentarii .[#toc-comments] =========================== diff --git a/latte/ro/tags.texy b/latte/ro/tags.texy index 12fbf21767..ca997cafc5 100644 --- a/latte/ro/tags.texy +++ b/latte/ro/tags.texy @@ -991,6 +991,8 @@ Dacă `$heading === null`, atributul `

` este tipărit fără modificări. Î

...

``` +Deoarece Latte este un sistem de modelare securizat, acesta verifică dacă noul nume de etichetă este valid și nu conține valori nedorite sau rău intenționate. + n:ifcontent .[#toc-n-ifcontent] ------------------------------- diff --git a/latte/ru/develop.texy b/latte/ru/develop.texy index d252d0bdd3..bba7e01173 100644 --- a/latte/ru/develop.texy +++ b/latte/ru/develop.texy @@ -274,14 +274,23 @@ vendor/bin/latte-lint // введите фактический путь к файлу autoload.php require __DIR__ . '/vendor/autoload.php'; -$engine = new Latte\Engine; -// добавить сюда отдельные расширения -$engine->addExtension(/* ... */); +$path = $argv[1] ?? '.'; + +$linter = new Latte\Tools\Linter; +$latte = $linter->getEngine(); +// добавьте сюда свои индивидуальные расширения +$latte->addExtension(/* ... */); -$path = $argv[1]; -$linter = new Latte\Tools\Linter(engine: $engine); $ok = $linter->scanDirectory($path); -exit($ok ? 0: 1); +exit($ok ? 0 : 1); +``` + +В качестве альтернативы можно передать Линтеру свой собственный объект `Latte\Engine`: + +```php +$latte = new Latte\Engine; +// здесь мы настраиваем объект $latte +$linter = new Latte\Tools\Linter(engine: $latte); ``` diff --git a/latte/ru/syntax.texy b/latte/ru/syntax.texy index 436d486851..8f30d3b53a 100644 --- a/latte/ru/syntax.texy +++ b/latte/ru/syntax.texy @@ -155,6 +155,20 @@ Latte позволяет вызывать фильтры с помощью зн ``` +Динамические HTML-теги .[#toc-dynamic-html-tags] +================================================ + +Latte поддерживает динамические HTML-теги, которые полезны, когда требуется гибкость в названиях тегов: + +```latte +Heading +``` + +Например, приведенный выше код может генерировать `

Heading

` или `

Heading

` в зависимости от значения переменной `$level`. Динамические HTML-теги в Latte всегда должны быть парными. Их альтернативой является [n:tag |tags#n:tag]. + +Поскольку Latte является безопасной системой шаблонизации, она проверяет, что результирующее имя тега является корректным и не содержит нежелательных или вредоносных значений. Также проверяется, что имя конечного тега всегда совпадает с именем открывающего тега. + + Комментарии .[#toc-comments] ============================ diff --git a/latte/ru/tags.texy b/latte/ru/tags.texy index 5b12995d91..9a1d840b66 100644 --- a/latte/ru/tags.texy +++ b/latte/ru/tags.texy @@ -991,6 +991,8 @@ n:tag

...

``` +Поскольку Latte является безопасной системой шаблонизации, она проверяет, что имя нового тега является корректным и не содержит никаких нежелательных или вредоносных значений. + n:ifcontent .[#toc-n-ifcontent] ------------------------------- diff --git a/latte/sl/develop.texy b/latte/sl/develop.texy index 3eee56c049..7df0221c10 100644 --- a/latte/sl/develop.texy +++ b/latte/sl/develop.texy @@ -274,16 +274,25 @@ S parametrom `--strict` lahko aktivirate [strogi način|#strict mode]. // vnesite dejansko pot do datoteke autoload.php require __DIR__ . '/vendor/autoload.php'; -$engine = new Latte\Engine; -// tukaj dodajte posamezne razširitve -$engine->addExtension(/* ... */); +$path = $argv[1] ?? '.'; + +$linter = new Latte\Tools\Linter; +$latte = $linter->getEngine(); +// tukaj dodajte svoje posamezne razširitve +$latte->addExtension(/* ... */); -$path = $argv[1]; -$linter = new Latte\Tools\Linter(engine: $engine); $ok = $linter->scanDirectory($path); exit($ok ? 0 : 1); ``` +Druga možnost je, da programu Linter posredujete svoj predmet `Latte\Engine`: + +```php +$latte = new Latte\Engine; +// tukaj konfiguriramo predmet $latte +$linter = new Latte\Tools\Linter(engine: $latte); +``` + Nalaganje predlog iz niza .[#toc-loading-templates-from-a-string] ================================================================= diff --git a/latte/sl/syntax.texy b/latte/sl/syntax.texy index 64b197c208..0896381aa7 100644 --- a/latte/sl/syntax.texy +++ b/latte/sl/syntax.texy @@ -155,6 +155,20 @@ Ali neposredno na vrednosti (v kombinaciji z [`{=expr}` | https://latte.nette.or ``` +Dinamične oznake HTML .[#toc-dynamic-html-tags] +=============================================== + +Latte podpira dinamične oznake HTML, ki so uporabne, kadar je potrebna prilagodljivost imen oznak: + +```latte +Heading +``` + +Zgornja koda lahko na primer ustvari `

Heading

` ali `

Heading

` odvisno od vrednosti spremenljivke `$level`. Dinamične oznake HTML v Latte morajo biti vedno v paru. Njihova alternativa je [n:tag |tags#n:tag]. + +Ker je Latte varen sistem za oblikovanje predlog, preveri, ali je dobljeno ime oznake veljavno in ne vsebuje neželenih ali zlonamernih vrednosti. Prav tako zagotavlja, da je končno ime oznake vedno enako začetnemu imenu oznake. + + Komentarji .[#toc-comments] =========================== diff --git a/latte/sl/tags.texy b/latte/sl/tags.texy index c619c4a3ff..1e52d9acf5 100644 --- a/latte/sl/tags.texy +++ b/latte/sl/tags.texy @@ -991,6 +991,8 @@ Atribut `n:tag` lahko dinamično spremeni ime elementa HTML.

...

``` +Ker je Latte varen sistem za oblikovanje predlog, preveri, ali je ime nove oznake veljavno in ne vsebuje neželenih ali zlonamernih vrednosti. + n:ifcontent .[#toc-n-ifcontent] ------------------------------- diff --git a/latte/tr/develop.texy b/latte/tr/develop.texy index d1c0485531..89515279b0 100644 --- a/latte/tr/develop.texy +++ b/latte/tr/develop.texy @@ -274,16 +274,25 @@ vendor/bin/latte-lint // autoload.php dosyasının gerçek yolunu girin require __DIR__ . '/vendor/autoload.php'; -$engine = new Latte\Engine; -// bireysel uzantıları buraya ekleyin -$engine->addExtension(/* ... */); +$path = $argv[1] ?? '.'; + +$linter = new Latte\Tools\Linter; +$latte = $linter->getEngine(); +// bireysel uzantılarınızı buraya ekleyin +$latte->addExtension(/* ... */); -$path = $argv[1]; -$linter = new Latte\Tools\Linter(engine: $engine); $ok = $linter->scanDirectory($path); exit($ok ? 0 : 1); ``` +Alternatif olarak, kendi `Latte\Engine` nesnenizi Linter'a aktarabilirsiniz: + +```php +$latte = new Latte\Engine; +// burada $latte nesnesini yapılandırıyoruz +$linter = new Latte\Tools\Linter(engine: $latte); +``` + Dizeden Şablon Yükleme .[#toc-loading-templates-from-a-string] ============================================================== diff --git a/latte/tr/syntax.texy b/latte/tr/syntax.texy index 7877c39232..6e2b0e4925 100644 --- a/latte/tr/syntax.texy +++ b/latte/tr/syntax.texy @@ -155,6 +155,20 @@ Veya doğrudan değer üzerinde (ile birlikte [`{=expr}` | https://latte.nette.o ``` +Dinamik HTML Etiketleri .[#toc-dynamic-html-tags] +================================================= + +Latte, etiket adlarında esnekliğe ihtiyaç duyduğunuzda yararlı olan dinamik HTML etiketlerini destekler: + +```latte +Heading +``` + +Örneğin, yukarıdaki kod şunları üretebilir `

Heading

` veya `

Heading

` değişkeninin değerine bağlı olarak `$level`. Latte'deki dinamik HTML etiketleri her zaman eşleştirilmelidir. Alternatifleri [n:tag |tags#n:tag]. + +Latte güvenli bir şablonlama sistemi olduğundan, ortaya çıkan etiket adının geçerli olup olmadığını ve istenmeyen veya kötü amaçlı değerler içermediğini kontrol eder. Ayrıca, son etiket adının her zaman açılış etiketi adıyla aynı olmasını sağlar. + + Yorumlar .[#toc-comments] ========================= diff --git a/latte/tr/tags.texy b/latte/tr/tags.texy index d724a901db..9639ca566a 100644 --- a/latte/tr/tags.texy +++ b/latte/tr/tags.texy @@ -991,6 +991,8 @@ Eğer `$heading === null`, ise `

` etiketi değiştirilmeden yazdırılır. A

...

``` +Latte güvenli bir şablonlama sistemi olduğundan, yeni etiket adının geçerli olup olmadığını ve istenmeyen veya kötü amaçlı değerler içermediğini kontrol eder. + n:ifcontent .[#toc-n-ifcontent] ------------------------------- diff --git a/latte/uk/develop.texy b/latte/uk/develop.texy index bf30c26614..a41c7a5d0b 100644 --- a/latte/uk/develop.texy +++ b/latte/uk/develop.texy @@ -271,19 +271,28 @@ vendor/bin/latte-lint #!/usr/bin/env php addExtension(/* ... */); +$path = $argv[1] ?? '.'; + +$linter = new Latte\Tools\Linter; +$latte = $linter->getEngine(); +// додайте тут свої індивідуальні розширення +$latte->addExtension(/* ... */); -$path = $argv[1]; -$linter = new Latte\Tools\Linter(engine: $engine); $ok = $linter->scanDirectory($path); exit($ok ? 0 : 1); ``` +Крім того, ви можете передати лінтеру власний об'єкт `Latte\Engine`: + +```php +$latte = new Latte\Engine; +// тут ми налаштовуємо об'єкт $latte +$linter = new Latte\Tools\Linter(engine: $latte); +``` + Завантаження шаблонів з рядка .[#toc-loading-templates-from-a-string] ===================================================================== diff --git a/latte/uk/syntax.texy b/latte/uk/syntax.texy index d8b174c598..b1636f38ba 100644 --- a/latte/uk/syntax.texy +++ b/latte/uk/syntax.texy @@ -155,6 +155,20 @@ Latte дозволяє викликати фільтри за допомогою ``` +Динамічні теги HTML .[#toc-dynamic-html-tags] +============================================= + +Latte підтримує динамічні HTML-теги, які корисні, коли вам потрібна гнучкість у назвах тегів: + +```latte +Heading +``` + +Наприклад, код вище може згенерувати `

Heading

` або `

Heading

` в залежності від значення змінної `$level`. Динамічні HTML-теги в Latte завжди повинні бути парними. Їх альтернативою є [n:tag |tags#n:tag]. + +Оскільки Latte є безпечною системою шаблонів, вона перевіряє, що результуюче ім'я тегу є дійсним і не містить небажаних або шкідливих значень. Вона також гарантує, що ім'я кінцевого тегу завжди збігається з ім'ям початкового тегу. + + Коментарі .[#toc-comments] ========================== diff --git a/latte/uk/tags.texy b/latte/uk/tags.texy index 4fe83f6b5a..5904f30aa8 100644 --- a/latte/uk/tags.texy +++ b/latte/uk/tags.texy @@ -991,6 +991,8 @@ n:tag .[#toc-n-tag]

...

``` +Оскільки Latte - це безпечна система шаблонів, вона перевіряє, що нове ім'я тегу є дійсним і не містить небажаних або шкідливих значень. + n:ifcontent .[#toc-n-ifcontent] ------------------------------- From 3362e5d76260ce759130f8a26763dc5d82226936 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 12 Sep 2023 08:05:03 +0200 Subject: [PATCH 003/137] filesystem: link to Finder --- utils/bg/filesystem.texy | 2 ++ utils/cs/filesystem.texy | 4 +++- utils/de/filesystem.texy | 2 ++ utils/el/filesystem.texy | 2 ++ utils/en/filesystem.texy | 2 ++ utils/es/filesystem.texy | 2 ++ utils/fr/filesystem.texy | 2 ++ utils/hu/filesystem.texy | 2 ++ utils/it/filesystem.texy | 2 ++ utils/pl/filesystem.texy | 2 ++ utils/pt/filesystem.texy | 2 ++ utils/ro/filesystem.texy | 2 ++ utils/ru/filesystem.texy | 2 ++ utils/sl/filesystem.texy | 2 ++ utils/tr/filesystem.texy | 2 ++ utils/uk/filesystem.texy | 2 ++ 16 files changed, 33 insertions(+), 1 deletion(-) diff --git a/utils/bg/filesystem.texy b/utils/bg/filesystem.texy index c17d8ffb79..46b25a925e 100644 --- a/utils/bg/filesystem.texy +++ b/utils/bg/filesystem.texy @@ -5,6 +5,8 @@ [api:Nette\Utils\FileSystem] е статичен клас, който съдържа полезни функции за работа с файлова система. Едно от предимствата им пред нативните функции на PHP е, че те хвърлят изключения в случай на грешки. +Ако трябва да търсите файлове на диска, използвайте [Finder |finder]. + Инсталация: ```shell diff --git a/utils/cs/filesystem.texy b/utils/cs/filesystem.texy index 03a950b5e2..169820d712 100644 --- a/utils/cs/filesystem.texy +++ b/utils/cs/filesystem.texy @@ -2,9 +2,11 @@ Souborový systém **************** .[perex] -[api:Nette\Utils\FileSystem] je statická třída s užitečnými funkcemi pro práci se souborovým systémem. Jednou z výhod oproti nativním PHP funkcím je, že v případě chyb vyhazují výjimky. +[api:Nette\Utils\FileSystem] je statická třída s užitečnými funkcemi pro práci se souborovým systémem. Jednou z výhod oproti nativním PHP funkcím je, že v případě chyby vyhazují výjimky. +Pokud potřebujete hledat soubory na disku, použijte [Finder|finder]. + Instalace: ```shell diff --git a/utils/de/filesystem.texy b/utils/de/filesystem.texy index be0bd14ff5..73fb5d0b5c 100644 --- a/utils/de/filesystem.texy +++ b/utils/de/filesystem.texy @@ -5,6 +5,8 @@ Dateisystem-Funktionen [api:Nette\Utils\FileSystem] ist eine statische Klasse, die nützliche Funktionen für die Arbeit mit einem Dateisystem enthält. Ein Vorteil gegenüber nativen PHP-Funktionen ist, dass sie im Fehlerfall Ausnahmen auslösen. +Wenn Sie nach Dateien auf dem Datenträger suchen müssen, verwenden Sie den [Finder |finder]. + Installation: ```shell diff --git a/utils/el/filesystem.texy b/utils/el/filesystem.texy index 2c7b28f09c..fa9d16d7cf 100644 --- a/utils/el/filesystem.texy +++ b/utils/el/filesystem.texy @@ -5,6 +5,8 @@ [api:Nette\Utils\FileSystem] είναι μια στατική κλάση, η οποία περιέχει χρήσιμες συναρτήσεις για την εργασία με ένα σύστημα αρχείων. Ένα πλεονέκτημα σε σχέση με τις εγγενείς συναρτήσεις της PHP είναι ότι πετάνε εξαιρέσεις σε περίπτωση σφαλμάτων. +Αν θέλετε να αναζητήσετε αρχεία στο δίσκο, χρησιμοποιήστε το [Finder |finder]. + Εγκατάσταση: ```shell diff --git a/utils/en/filesystem.texy b/utils/en/filesystem.texy index d7fc8b600b..995e03310c 100644 --- a/utils/en/filesystem.texy +++ b/utils/en/filesystem.texy @@ -5,6 +5,8 @@ Filesystem Functions [api:Nette\Utils\FileSystem] is a static class, which contains useful functions for working with a filesystem. One advantage over native PHP functions is that they throw exceptions in case of errors. +If you need to search for files on the disk, use the [Finder |finder]. + Installation: ```shell diff --git a/utils/es/filesystem.texy b/utils/es/filesystem.texy index f7f914d42b..c7827c8fb4 100644 --- a/utils/es/filesystem.texy +++ b/utils/es/filesystem.texy @@ -5,6 +5,8 @@ Funciones del sistema de archivos [api:Nette\Utils\FileSystem] es una clase estática, que contiene funciones útiles para trabajar con un sistema de archivos. Una ventaja sobre las funciones nativas de PHP es que lanzan excepciones en caso de errores. +Si necesitas buscar archivos en el disco, utiliza el [Finder |finder]. + Instalación: ```shell diff --git a/utils/fr/filesystem.texy b/utils/fr/filesystem.texy index a8aceb487f..649b9ab4f5 100644 --- a/utils/fr/filesystem.texy +++ b/utils/fr/filesystem.texy @@ -5,6 +5,8 @@ Fonctions du système de fichiers [api:Nette\Utils\FileSystem] est une classe statique, qui contient des fonctions utiles pour travailler avec un système de fichiers. Un avantage par rapport aux fonctions natives de PHP est qu'elles lèvent des exceptions en cas d'erreurs. +Si vous devez rechercher des fichiers sur le disque, utilisez le [Finder |finder]. + Installation : ```shell diff --git a/utils/hu/filesystem.texy b/utils/hu/filesystem.texy index 83e5836ceb..6299e34529 100644 --- a/utils/hu/filesystem.texy +++ b/utils/hu/filesystem.texy @@ -5,6 +5,8 @@ Fájlrendszer funkciók [api:Nette\Utils\FileSystem] egy statikus osztály, amely hasznos függvényeket tartalmaz a fájlrendszerrel való munkához. Egyik előnye a natív PHP függvényekkel szemben, hogy hiba esetén kivételeket dobnak. +Ha fájlokat kell keresnie a lemezen, használja a [Finder |finder] programot. + Telepítés: ```shell diff --git a/utils/it/filesystem.texy b/utils/it/filesystem.texy index 695312636c..183198d5df 100644 --- a/utils/it/filesystem.texy +++ b/utils/it/filesystem.texy @@ -5,6 +5,8 @@ Funzioni del filesystem [api:Nette\Utils\FileSystem] è una classe statica che contiene funzioni utili per lavorare con il filesystem. Un vantaggio rispetto alle funzioni native di PHP è che lanciano eccezioni in caso di errori. +Per cercare i file sul disco, utilizzare il [Finder |finder]. + Installazione: ```shell diff --git a/utils/pl/filesystem.texy b/utils/pl/filesystem.texy index 05514e25fd..5980e40c18 100644 --- a/utils/pl/filesystem.texy +++ b/utils/pl/filesystem.texy @@ -5,6 +5,8 @@ Funkcje systemu plików [api:Nette\Utils\FileSystem] jest statyczną klasą, która zawiera przydatne funkcje do pracy z systemem plików. Jedną z zalet w stosunku do natywnych funkcji PHP jest to, że w przypadku błędów rzucają one wyjątki. +Jeśli chcesz wyszukać pliki na dysku, użyj [Finder |finder]. + Instalacja: ```shell diff --git a/utils/pt/filesystem.texy b/utils/pt/filesystem.texy index 573e5b0859..c869b35f84 100644 --- a/utils/pt/filesystem.texy +++ b/utils/pt/filesystem.texy @@ -5,6 +5,8 @@ Funções do sistema de arquivos [api:Nette\Utils\FileSystem] é uma classe estática, que contém funções úteis para trabalhar com um sistema de arquivos. Uma vantagem sobre as funções PHP nativas é que elas lançam exceções em caso de erros. +Se você precisar procurar arquivos no disco, use o [Finder |finder]. + Instalação: ```shell diff --git a/utils/ro/filesystem.texy b/utils/ro/filesystem.texy index 08c0be3261..ac3971da59 100644 --- a/utils/ro/filesystem.texy +++ b/utils/ro/filesystem.texy @@ -5,6 +5,8 @@ Funcțiile sistemului de fișiere [api:Nette\Utils\FileSystem] este o clasă statică, care conține funcții utile pentru lucrul cu un sistem de fișiere. Un avantaj față de funcțiile native PHP este că acestea aruncă excepții în caz de erori. +Dacă trebuie să căutați fișiere pe disc, utilizați [Finder |finder]. + Instalare: ```shell diff --git a/utils/ru/filesystem.texy b/utils/ru/filesystem.texy index 0e83acb07b..edbc258074 100644 --- a/utils/ru/filesystem.texy +++ b/utils/ru/filesystem.texy @@ -5,6 +5,8 @@ [api:Nette\Utils\FileSystem] это статический класс, содержащий полезные функции для работы с файловой системой. Одно из преимуществ перед собственными функциями PHP заключается в том, что они бросают исключения в случае ошибок. +Если необходимо найти файлы на диске, используйте [Finder |finder]. + Установка: ```shell diff --git a/utils/sl/filesystem.texy b/utils/sl/filesystem.texy index e51281d06c..69212925c7 100644 --- a/utils/sl/filesystem.texy +++ b/utils/sl/filesystem.texy @@ -5,6 +5,8 @@ Funkcije datotečnega sistema [api:Nette\Utils\FileSystem] je statični razred, ki vsebuje uporabne funkcije za delo z datotečnim sistemom. Ena od prednosti v primerjavi z izvornimi funkcijami PHP je, da v primeru napak mečejo izjeme. +Če želite poiskati datoteke na disku, uporabite [Finder |finder]. + Namestitev: ```shell diff --git a/utils/tr/filesystem.texy b/utils/tr/filesystem.texy index 8ed0f75b1a..96aa3f27ca 100644 --- a/utils/tr/filesystem.texy +++ b/utils/tr/filesystem.texy @@ -5,6 +5,8 @@ Dosya Sistemi İşlevleri [api:Nette\Utils\FileSystem] bir dosya sistemi ile çalışmak için yararlı işlevler içeren duruk bir sınıftır. Yerel PHP işlevlerine göre bir avantajı, hata durumunda istisnalar atmasıdır. +Diskte dosya aramanız gerekiyorsa [Finder |finder]'ı kullanın. + Kurulum: ```shell diff --git a/utils/uk/filesystem.texy b/utils/uk/filesystem.texy index 1940925dfb..0f5a3f31a2 100644 --- a/utils/uk/filesystem.texy +++ b/utils/uk/filesystem.texy @@ -5,6 +5,8 @@ [api:Nette\Utils\FileSystem] це статичний клас, який містить корисні функції для роботи з файловою системою. Однією з переваг над нативними функціями PHP є те, що вони генерують виключення у випадку помилок. +Якщо вам потрібно знайти файли на диску, скористайтеся [Finder |finder]. + Встановлення: ```shell From 5ab9698cfd77b937ad4ade67bf134ba91ad7987a Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 12 Sep 2023 08:18:39 +0200 Subject: [PATCH 004/137] own page for StaticClass --- nette/bg/@home.texy | 2 +- nette/cs/@home.texy | 2 +- nette/de/@home.texy | 2 +- nette/el/@home.texy | 2 +- nette/en/@home.texy | 2 +- nette/es/@home.texy | 2 +- nette/fr/@home.texy | 2 +- nette/hu/@home.texy | 2 +- nette/it/@home.texy | 2 +- nette/pl/@home.texy | 2 +- nette/pt/@home.texy | 2 +- nette/ro/@home.texy | 2 +- nette/ru/@home.texy | 2 +- nette/sl/@home.texy | 2 +- nette/tr/@home.texy | 2 +- nette/uk/@home.texy | 2 +- utils/bg/@home.texy | 2 +- utils/bg/@left-menu.texy | 3 ++- utils/bg/smartobject.texy | 21 +++------------------ utils/bg/staticclass.texy | 21 +++++++++++++++++++++ utils/cs/@home.texy | 2 +- utils/cs/@left-menu.texy | 3 ++- utils/cs/smartobject.texy | 21 +++------------------ utils/cs/staticclass.texy | 21 +++++++++++++++++++++ utils/de/@home.texy | 2 +- utils/de/@left-menu.texy | 3 ++- utils/de/smartobject.texy | 21 +++------------------ utils/de/staticclass.texy | 21 +++++++++++++++++++++ utils/el/@home.texy | 2 +- utils/el/@left-menu.texy | 3 ++- utils/el/smartobject.texy | 21 +++------------------ utils/el/staticclass.texy | 21 +++++++++++++++++++++ utils/en/@home.texy | 2 +- utils/en/@left-menu.texy | 3 ++- utils/en/smartobject.texy | 21 +++------------------ utils/en/staticclass.texy | 21 +++++++++++++++++++++ utils/es/@home.texy | 2 +- utils/es/@left-menu.texy | 3 ++- utils/es/smartobject.texy | 21 +++------------------ utils/es/staticclass.texy | 21 +++++++++++++++++++++ utils/fr/@home.texy | 2 +- utils/fr/@left-menu.texy | 3 ++- utils/fr/smartobject.texy | 21 +++------------------ utils/fr/staticclass.texy | 21 +++++++++++++++++++++ utils/hu/@home.texy | 2 +- utils/hu/@left-menu.texy | 3 ++- utils/hu/smartobject.texy | 21 +++------------------ utils/hu/staticclass.texy | 21 +++++++++++++++++++++ utils/it/@home.texy | 2 +- utils/it/@left-menu.texy | 3 ++- utils/it/smartobject.texy | 23 ++++------------------- utils/it/staticclass.texy | 21 +++++++++++++++++++++ utils/pl/@home.texy | 2 +- utils/pl/@left-menu.texy | 3 ++- utils/pl/smartobject.texy | 21 +++------------------ utils/pl/staticclass.texy | 21 +++++++++++++++++++++ utils/pt/@home.texy | 2 +- utils/pt/@left-menu.texy | 3 ++- utils/pt/smartobject.texy | 21 +++------------------ utils/pt/staticclass.texy | 21 +++++++++++++++++++++ utils/ro/@home.texy | 2 +- utils/ro/@left-menu.texy | 3 ++- utils/ro/smartobject.texy | 21 +++------------------ utils/ro/staticclass.texy | 21 +++++++++++++++++++++ utils/ru/@home.texy | 2 +- utils/ru/@left-menu.texy | 3 ++- utils/ru/smartobject.texy | 21 +++------------------ utils/ru/staticclass.texy | 21 +++++++++++++++++++++ utils/sl/@home.texy | 2 +- utils/sl/@left-menu.texy | 3 ++- utils/sl/smartobject.texy | 21 +++------------------ utils/sl/staticclass.texy | 21 +++++++++++++++++++++ utils/tr/@home.texy | 2 +- utils/tr/@left-menu.texy | 3 ++- utils/tr/smartobject.texy | 21 +++------------------ utils/tr/staticclass.texy | 21 +++++++++++++++++++++ utils/uk/@home.texy | 2 +- utils/uk/@left-menu.texy | 3 ++- utils/uk/smartobject.texy | 21 +++------------------ utils/uk/staticclass.texy | 21 +++++++++++++++++++++ 80 files changed, 449 insertions(+), 337 deletions(-) create mode 100644 utils/bg/staticclass.texy create mode 100644 utils/cs/staticclass.texy create mode 100644 utils/de/staticclass.texy create mode 100644 utils/el/staticclass.texy create mode 100644 utils/en/staticclass.texy create mode 100644 utils/es/staticclass.texy create mode 100644 utils/fr/staticclass.texy create mode 100644 utils/hu/staticclass.texy create mode 100644 utils/it/staticclass.texy create mode 100644 utils/pl/staticclass.texy create mode 100644 utils/pt/staticclass.texy create mode 100644 utils/ro/staticclass.texy create mode 100644 utils/ru/staticclass.texy create mode 100644 utils/sl/staticclass.texy create mode 100644 utils/tr/staticclass.texy create mode 100644 utils/uk/staticclass.texy diff --git a/nette/bg/@home.texy b/nette/bg/@home.texy index 186b0c1b59..feabd53f9c 100644 --- a/nette/bg/@home.texy +++ b/nette/bg/@home.texy @@ -84,11 +84,11 @@ - [помощни средства:JSON |utils:JSON] - [NEON |neon:] - [Събиране на пароли |security:passwords] -- [SmartObject |utils:SmartObject] - [Типове PHP |utils:type] - [Strings |utils:Strings] - [Валидатори |utils:validators] - [RobotLoader |robot-loader:] +- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] - [SafeStream |safe-stream:] - [...други |utils:] diff --git a/nette/cs/@home.texy b/nette/cs/@home.texy index ec7373b9d4..9d81baaa96 100644 --- a/nette/cs/@home.texy +++ b/nette/cs/@home.texy @@ -84,11 +84,11 @@ Utilities - [utils:JSON] - [NEON|neon:] - [Hashování hesel |security:passwords] -- [SmartObject |utils:smartobject] - [PHP typy |utils:type] - [Řetězce |utils:strings] - [Validátory |utils:validators] - [RobotLoader |robot-loader:] +- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] - [SafeStream |safe-stream:] - [...další |utils:] diff --git a/nette/de/@home.texy b/nette/de/@home.texy index b8ef3cad0f..9b30ddb609 100644 --- a/nette/de/@home.texy +++ b/nette/de/@home.texy @@ -84,11 +84,11 @@ Dienstprogramme - [JSON |utils:JSON] - [NEON |neon:] - [Passwort-Hashing |security:passwords] -- [SmartObject |utils:SmartObject] - [PHP Typen |utils:type] - [Zeichenketten |utils:Strings] - [Prüfer |utils:validators] - [RobotLoader |robot-loader:] +- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] - [SafeStream |safe-stream:] - [...andere |utils:] diff --git a/nette/el/@home.texy b/nette/el/@home.texy index 24a21d5a36..2923d00186 100644 --- a/nette/el/@home.texy +++ b/nette/el/@home.texy @@ -84,11 +84,11 @@ Nette Τεκμηρίωση - [JSON |utils:JSON] - [NEON |neon:] - [Κρυπτογράφηση κωδικού πρόσβασης |security:passwords] -- [SmartObject |utils:SmartObject] - [Τύποι PHP |utils:type] - [Strings |utils:Strings] - [Επικυρωτές |utils:validators] - [RobotLoader |robot-loader:] +- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] - [SafeStream |safe-stream:] - [...άλλα |utils:] diff --git a/nette/en/@home.texy b/nette/en/@home.texy index 2fe80a3dab..b2d2e5c09a 100644 --- a/nette/en/@home.texy +++ b/nette/en/@home.texy @@ -84,11 +84,11 @@ Utilities - [utils:JSON] - [NEON|neon:] - [Password Hashing |security:passwords] -- [utils:SmartObject] - [PHP Types |utils:type] - [utils:Strings] - [Validators |utils:validators] - [RobotLoader |robot-loader:] +- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] - [SafeStream |safe-stream:] - [...others |utils:] diff --git a/nette/es/@home.texy b/nette/es/@home.texy index c6644ab4c5..0a57b34965 100644 --- a/nette/es/@home.texy +++ b/nette/es/@home.texy @@ -84,11 +84,11 @@ Utilidades - [JSON |utils:JSON] - [NEON |neon:] - [Hashing de contraseñas |security:passwords] -- [SmartObject |utils:SmartObject] - [Tipos de PHP |utils:type] - [Cadenas |utils:Strings] - [Validadores |utils:validators] - [RobotLoader |robot-loader:] +- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] - [SafeStream |safe-stream:] - ... [otros |utils:] diff --git a/nette/fr/@home.texy b/nette/fr/@home.texy index 76241bb9d3..23f87d0522 100644 --- a/nette/fr/@home.texy +++ b/nette/fr/@home.texy @@ -84,11 +84,11 @@ Utilitaires - [JSON |utils:JSON] - [NEON |neon:] - [Hachage de mot de passe |security:passwords] -- [SmartObject |utils:SmartObject] - [Types PHP |utils:type] - [Strings |utils:Strings] - [Validateurs |utils:validators] - [RobotLoader |robot-loader:] +- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] - [SafeStream |safe-stream:] - [...autres |utils:] diff --git a/nette/hu/@home.texy b/nette/hu/@home.texy index 53d3959489..b3aa613dea 100644 --- a/nette/hu/@home.texy +++ b/nette/hu/@home.texy @@ -84,11 +84,11 @@ Segédprogramok - [JSON |utils:JSON] - [NEON |neon:] - [Password Hashing |security:passwords] -- [SmartObject |utils:SmartObject] - [PHP típusok |utils:type] - [Strings |utils:Strings] - [Validátorok |utils:validators] - [RobotLoader |robot-loader:] +- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] - [SafeStream |safe-stream:] - [...mások |utils:] diff --git a/nette/it/@home.texy b/nette/it/@home.texy index 73dfd0447c..758fd70193 100644 --- a/nette/it/@home.texy +++ b/nette/it/@home.texy @@ -84,11 +84,11 @@ Utilità - [JSON |utils:JSON] - [NEON |neon:] - [Hashing della password |security:passwords] -- [SmartObject |utils:SmartObject] - [Tipi PHP |utils:type] - [Stringhe |utils:Strings] - [Validatori |utils:validators] - [RobotLoader |robot-loader:] +- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] - [SafeStream |safe-stream:] - [...altri |utils:] diff --git a/nette/pl/@home.texy b/nette/pl/@home.texy index 9868af29e3..6429bb7295 100644 --- a/nette/pl/@home.texy +++ b/nette/pl/@home.texy @@ -84,11 +84,11 @@ Narzędzia - [JSON |utils:JSON] - [NEON |neon:] - [Hashing hasła |security:passwords] -- [SmartObject |utils:smartobject] - [Rodzaje PHP |utils:type] - [Struny |utils:strings] - [Walidatory |utils:validators] - [RobotLoader |robot-loader:] +- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] - [SafeStream |safe-stream:] - [...więcej |utils:] diff --git a/nette/pt/@home.texy b/nette/pt/@home.texy index 6b35915287..e2fdbdc4ec 100644 --- a/nette/pt/@home.texy +++ b/nette/pt/@home.texy @@ -84,11 +84,11 @@ Utilidades - [JSON |utils:JSON] - [NEON |neon:] - [Hashing de senha |security:passwords] -- [SmartObject |utils:SmartObject] - [Tipos de PHP |utils:type] - [Cordas |utils:Strings] - [Validadores |utils:validators] - [RobotLoader |robot-loader:] +- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] - [SafeStream |safe-stream:] - [...outros |utils:] diff --git a/nette/ro/@home.texy b/nette/ro/@home.texy index 93cb581542..44631364c9 100644 --- a/nette/ro/@home.texy +++ b/nette/ro/@home.texy @@ -84,11 +84,11 @@ Utilități - [JSON |utils:JSON] - [NEON |neon:] - [Hașurarea parolei |security:passwords] -- [SmartObject |utils:SmartObject] - [Tipuri PHP |utils:type] - [Șiruri de caractere |utils:Strings] - [Validatori |utils:validators] - [RobotLoader |robot-loader:] +- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] - [SafeStream |safe-stream:] - [...altele |utils:] diff --git a/nette/ru/@home.texy b/nette/ru/@home.texy index fbf9ee8c63..e00f7de000 100644 --- a/nette/ru/@home.texy +++ b/nette/ru/@home.texy @@ -84,11 +84,11 @@ - [utils:JSON] - [NEON|neon:] - [Password Hashing |security:passwords] -- [utils:SmartObject] - [PHP Reflection |utils:reflection] - [utils:Strings] - [Валидаторы |utils:validators] - [RobotLoader |robot-loader:] +- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] - [SafeStream |safe-stream:] - [...другое |utils:] diff --git a/nette/sl/@home.texy b/nette/sl/@home.texy index bafe6b5d10..170bbd9789 100644 --- a/nette/sl/@home.texy +++ b/nette/sl/@home.texy @@ -84,11 +84,11 @@ Storitve - [JSON |utils:JSON] - [NEON |neon:] - [Hashing gesel |security:passwords] -- [SmartObject |utils:SmartObject] - [Tipi PHP |utils:type] - [Nizi |utils:Strings] - [Validatorji |utils:validators] - [RobotLoader |robot-loader:] +- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] - [SafeStream |safe-stream:] - [...drugi |utils:] diff --git a/nette/tr/@home.texy b/nette/tr/@home.texy index 095f3e9aff..cb5c58765f 100644 --- a/nette/tr/@home.texy +++ b/nette/tr/@home.texy @@ -84,11 +84,11 @@ Yardımcı Programlar - [JSON |utils:JSON] - [NEON |neon:] - [Parola Hashing |security:passwords] -- [SmartObject |utils:SmartObject] - [PHP Türleri |utils:type] - [Dizeler |utils:Strings] - [Doğrulayıcılar |utils:validators] - [RobotLoader |robot-loader:] +- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] - [SafeStream |safe-stream:] - [...diğerleri |utils:] diff --git a/nette/uk/@home.texy b/nette/uk/@home.texy index 22a16c5c9d..1783ac19fe 100644 --- a/nette/uk/@home.texy +++ b/nette/uk/@home.texy @@ -84,11 +84,11 @@ - [JSON |utils:JSON] - [NEON |neon:] - [Зашивання пароля |security:passwords] -- [SmartObject |utils:SmartObject] - [Типи PHP |utils:type] - [Strings |utils:Strings] - [Валідатори |utils:validators] - [RobotLoader |robot-loader:] +- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] - [SafeStream |safe-stream:] - [...інше |utils:] diff --git a/utils/bg/@home.texy b/utils/bg/@home.texy index 25520611d9..468b428942 100644 --- a/utils/bg/@home.texy +++ b/utils/bg/@home.texy @@ -11,7 +11,6 @@ | [Генериране на случайни низове |random] | Nette\Utils\Random | [Дата и час |datetime] | Nette\Utils\DateTime | [Nette\Utils\Image |images] -| [Модел на обекта |smartobject] | Nette\SmartObject & Nette\StaticClass | [Пагинация |paginator] | Nette\Utils\Paginator | [Парсинг и генериране на JSON |json] | Nette\Utils\Json | [Полета |arrays] | Nette\Utils\Arrays @@ -20,6 +19,7 @@ | [Файлова система |filesystem] | Nette\Utils\FileSystem | [Полезни функции | Nette\Utils\Helpers |helpers] | [HTML елементи |html-elements] | Nette\Utils\Html +| [SmartObject] & [StaticClass] | Nette\SmartObject & Nette\StaticClass | [PHP Reflection |reflection] | Nette\Utils\Reflection diff --git a/utils/bg/@left-menu.texy b/utils/bg/@left-menu.texy index 9d14fb22d2..1c661ebc3d 100644 --- a/utils/bg/@left-menu.texy +++ b/utils/bg/@left-menu.texy @@ -15,8 +15,9 @@ - [Файлова система |filesystem] - [Помощни функции |helpers] - [Елементи на HTML |html-elements] +- [SmartObject] +- [StaticClass] - [Размисли за PHP |reflection] -- [SmartObject |smartobject] Други инструменти diff --git a/utils/bg/smartobject.texy b/utils/bg/smartobject.texy index 471bf25ce9..89997e6857 100644 --- a/utils/bg/smartobject.texy +++ b/utils/bg/smartobject.texy @@ -1,8 +1,8 @@ -SmartObject и StaticClass -************************* +SmartObject +*********** .[perex] -SmartObject добавя поддръжка на *свойства* към класовете на PHP. StaticClass се използва за обозначаване на статични класове. +SmartObject поправяше поведението на обектите по много начини, но днешният PHP вече включва повечето от тези подобрения. Въпреки това той все още добавя поддръжка за *собственост*. Настройка: @@ -65,21 +65,6 @@ echo $circle->visible; // извиква isVisible() Свойствата са преди всичко "синтактична захар" и са предназначени да направят живота на програмиста по-сладък, като опростят кода. Ако нямате нужда от тях, не е нужно да ги използвате. -Статични класове .[#toc-static-classes] -======================================= - -Статичните класове, т.е. класовете, които не са предназначени да бъдат инстанцирани, могат да бъдат маркирани с `Nette\StaticClass`: - -```php -class Strings -{ - use Nette\StaticClass; -} -``` - -Когато се опитате да създадете инстанция, се появява изключение `Error`, което показва, че класът е статичен. - - Поглед към историята .[#toc-a-look-into-the-history] ==================================================== diff --git a/utils/bg/staticclass.texy b/utils/bg/staticclass.texy new file mode 100644 index 0000000000..4b65d4e728 --- /dev/null +++ b/utils/bg/staticclass.texy @@ -0,0 +1,21 @@ +Статични класове +**************** + +.[perex] +StaticClass се използва за обозначаване на статични класове. + + +Инсталация: + +```shell +composer require nette/utils +``` + +Статичните класове, т.е. класовете, които не са предназначени да бъдат инстанцирани, могат да бъдат маркирани с признака [api:Nette\StaticClass]: + +```php +class Strings +{ + use Nette\StaticClass; +} +``` diff --git a/utils/cs/@home.texy b/utils/cs/@home.texy index bf462b878e..a3b1331096 100644 --- a/utils/cs/@home.texy +++ b/utils/cs/@home.texy @@ -10,7 +10,6 @@ V balíčku `nette/utils` najdete sadu užitečných tříd pro každodenní pou | [HTML elementy |html-elements] | Nette\Utils\Html | [JSON |json] | Nette\Utils\Json | [Náhodné řetězce |random] | Nette\Utils\Random -| [Objektový model |smartobject] | Nette\SmartObject & Nette\StaticClass | [Obrázky |images] | Nette\Utils\Image | [PHP reflexe |reflection] | Nette\Utils\Reflection | [PHP typy |type] | Nette\Utils\Type @@ -20,6 +19,7 @@ V balíčku `nette/utils` najdete sadu užitečných tříd pro každodenní pou | [Řetězce |strings] | Nette\Utils\Strings | [Souborový systém |filesystem] | Nette\Utils\FileSystem | [Stránkování |paginator] | Nette\Utils\Paginator +| [SmartObject] & [StaticClass] | Nette\SmartObject & Nette\StaticClass | [Validátor |validators] | Nette\Utils\Validators diff --git a/utils/cs/@left-menu.texy b/utils/cs/@left-menu.texy index 94c90f1dd2..f64ec996d3 100644 --- a/utils/cs/@left-menu.texy +++ b/utils/cs/@left-menu.texy @@ -14,7 +14,8 @@ Balíček nette/utils - [Pole |arrays] - [Pomocné funkce |helpers] - [Řetězce |strings] -- [SmartObject |smartobject] +- [SmartObject] +- [StaticClass] - [Souborový systém |filesystem] - [Validátor |validators] diff --git a/utils/cs/smartobject.texy b/utils/cs/smartobject.texy index 63cc12a241..a7cc76b200 100644 --- a/utils/cs/smartobject.texy +++ b/utils/cs/smartobject.texy @@ -1,8 +1,8 @@ -SmartObject a StaticClass -************************* +SmartObject +*********** .[perex] -SmartObject přidává PHP třídám podporu pro tzv. *property*. StaticClass slouží pro označení statických tříd. +SmartObject opravovala chování objektů v mnoha směrech, ale dnešní PHP již obsahuje většinu vylepšení nativně. Stále však přidává podporu pro tzv. *property*. Instalace: @@ -65,21 +65,6 @@ echo $circle->visible; // volá isVisible() Properties jsou především "syntaktickým cukříkem"((syntactic sugar)), jehož smyslem je zpřehlednit kód a osladit tak programátorovi život. Pokud nechcete, nemusíte je používat. -Statické třídy -============== - -Statické třídy, tedy třídy, které nejsou určené k vytváření instancí, můžete označit traitou `Nette\StaticClass`: - -```php -class Strings -{ - use Nette\StaticClass; -} -``` - -Při pokusu o vytvoření instance se vyhodí výjimka `Error` s informací, že uvedená třída je statická. - - Pohled do historie ================== diff --git a/utils/cs/staticclass.texy b/utils/cs/staticclass.texy new file mode 100644 index 0000000000..ea757f58f9 --- /dev/null +++ b/utils/cs/staticclass.texy @@ -0,0 +1,21 @@ +Statické třídy +************** + +.[perex] +StaticClass slouží pro označení statických tříd. + + +Instalace: + +```shell +composer require nette/utils +``` + +Statické třídy, tedy třídy, které nejsou určené k vytváření instancí, můžete označit traitou [api:Nette\StaticClass]: + +```php +class Strings +{ + use Nette\StaticClass; +} +``` diff --git a/utils/de/@home.texy b/utils/de/@home.texy index a0eb54a00f..babf795f17 100644 --- a/utils/de/@home.texy +++ b/utils/de/@home.texy @@ -13,13 +13,13 @@ Im Paket `nette/utils` finden Sie eine Reihe von nützlichen Klassen für den t | [Generieren von HTML-Code |html-elements] | Nette\Utils\Html | [Helferfunktionen |helpers] | Nette\Utils\Helfer | [JSON] | Nette\Utils\Json -| [Objektmodell |smartobject] | Nette\SmartObject & Nette\StaticClass | [Paginator] | Nette\Utils\Paginator | [PHP-Reflexion |reflection] | Nette\Utils\Reflexion | [Rückruf |Callback] | Nette\Utils\Callback | [Typen |type] | Nette\Utils\Type | [Validatoren |Validators] | Nette\Utils\Validatoren | [Zeichenketten |Strings] | Nette\Utils\Strings +| [SmartObject] & [StaticClass] | Nette\SmartObject & Nette\StaticClass | [Zufällige Zeichenketten generieren |random] | Nette\Utils\Random diff --git a/utils/de/@left-menu.texy b/utils/de/@left-menu.texy index f820e0f6ce..5ca87cc2c6 100644 --- a/utils/de/@left-menu.texy +++ b/utils/de/@left-menu.texy @@ -13,8 +13,9 @@ Paket nette/utils - [Paginator |paginator] - [PHP-Reflexion |reflection] - [PHP Typen |type] -- [SmartObject] - [Strings] +- [SmartObject] +- [StaticClass] - [Validatoren |validators] - [Zufällige Zeichenketten |random] diff --git a/utils/de/smartobject.texy b/utils/de/smartobject.texy index 783015895d..3ea9f4b074 100644 --- a/utils/de/smartobject.texy +++ b/utils/de/smartobject.texy @@ -1,8 +1,8 @@ -SmartObject und StaticClass -*************************** +SmartObject +*********** .[perex] -SmartObject fügt PHP-Klassen Unterstützung für *Eigenschaften* hinzu. StaticClass wird verwendet, um statische Klassen zu bezeichnen. +SmartObject hat das Verhalten von Objekten in vielerlei Hinsicht verbessert, aber das heutige PHP enthält die meisten dieser Verbesserungen bereits von Haus aus. Es fügt jedoch noch Unterstützung für *Property* hinzu. Installation: @@ -65,21 +65,6 @@ echo $circle->visible; // calls isVisible() Eigenschaften sind in erster Linie "syntaktischer Zucker" ((syntactic sugar)), der das Leben des Programmierers durch Vereinfachung des Codes versüßen soll. Wenn Sie sie nicht wollen, müssen Sie sie nicht verwenden. -Statische Klassen .[#toc-static-classes] -======================================== - -Statische Klassen, d.h. Klassen, die nicht instanziiert werden sollen, können mit dem Trait `Nette\StaticClass` gekennzeichnet werden: - -```php -class Strings -{ - use Nette\StaticClass; -} -``` - -Wenn Sie versuchen, eine Instanz zu erstellen, wird die Ausnahme `Error` ausgelöst, die angibt, dass die Klasse statisch ist. - - Ein Blick in die Geschichte .[#toc-a-look-into-the-history] =========================================================== diff --git a/utils/de/staticclass.texy b/utils/de/staticclass.texy new file mode 100644 index 0000000000..c5831c1c0d --- /dev/null +++ b/utils/de/staticclass.texy @@ -0,0 +1,21 @@ +Statische Klassen +***************** + +.[perex] +StaticClass wird verwendet, um statische Klassen zu bezeichnen. + + +Installation: + +```shell +composer require nette/utils +``` + +Statische Klassen, d.h. Klassen, die nicht instanziiert werden sollen, können mit dem Trait [api:Nette\StaticClass] gekennzeichnet werden: + +```php +class Strings +{ + use Nette\StaticClass; +} +``` diff --git a/utils/el/@home.texy b/utils/el/@home.texy index 049f6689d3..8885bebad0 100644 --- a/utils/el/@home.texy +++ b/utils/el/@home.texy @@ -14,12 +14,12 @@ | [Στοιχεία HTML |HTML Elements] | Nette\Utils\Html | [Images |Images] | Nette\Utils\Image | [JSON |JSON] | Nette\Utils\Json -| [Μοντέλο αντικειμένων |smartobject] | Nette\SmartObject & Nette\StaticClass | [Paginator |paginator] | Nette\Utils\Paginator | [PHP Reflection |reflection] | Nette\Utils\Reflection | [PHP Types |type] | Nette\Utils\Type | [Τυχαίες συμβολοσειρές |random] | Nette\Utils\Random | [Strings |Strings] | Nette\Utils\Strings +| [SmartObject] & [StaticClass] | Nette\SmartObject & Nette\StaticClass | [Validators |validators] | Nette\Utils\Validators diff --git a/utils/el/@left-menu.texy b/utils/el/@left-menu.texy index c262d9deb2..6ef2e7ba0b 100644 --- a/utils/el/@left-menu.texy +++ b/utils/el/@left-menu.texy @@ -11,10 +11,11 @@ - [JSON |JSON] - [Σελιδοποιητής |paginator] - [Τυχαίες συμβολοσειρές |random] -- [SmartObject |SmartObject] - [PHP Reflection |reflection] - [Συμβολοσειρές |Strings] - [Floats |Floats] +- [SmartObject] +- [StaticClass] - [Τύποι PHP |type] - [Επικυρωτές |validators] diff --git a/utils/el/smartobject.texy b/utils/el/smartobject.texy index 229a82276f..54e24aa5fd 100644 --- a/utils/el/smartobject.texy +++ b/utils/el/smartobject.texy @@ -1,8 +1,8 @@ -SmartObject και StaticClass -*************************** +SmartObject +*********** .[perex] -Το SmartObject προσθέτει υποστήριξη για *ιδιότητες* στις κλάσεις PHP. Το StaticClass χρησιμοποιείται για να δηλώσει στατικές κλάσεις. +Το SmartObject διόρθωνε τη συμπεριφορά των αντικειμένων με πολλούς τρόπους, αλλά η σημερινή PHP περιλαμβάνει ήδη τις περισσότερες από αυτές τις βελτιώσεις εγγενώς. Ωστόσο, εξακολουθεί να προσθέτει υποστήριξη για *property*. Εγκατάσταση: @@ -65,21 +65,6 @@ echo $circle->visible; // καλεί την isVisible() Οι ιδιότητες είναι κατά κύριο λόγο "συντακτική ζάχαρη"((syntactic sugar)), η οποία έχει σκοπό να κάνει τη ζωή του προγραμματιστή πιο γλυκιά απλοποιώντας τον κώδικα. Αν δεν τις θέλετε, δεν χρειάζεται να τις χρησιμοποιήσετε. -Στατικές κλάσεις .[#toc-static-classes] -======================================= - -Οι στατικές κλάσεις, δηλαδή οι κλάσεις που δεν προορίζονται για ενσάρκωση, μπορούν να επισημανθούν με το χαρακτηριστικό `Nette\StaticClass`: - -```php -class Strings -{ - use Nette\StaticClass; -} -``` - -Όταν προσπαθείτε να δημιουργήσετε ένα instance, εκπέμπεται η εξαίρεση `Error`, υποδεικνύοντας ότι η κλάση είναι στατική. - - Μια ματιά στην ιστορία .[#toc-a-look-into-the-history] ====================================================== diff --git a/utils/el/staticclass.texy b/utils/el/staticclass.texy new file mode 100644 index 0000000000..0e7d4d0c58 --- /dev/null +++ b/utils/el/staticclass.texy @@ -0,0 +1,21 @@ +Στατικές κλάσεις +**************** + +.[perex] +Το StaticClass χρησιμοποιείται για να δηλώσει στατικές κλάσεις. + + +Εγκατάσταση: + +```shell +composer require nette/utils +``` + +μπορούν να επισημανθούν με το χαρακτηριστικό [api:Nette\StaticClass]: + +```php +class Strings +{ + use Nette\StaticClass; +} +``` diff --git a/utils/en/@home.texy b/utils/en/@home.texy index e2879920a3..6bddedbcfb 100644 --- a/utils/en/@home.texy +++ b/utils/en/@home.texy @@ -14,12 +14,12 @@ In package `nette/utils` you will find a set of useful classes for everyday use: | [HTML Elements] | Nette\Utils\Html | [Images] | Nette\Utils\Image | [JSON] | Nette\Utils\Json -| [Object model |smartobject] | Nette\SmartObject & Nette\StaticClass | [Paginator |paginator] | Nette\Utils\Paginator | [PHP Reflection |reflection] | Nette\Utils\Reflection | [PHP Types |type] | Nette\Utils\Type | [Random Strings |random] | Nette\Utils\Random | [Strings] | Nette\Utils\Strings +| [SmartObject] & [StaticClass] | Nette\SmartObject & Nette\StaticClass | [Validators |validators] | Nette\Utils\Validators diff --git a/utils/en/@left-menu.texy b/utils/en/@left-menu.texy index 249f02c4f6..fc5b708ef1 100644 --- a/utils/en/@left-menu.texy +++ b/utils/en/@left-menu.texy @@ -11,9 +11,10 @@ Package nette/utils - [JSON] - [Paginator |paginator] - [Random Strings |random] -- [SmartObject] - [PHP Reflection |reflection] - [Strings] +- [SmartObject] +- [StaticClass] - [Floats] - [PHP Types |type] - [Validators |validators] diff --git a/utils/en/smartobject.texy b/utils/en/smartobject.texy index f53fde130d..a45751b3d1 100644 --- a/utils/en/smartobject.texy +++ b/utils/en/smartobject.texy @@ -1,8 +1,8 @@ -SmartObject and StaticClass -*************************** +SmartObject +*********** .[perex] -SmartObject adds support for *property* to PHP classes. StaticClass is used to denote static classes. +SmartObject used to fix objects behavior in many ways, but today's PHP already includes most of these improvements natively. However, it still adds support for *property*. Installation: @@ -65,21 +65,6 @@ echo $circle->visible; // calls isVisible() Properties are primarily "syntactic sugar"((syntactic sugar)), which is intended to make the programmer's life sweeter by simplifying the code. If you don't want them, you don't have to use them. -Static Classes -============== - -Static classes, i.e. classes that are not intended to be instantiated, can be marked with the trait `Nette\StaticClass`: - -```php -class Strings -{ - use Nette\StaticClass; -} -``` - -When you try to create an instance, the `Error` exception is thrown, indicating that the class is static. - - A Look into the History ======================= diff --git a/utils/en/staticclass.texy b/utils/en/staticclass.texy new file mode 100644 index 0000000000..73054c0420 --- /dev/null +++ b/utils/en/staticclass.texy @@ -0,0 +1,21 @@ +Static Classes +************** + +.[perex] +StaticClass is used to denote static classes. + + +Installation: + +```shell +composer require nette/utils +``` + +Static classes, i.e. classes that are not intended to be instantiated, can be marked with the trait [api:Nette\StaticClass]: + +```php +class Strings +{ + use Nette\StaticClass; +} +``` diff --git a/utils/es/@home.texy b/utils/es/@home.texy index f54df2b0d8..ecf223d43d 100644 --- a/utils/es/@home.texy +++ b/utils/es/@home.texy @@ -16,10 +16,10 @@ En el paquete `nette/utils` encontrará un conjunto de clases útiles para el us | [Imágenes |Images] | Nette\Utils\Image | [JSON] | Nette\Utils\Json | [Matrices |Arrays] | Nette\Utils\Arrays -| [Modelo de objeto |smartobject] | Nette\SmartObject & Nette\StaticClass | [Paginador |Paginator] | Nette\Utils\Paginator | [Sistema de archivos |filesystem] | Nette\Utils\FileSystem | [Tipos |type] | Nette\Utils\Type +| [SmartObject] & [StaticClass] | Nette\SmartObject & Nette\StaticClass | [Validadores |Validators] | Nette\Utils\Validators diff --git a/utils/es/@left-menu.texy b/utils/es/@left-menu.texy index 9948ca0769..5bea16e074 100644 --- a/utils/es/@left-menu.texy +++ b/utils/es/@left-menu.texy @@ -11,10 +11,11 @@ Paquete nette/utils - [Imágenes |Images] - [JSON] - [Matrices |Arrays] -- [Objeto inteligente |SmartObject] - [Paginador |paginator] - [Reflexión PHP |reflection] - [Sistema de archivos |filesystem] +- [SmartObject] +- [StaticClass] - [Tipos de PHP |type] - [Validadores |validators] diff --git a/utils/es/smartobject.texy b/utils/es/smartobject.texy index b8824ec24d..247743a38f 100644 --- a/utils/es/smartobject.texy +++ b/utils/es/smartobject.texy @@ -1,8 +1,8 @@ -SmartObject y StaticClass -************************* +SmartObject +*********** .[perex] -SmartObject añade soporte para *propiedades* a las clases PHP. StaticClass se utiliza para denotar clases estáticas. +SmartObject solía arreglar el comportamiento de los objetos de muchas maneras, pero el PHP actual ya incluye la mayoría de estas mejoras de forma nativa. Sin embargo, aún añade soporte para *property*. Instalación: @@ -65,21 +65,6 @@ echo $circle->visible; // calls isVisible() Las propiedades son principalmente "azúcar sintáctico"((syntactic sugar)), que pretende hacer la vida del programador más dulce simplificando el código. Si no las quieres, no tienes por qué usarlas. -Clases estáticas .[#toc-static-classes] -======================================= - -Las clases estáticas, es decir, las clases que no están destinadas a ser instanciadas, pueden marcarse con el rasgo `Nette\StaticClass`: - -```php -class Strings -{ - use Nette\StaticClass; -} -``` - -Cuando se intenta crear una instancia, se lanza la excepción `Error`, indicando que la clase es estática. - - Un vistazo a la historia .[#toc-a-look-into-the-history] ======================================================== diff --git a/utils/es/staticclass.texy b/utils/es/staticclass.texy new file mode 100644 index 0000000000..c2f7bc35fc --- /dev/null +++ b/utils/es/staticclass.texy @@ -0,0 +1,21 @@ +Clases estáticas +**************** + +.[perex] +StaticClass se utiliza para denotar clases estáticas. + + +Instalación: + +```shell +composer require nette/utils +``` + +Las clases estáticas, es decir, las clases que no están destinadas a ser instanciadas, pueden marcarse con el rasgo [api:Nette\StaticClass]: + +```php +class Strings +{ + use Nette\StaticClass; +} +``` diff --git a/utils/fr/@home.texy b/utils/fr/@home.texy index f96f963d94..c9bf7ce122 100644 --- a/utils/fr/@home.texy +++ b/utils/fr/@home.texy @@ -13,13 +13,13 @@ Dans le paquetage `nette/utils`, vous trouverez un ensemble de classes utiles po | [Chaînes de caractères |Strings] | Nette\Utils\Strings | [Images] | Nette\Utils\Image | [JSON] | Nette\Utils\Json -| [Modèle d'objet |smartobject] | Nette\SmartObject & Nette\StaticClass | [Finder] | Nette\Utils\Finder | [Paginateur |Paginator] | Nette\Utils\Paginator | [PHP Reflection |reflection] | Nette\Utils\Reflection | [Système de fichiers |filesystem] | Nette\Utils\FileSystem | [Tableaux |Arrays] | Nette\Utils\Arrays | [Types |type] | Nette\Utils\Type +| [SmartObject] & [StaticClass] | Nette\SmartObject & Nette\StaticClass | [Validateurs |Validators] | Nette\Utils\Validators diff --git a/utils/fr/@left-menu.texy b/utils/fr/@left-menu.texy index 8b9a577cae..bddfa8c498 100644 --- a/utils/fr/@left-menu.texy +++ b/utils/fr/@left-menu.texy @@ -12,9 +12,10 @@ Paquet net/utils - [Paginateur |paginator] - [PHP Reflection |reflection] - [Retour d'appel |Callback] -- [SmartObject] - [Système de fichiers |filesystem] - [Tableaux |Arrays] +- [SmartObject] +- [StaticClass] - [Types PHP |type] - [Validateurs |validators] diff --git a/utils/fr/smartobject.texy b/utils/fr/smartobject.texy index 70d1024e3c..01912cad49 100644 --- a/utils/fr/smartobject.texy +++ b/utils/fr/smartobject.texy @@ -1,8 +1,8 @@ -SmartObject et StaticClass -************************** +SmartObject +*********** .[perex] -SmartObject ajoute le support des *propriétés* aux classes PHP. StaticClass est utilisé pour désigner les classes statiques. +SmartObject corrigeait le comportement des objets de plusieurs façons, mais le PHP d'aujourd'hui inclut déjà la plupart de ces améliorations de façon native. Cependant, il ajoute encore le support des *propriétés*. Installation : @@ -65,21 +65,6 @@ echo $circle->visible; // calls isVisible() Les propriétés sont principalement du "sucre syntaxique" ((sucre syntaxique)), destiné à rendre la vie du programmeur plus douce en simplifiant le code. Si vous n'en voulez pas, vous n'êtes pas obligé de les utiliser. -Classes statiques .[#toc-static-classes] -======================================== - -Les classes statiques, c'est-à-dire les classes qui ne sont pas destinées à être instanciées, peuvent être marquées par le trait `Nette\StaticClass`: - -```php -class Strings -{ - use Nette\StaticClass; -} -``` - -Lorsque vous essayez de créer une instance, l'exception `Error` est levée, indiquant que la classe est statique. - - Un regard sur l'histoire .[#toc-a-look-into-the-history] ======================================================== diff --git a/utils/fr/staticclass.texy b/utils/fr/staticclass.texy new file mode 100644 index 0000000000..20d426d804 --- /dev/null +++ b/utils/fr/staticclass.texy @@ -0,0 +1,21 @@ +Classes statiques +***************** + +.[perex] +StaticClass est utilisé pour désigner les classes statiques. + + +L'installation : + +```shell +composer require nette/utils +``` + +Les classes statiques, c'est-à-dire les classes qui ne sont pas destinées à être instanciées, peuvent être marquées par le trait [api:Nette\StaticClass]: + +```php +class Strings +{ + use Nette\StaticClass; +} +``` diff --git a/utils/hu/@home.texy b/utils/hu/@home.texy index 9a33f01d4c..9ddc16be73 100644 --- a/utils/hu/@home.texy +++ b/utils/hu/@home.texy @@ -14,12 +14,12 @@ A `nette/utils` csomagban a mindennapi használatra hasznos osztályok találhat | [HTML elemek |HTML Elements] | Nette\Utils\Html | [Képek |Images] | Nette\Utils\Image | [JSON |JSON] | Nette\Utils\Json -| [Objektum modell |smartobject] | Nette\SmartObject & Nette\StaticClass | [Paginátor |paginator] | Nette\Utils\Paginátor | [PHP Reflection |reflection] | Nette\Utils\Reflection | [PHP típusok |type] | Nette\Utils\Type | [Véletlenszerű karakterláncok |random] | Nette\Utils\Random | [Sztringek |Strings] | Nette\Utils\Strings +| [SmartObject] & [StaticClass] | Nette\SmartObject & Nette\StaticClass | [Érvényesítők |validators] | Nette\Utils\Validators diff --git a/utils/hu/@left-menu.texy b/utils/hu/@left-menu.texy index 7c674c589e..9e6f969b23 100644 --- a/utils/hu/@left-menu.texy +++ b/utils/hu/@left-menu.texy @@ -11,10 +11,11 @@ Csomag nette/utils - [JSON |JSON] - [Paginátor |paginator] - [Véletlenszerű karakterláncok |random] -- [SmartObject |SmartObject] - [PHP reflexió |reflection] - [Strings |Strings] - [Lebegők |Floats] +- [SmartObject] +- [StaticClass] - [PHP típusok |type] - [Validátorok |validators] diff --git a/utils/hu/smartobject.texy b/utils/hu/smartobject.texy index a158b2858b..a050640455 100644 --- a/utils/hu/smartobject.texy +++ b/utils/hu/smartobject.texy @@ -1,8 +1,8 @@ -SmartObject és StaticClass -************************** +SmartObject +*********** .[perex] -A SmartObject a PHP osztályok *tulajdonságok* támogatását adja hozzá. A StaticClass a statikus osztályok jelölésére szolgál. +A SmartObject korábban sokféleképpen javította az objektumok viselkedését, de a mai PHP már natívan tartalmazza ezen fejlesztések nagy részét. Azonban még mindig hozzáadja a *tulajdonságok* támogatását. Telepítés: @@ -65,21 +65,6 @@ echo $circle->visible; // hívja az isVisible() függvényt A tulajdonságok elsősorban "szintaktikai cukor"((syntactic sugar)), amelynek célja, hogy a kód egyszerűsítésével megédesítse a programozó életét. Ha nem akarod őket, nem kell használni őket. -Statikus osztályok .[#toc-static-classes] -========================================= - -A statikus osztályokat, azaz azokat az osztályokat, amelyeket nem szándékoznak példányosítani, a `Nette\StaticClass` tulajdonsággal lehet jelölni: - -```php -class Strings -{ - use Nette\StaticClass; -} -``` - -Amikor megpróbál egy példányt létrehozni, a `Error` kivétel dobódik, jelezve, hogy az osztály statikus. - - Egy pillantás a történelembe .[#toc-a-look-into-the-history] ============================================================ diff --git a/utils/hu/staticclass.texy b/utils/hu/staticclass.texy new file mode 100644 index 0000000000..aff0d36925 --- /dev/null +++ b/utils/hu/staticclass.texy @@ -0,0 +1,21 @@ +Statikus osztályok +****************** + +.[perex] +A StaticClass a statikus osztályok jelölésére szolgál. + + +Telepítés: + +```shell +composer require nette/utils +``` + +Statikus osztályok, azaz olyan osztályok, amelyeket nem szándékoznak példányosítani, a [api:Nette\StaticClass] tulajdonsággal jelölhetők: + +```php +class Strings +{ + use Nette\StaticClass; +} +``` diff --git a/utils/it/@home.texy b/utils/it/@home.texy index d7eac70856..9674b40ae9 100644 --- a/utils/it/@home.texy +++ b/utils/it/@home.texy @@ -14,12 +14,12 @@ Il pacchetto `nette/utils` contiene un insieme di classi utili per l'uso quotidi | [Elementi HTML |HTML Elements] | Nette\Utils\Html | [Immagini |Images] | Nette\Utils\Image | [JSON |JSON] | Nette\Utils\Json -| [Modello a oggetti |smartobject] | Nette\SmartObject & Nette\StaticClass | [Paginatore |paginator] | Nette\Utils\Paginatore | [Riflessione PHP |reflection] | Nette\Utils\Reflection | [Tipi PHP |type] | Nette\Utils\Type | [Stringhe casuali |random] | Nette\Utils\Random | [Stringhe |Strings] | Nette\Utils\Strings +| [SmartObject] & [StaticClass] | Nette\SmartObject & Nette\StaticClass | [Validatori |validators] | Nette\Utils\Validators diff --git a/utils/it/@left-menu.texy b/utils/it/@left-menu.texy index c856685e85..0e8f491439 100644 --- a/utils/it/@left-menu.texy +++ b/utils/it/@left-menu.texy @@ -11,10 +11,11 @@ Pacchetto nette/utils - [JSON |JSON] - [Paginatore |paginator] - [Stringhe casuali |random] -- [Oggetto intelligente |SmartObject] - [Riflessione PHP |reflection] - [Stringhe |Strings] - [Galleggianti |Floats] +- [SmartObject] +- [StaticClass] - [Tipi PHP |type] - [Validatori |validators] diff --git a/utils/it/smartobject.texy b/utils/it/smartobject.texy index aefed8cef1..0e5feea57c 100644 --- a/utils/it/smartobject.texy +++ b/utils/it/smartobject.texy @@ -1,8 +1,8 @@ -SmartObject e StaticClass -************************* +SmartObject +*********** .[perex] -SmartObject aggiunge il supporto per le *proprietà* alle classi PHP. StaticClass è usato per indicare le classi statiche. +SmartObject correggeva il comportamento degli oggetti in molti modi, ma il PHP di oggi include già la maggior parte di questi miglioramenti in modo nativo. Tuttavia, aggiunge ancora il supporto per le *proprietà*. Installazione: @@ -65,25 +65,10 @@ echo $circle->visible; // chiama isVisible() Le proprietà sono principalmente "zucchero sintattico" ((syntactic sugar)), che ha lo scopo di rendere più dolce la vita del programmatore semplificando il codice. Se non le si vuole, non è necessario usarle. -Classi statiche .[#toc-static-classes] -====================================== - -Le classi statiche, cioè quelle che non sono destinate ad essere istanziate, possono essere contrassegnate con il tratto `Nette\StaticClass`: - -```php -class Strings -{ - use Nette\StaticClass; -} -``` - -Quando si tenta di creare un'istanza, viene lanciata l'eccezione `Error`, che indica che la classe è statica. - - Uno sguardo alla storia .[#toc-a-look-into-the-history] ======================================================= -SmartObject migliorava e correggeva il comportamento delle classi in molti modi, ma l'evoluzione di PHP ha reso superflua la maggior parte delle caratteristiche originali. Di seguito viene presentata la storia di come si sono evolute le cose. +SmartObject correggeva il comportamento degli oggetti in molti modi, ma il PHP di oggi include già la maggior parte dei miglioramenti in modo nativo. Quello che segue è uno sguardo nostalgico alla storia e un promemoria di come le cose si sono evolute. Fin dall'inizio, il modello a oggetti di PHP soffriva di una serie di gravi difetti e inefficienze. Questo è stato il motivo della creazione della classe `Nette\Object` (nel 2007), che ha cercato di porvi rimedio e di migliorare l'esperienza d'uso di PHP. È bastato che altre classi ereditassero da essa per trarne i benefici. Quando PHP 5.4 ha introdotto il supporto ai trait, la classe `Nette\Object` è stata sostituita da `Nette\SmartObject`. Pertanto, non era più necessario ereditare da un antenato comune. Inoltre, i trait potevano essere usati in classi che già ereditavano da un'altra classe. La fine definitiva di `Nette\Object` avvenne con il rilascio di PHP 7.2, che proibiva alle classi di chiamarsi `Object`. diff --git a/utils/it/staticclass.texy b/utils/it/staticclass.texy new file mode 100644 index 0000000000..50cdbf5ebd --- /dev/null +++ b/utils/it/staticclass.texy @@ -0,0 +1,21 @@ +Classi statiche +*************** + +.[perex] +StaticClass è usato per indicare le classi statiche. + + +Installazione: + +```shell +composer require nette/utils +``` + +Le classi statiche, cioè quelle che non sono destinate a essere istanziate, possono essere contrassegnate con il tratto [api:Nette\StaticClass]: + +```php +class Strings +{ + use Nette\StaticClass; +} +``` diff --git a/utils/pl/@home.texy b/utils/pl/@home.texy index 6912d59579..f53a3669d8 100644 --- a/utils/pl/@home.texy +++ b/utils/pl/@home.texy @@ -10,7 +10,6 @@ W pakiecie `nette/utils` znajdziesz zestaw przydatnych klas do codziennego użyt | [elementów HTML |html-elements] | Nette\Utils\Html | [JSON |json] | Nette\Utils\Json | [Losowe ciągi znaków |random] | Nette\Utils\Random -| [Model Obiektów |smartobject] | Nette\SmartObject & Nette\StaticClass | [Obrazki |images] | Nette\Utils\Image | [Odbicie w PHP |reflection] | Nette\Utils\Reflection | [typy PHP |type] Nette\Utils\Type @@ -20,6 +19,7 @@ W pakiecie `nette/utils` znajdziesz zestaw przydatnych klas do codziennego użyt | [Strings |strings] | Nette\Utils\Strings | [System plików |filesystem] | Nette\Utils\Filesystem | [Paginator |paginator] | Nette\Utils\Paginator +| [SmartObject] & [StaticClass] | Nette\SmartObject & Nette\StaticClass | [Walidator |validators] | Nette\Utils\Validator diff --git a/utils/pl/@left-menu.texy b/utils/pl/@left-menu.texy index 73189365a3..e9c10fbdf0 100644 --- a/utils/pl/@left-menu.texy +++ b/utils/pl/@left-menu.texy @@ -14,7 +14,8 @@ Pakiet Nette/utils - [Tablice |arrays] - [Funkcje pomocnicze |helpers] - [Struny |strings] -- [SmartObject |smartobject] +- [SmartObject] +- [StaticClass] - [System plików |filesystem] - [Walidator |validators] diff --git a/utils/pl/smartobject.texy b/utils/pl/smartobject.texy index 138a67a5fc..d76d67d8f2 100644 --- a/utils/pl/smartobject.texy +++ b/utils/pl/smartobject.texy @@ -1,8 +1,8 @@ -SmartObject i StaticClass -************************* +SmartObject +*********** .[perex] -SmartObject dodaje do klas PHP wsparcie dla *property*. StaticClass służy do oznaczania klas statycznych. +SmartObject poprawiał zachowanie obiektów na wiele sposobów, ale dzisiejszy PHP zawiera już większość tych ulepszeń natywnie. Wciąż jednak dodaje wsparcie dla *property*. Instalacja: @@ -65,21 +65,6 @@ echo $circle->visible; // volá isVisible() Właściwości to przede wszystkim "cukier syntaktyczny"((syntactic sugar)), który ma uczynić życie programisty słodszym poprzez uproszczenie kodu. Jeśli ich nie chcesz, nie musisz z nich korzystać. -Klasy statyczne .[#toc-staticke-tridy] -====================================== - -Klasy statyczne, czyli takie, które nie są przeznaczone do instancjonowania, mogą być oznaczone cechą `Nette\StaticClass`: - -```php -class Strings -{ - use Nette\StaticClass; -} -``` - -Podczas próby utworzenia instancji rzucany jest wyjątek `Error` wskazujący, że klasa jest statyczna. - - Spojrzenie na historię ====================== diff --git a/utils/pl/staticclass.texy b/utils/pl/staticclass.texy new file mode 100644 index 0000000000..013de13034 --- /dev/null +++ b/utils/pl/staticclass.texy @@ -0,0 +1,21 @@ +Klasy statyczne +*************** + +.[perex] +StaticClass służy do oznaczania klas statycznych. + + +Instalacja: + +```shell +composer require nette/utils +``` + +Klasy statyczne, tj. klasy, które nie są przeznaczone do instancjonowania, mogą być oznaczone cechą [api:Nette\StaticClass]: + +```php +class Strings +{ + use Nette\StaticClass; +} +``` diff --git a/utils/pt/@home.texy b/utils/pt/@home.texy index f9219966f1..f02fdd62ed 100644 --- a/utils/pt/@home.texy +++ b/utils/pt/@home.texy @@ -14,12 +14,12 @@ No pacote `nette/utils` você encontrará um conjunto de aulas úteis para o uso | [Elementos HTML |HTML Elements] | Nette\Utils\Html | [Imagens |Images] | Nette\Utils\Image | [JSON |JSON] | Nette\Utils\Json -| [Modelo do objeto |smartobject] | Nette\SmartObject & Nette\StaticClass | [Paginador de Paginadores |paginator] | Nette\Utils\Paginator | [Reflexão PHP Ref |reflection] | Nette\Utils\Reflection | [Tipos de PHP |type] | Nette\Utils\Type | [Random Strings |random] | Nette\Utils\Random | [Cordas |Strings] | Nette\Utils\Strings +| [SmartObject] & [StaticClass] | Nette\SmartObject & Nette\StaticClass | [Validadores |validators] Nette\Utils\Validators diff --git a/utils/pt/@left-menu.texy b/utils/pt/@left-menu.texy index 487e5158bd..83178cea74 100644 --- a/utils/pt/@left-menu.texy +++ b/utils/pt/@left-menu.texy @@ -11,10 +11,11 @@ Pacote nette/utils - [JSON |JSON] - [Paginador |paginator] - [Cordas Aleatórias |random] -- [SmartObject |SmartObject] - [Reflexão PHP |reflection] - [Cordas |Strings] - [Flutuadores |Floats] +- [SmartObject] +- [StaticClass] - [Tipos de PHP |type] - [Validadores |validators] diff --git a/utils/pt/smartobject.texy b/utils/pt/smartobject.texy index cc43032dd3..31736e235f 100644 --- a/utils/pt/smartobject.texy +++ b/utils/pt/smartobject.texy @@ -1,8 +1,8 @@ -SmartObject e StaticClass -************************* +SmartObject +*********** .[perex] -O SmartObject adiciona suporte para *propriedade* às classes PHP. O StaticClass é usado para denotar classes estáticas. +O SmartObject costumava corrigir o comportamento dos objetos de várias maneiras, mas o PHP atual já inclui a maioria desses aprimoramentos nativamente. No entanto, ele ainda adiciona suporte para *property*. Instalação: @@ -65,21 +65,6 @@ echo $circle->visible; // chamadas isVisible() As propriedades são principalmente o "açúcar sintático"((açúcar sintático)), que se destina a tornar a vida do programador mais doce, simplificando o código. Se você não os quer, não precisa usá-los. -Classes estáticas .[#toc-static-classes] -======================================== - -As classes estáticas, ou seja, classes que não se destinam a ser instanciadas, podem ser marcadas com o traço `Nette\StaticClass`: - -```php -class Strings -{ - use Nette\StaticClass; -} -``` - -Quando você tenta criar uma instância, a exceção `Error` é lançada, indicando que a classe é estática. - - Um olhar sobre a história .[#toc-a-look-into-the-history] ========================================================= diff --git a/utils/pt/staticclass.texy b/utils/pt/staticclass.texy new file mode 100644 index 0000000000..75a43f1f65 --- /dev/null +++ b/utils/pt/staticclass.texy @@ -0,0 +1,21 @@ +Classes estáticas +***************** + +.[perex] +StaticClass é usado para indicar classes estáticas. + + +Instalação: + +```shell +composer require nette/utils +``` + +Classes estáticas, ou seja, classes que não se destinam a ser instanciadas, podem ser marcadas com a característica [api:Nette\StaticClass]: + +```php +class Strings +{ + use Nette\StaticClass; +} +``` diff --git a/utils/ro/@home.texy b/utils/ro/@home.texy index a9e20302c0..bc68166834 100644 --- a/utils/ro/@home.texy +++ b/utils/ro/@home.texy @@ -14,12 +14,12 @@ Utilități | [Elemente HTML |HTML Elements] | Nette\Utils\Html [Imagini |Images] | Imagini | Nette\Utils\Image [JSON |JSON] | JSON | Nette\Utils\Json -| [Model de obiect |smartobject] | Nette\SmartObject & Nette\StaticClass | [Paginator |paginator] | Nette\Utils\Paginator [PHP Reflection |reflection] | [PHP |reflection] Reflection | Nette\Utils\Reflection [PHP Types |type] | [PHP Types |type] | Nette\Utils\Type | [Șiruri aleatorii |random] | Nette\Utils\Random | [Șiruri de caractere |Strings] | Nette\Utils\Strings +| [SmartObject] & [StaticClass] | Nette\SmartObject & Nette\StaticClass [Validatori |validators] | Validators | Nette\Utils\Validators diff --git a/utils/ro/@left-menu.texy b/utils/ro/@left-menu.texy index 8c32b60f04..8b2e3fc881 100644 --- a/utils/ro/@left-menu.texy +++ b/utils/ro/@left-menu.texy @@ -11,10 +11,11 @@ Pachetul nette/utils - [JSON |JSON] - [Paginator |paginator] - [Șiruri aleatorii |random] -- [SmartObject |SmartObject] - [Reflecție PHP |reflection] - [Șiruri de caractere |Strings] - [Flote |Floats] +- [SmartObject] +- [StaticClass] - [Tipuri PHP |type] - [Validatori |validators] diff --git a/utils/ro/smartobject.texy b/utils/ro/smartobject.texy index d487e98cfd..5cbc348305 100644 --- a/utils/ro/smartobject.texy +++ b/utils/ro/smartobject.texy @@ -1,8 +1,8 @@ -SmartObject și StaticClass -************************** +SmartObject +*********** .[perex] -SmartObject adaugă suport pentru *proprietăți* la clasele PHP. StaticClass este utilizat pentru a desemna clasele statice. +SmartObject obișnuia să corecteze comportamentul obiectelor în mai multe moduri, dar PHP-ul de astăzi include deja majoritatea acestor îmbunătățiri în mod nativ. Cu toate acestea, se adaugă încă suport pentru *proprietate*. Instalare: @@ -65,21 +65,6 @@ echo $circle->visible; // solicită isVisible() Proprietățile sunt în primul rând "zahăr sintactic"((zahăr sintactic)), care are rolul de a face viața programatorului mai ușoară prin simplificarea codului. Dacă nu le doriți, nu trebuie să le folosiți. -Clase statice .[#toc-static-classes] -==================================== - -Clasele statice, adică clasele care nu sunt destinate a fi instanțiate, pot fi marcate cu trăsătura `Nette\StaticClass`: - -```php -class Strings -{ - use Nette\StaticClass; -} -``` - -Atunci când încercați să creați o instanță, se aruncă excepția `Error`, indicând că clasa este statică. - - O privire în istorie .[#toc-a-look-into-the-history] ==================================================== diff --git a/utils/ro/staticclass.texy b/utils/ro/staticclass.texy new file mode 100644 index 0000000000..76eaa09869 --- /dev/null +++ b/utils/ro/staticclass.texy @@ -0,0 +1,21 @@ +Clase statice +************* + +.[perex] +StaticClass este utilizat pentru a desemna clasele statice. + + +Instalare: + +```shell +composer require nette/utils +``` + +Clasele statice, adică clasele care nu sunt destinate a fi instanțiate, pot fi marcate cu trăsătura [api:Nette\StaticClass]: + +```php +class Strings +{ + use Nette\StaticClass; +} +``` diff --git a/utils/ru/@home.texy b/utils/ru/@home.texy index e75c6199af..363d308da6 100644 --- a/utils/ru/@home.texy +++ b/utils/ru/@home.texy @@ -11,7 +11,6 @@ | [Генерация случайных строк |random] | Nette\Utils\Random | [Дата и время |datetime] | Nette\Utils\DateTime | [Изображения |images] | Nette\Utils\Image -| [Модель объекта |smartobject] | Nette\SmartObject & Nette\StaticClass | [Пагинация |paginator] | Nette\Utils\Paginator | [Парсинг и генерация JSON |json] | Nette\Utils\Json | [Поле |arrays] | Nette\Utils\Arrays @@ -20,6 +19,7 @@ | [Файловая система |filesystem] | Nette\Utils\FileSystem | [Функции-помощники |helpers] | Nette\Utils\Helpers | [Элементы HTML |html-elements] | Nette\Utils\Html +| [SmartObject] & [StaticClass] | Nette\SmartObject & Nette\StaticClass | [PHP Отражение |reflection] | Nette\Utils\Reflection diff --git a/utils/ru/@left-menu.texy b/utils/ru/@left-menu.texy index 4c34b12008..94fce6f58f 100644 --- a/utils/ru/@left-menu.texy +++ b/utils/ru/@left-menu.texy @@ -15,8 +15,9 @@ - [Файловая система |filesystem] - [Функции-помощники |helpers] - [Элементы HTML |html-elements] +- [SmartObject] +- [StaticClass] - [PHP Отражение |reflection] -- [SmartObject |smartobject] Другие инструменты diff --git a/utils/ru/smartobject.texy b/utils/ru/smartobject.texy index 458fd548d2..444ea955e8 100644 --- a/utils/ru/smartobject.texy +++ b/utils/ru/smartobject.texy @@ -1,8 +1,8 @@ -SmartObject и StaticClass -************************* +SmartObject +*********** .[perex] -SmartObject добавляет поддержку *свойств* в классы PHP. StaticClass используется для обозначения статических классов. +SmartObject во многом исправлял поведение объектов, но современный PHP уже включает большинство этих улучшений нативно. Тем не менее, в нем все еще добавлена поддержка *property*. Установка: @@ -65,21 +65,6 @@ echo $circle->visible; // calls isVisible() Свойства - это прежде всего "синтаксический сахар"((syntactic sugar)), который призван сделать жизнь программиста слаще за счет упрощения кода. Если они вам не нужны, вы не обязаны их использовать. -Статические классы .[#toc-static-classes] -========================================= - -Статические классы, т.е. классы, которые не предназначены для инстанцирования, могут быть помечены признаком `Nette\StaticClass`: - -```php -class Strings -{ - use Nette\StaticClass; -} -``` - -Когда вы пытаетесь создать экземпляр, возникает исключение `Error`, указывающее на то, что класс является статическим. - - Взгляд в историю .[#toc-a-look-into-the-history] ================================================ diff --git a/utils/ru/staticclass.texy b/utils/ru/staticclass.texy new file mode 100644 index 0000000000..97f573e878 --- /dev/null +++ b/utils/ru/staticclass.texy @@ -0,0 +1,21 @@ +Статические классы +****************** + +.[perex] +StaticClass используется для обозначения статических классов. + + +Установка: + +```shell +composer require nette/utils +``` + +Статические классы, т.е. классы, не предназначенные для инстанцирования, могут быть помечены признаком [api:Nette\StaticClass]: + +```php +class Strings +{ + use Nette\StaticClass; +} +``` diff --git a/utils/sl/@home.texy b/utils/sl/@home.texy index 131197c536..1d9cedcb7c 100644 --- a/utils/sl/@home.texy +++ b/utils/sl/@home.texy @@ -14,12 +14,12 @@ V paketu `nette/utils` boste našli niz uporabnih razredov za vsakdanjo uporabo: | [Elementi HTML |HTML Elements] | Nette\Utils\Html | [Slike |Images] | Nette\Utils\Image | [JSON |JSON] | Nette\Utils\Json -| [Objektni model |smartobject] | Nette\SmartObject & Nette\StaticClass | [Paginator |paginator] | Nette\Utils\Paginator | [PHP Reflection |reflection] | Nette\Utils\Reflection | [Tipi PHP |type] | Nette\Utils\Type | [Naključni nizi |random] | Nette\Utils\Random [Nizi |Strings] | Nette\Utils\Nizi | Nette\Utils\Nizi +| [SmartObject] & [StaticClass] | Nette\SmartObject & Nette\StaticClass | [Validatorji |validators] | Nette\Utils\Validators diff --git a/utils/sl/@left-menu.texy b/utils/sl/@left-menu.texy index 0e2cbfd550..e9d66c191d 100644 --- a/utils/sl/@left-menu.texy +++ b/utils/sl/@left-menu.texy @@ -11,10 +11,11 @@ Paket nette/utils - [JSON |JSON] - [Paginator |paginator] - [Naključni nizi |random] -- [SmartObject |SmartObject] - [Odsev PHP |reflection] - [Nizi |Strings] - [Plavaji |Floats] +- [SmartObject] +- [StaticClass] - [Tipi PHP |type] - [Validatorji |validators] diff --git a/utils/sl/smartobject.texy b/utils/sl/smartobject.texy index 212a575673..26548988f2 100644 --- a/utils/sl/smartobject.texy +++ b/utils/sl/smartobject.texy @@ -1,8 +1,8 @@ -SmartObject in StaticClass -************************** +SmartObject +*********** .[perex] -SmartObject razredom PHP doda podporo za *lastnosti*. StaticClass se uporablja za označevanje statičnih razredov. +SmartObject je v preteklosti na različne načine popravljal obnašanje predmetov, vendar današnji PHP večino teh izboljšav že vključuje. Vendar pa še vedno dodaja podporo za *lastnost*. Namestitev: @@ -65,21 +65,6 @@ echo $circle->visible; // pokliče isVisible() Lastnosti so predvsem "sintaktični sladkor"((sintactic sugar)), ki je namenjen temu, da programerju s poenostavitvijo kode osladi življenje. Če jih ne želite, vam jih ni treba uporabljati. -Statični razredi .[#toc-static-classes] -======================================= - -Statične razrede, tj. razrede, ki niso namenjeni instanciranju, lahko označimo z lastnostjo `Nette\StaticClass`: - -```php -class Strings -{ - use Nette\StaticClass; -} -``` - -Pri poskusu ustvarjanja instance se vrže izjema `Error`, ki označuje, da je razred statičen. - - Pogled v zgodovino .[#toc-a-look-into-the-history] ================================================== diff --git a/utils/sl/staticclass.texy b/utils/sl/staticclass.texy new file mode 100644 index 0000000000..135be2a633 --- /dev/null +++ b/utils/sl/staticclass.texy @@ -0,0 +1,21 @@ +Statični razredi +**************** + +.[perex] +StaticClass se uporablja za označevanje statičnih razredov. + + +Namestitev: + +```shell +composer require nette/utils +``` + +Statični razredi, tj. razredi, ki niso namenjeni instanciranju, so lahko označeni z lastnostjo [api:Nette\StaticClass]: + +```php +class Strings +{ + use Nette\StaticClass; +} +``` diff --git a/utils/tr/@home.texy b/utils/tr/@home.texy index 45bc74103b..54c3533daa 100644 --- a/utils/tr/@home.texy +++ b/utils/tr/@home.texy @@ -14,12 +14,12 @@ Yardımcı Programlar | [HTML Elemanları |HTML Elements] | Nette\Utils\Html | [Görüntüler |Images] | Nette\Utils\Image | [JSON |JSON] | Nette\Utils\Json -| [Nesne modeli |smartobject] | Nette\SmartObject & Nette\StaticClass | [Paginator |paginator] | Nette\Utils\Paginator | [PHP |reflection] Yansıması | Nette\Utils\Reflection | [PHP Türleri |type] | Nette\Utils\Type | [Rastgele Dizeler |random] | Nette\Utils\Random | [Dizeler |Strings] | Nette\Utils\Strings +| [SmartObject] & [StaticClass] | Nette\SmartObject & Nette\StaticClass | [Doğrulayıcılar |validators] | Nette\Utils\Validators diff --git a/utils/tr/@left-menu.texy b/utils/tr/@left-menu.texy index 738761e936..a0a5bb879b 100644 --- a/utils/tr/@left-menu.texy +++ b/utils/tr/@left-menu.texy @@ -11,10 +11,11 @@ Paket nette/utils - [JSON |JSON] - [Paginator |paginator] - [Rastgele Dizeler |random] -- [SmartObject |SmartObject] - [PHP Yansıması|reflection] - [Dizeler |Strings] - [Yüzer |Floats] +- [SmartObject] +- [StaticClass] - [PHP Türleri |type] - [Doğrulayıcılar |validators] diff --git a/utils/tr/smartobject.texy b/utils/tr/smartobject.texy index 41a488dbaa..1617abc805 100644 --- a/utils/tr/smartobject.texy +++ b/utils/tr/smartobject.texy @@ -1,8 +1,8 @@ -SmartObject ve StaticClass -************************** +SmartObject +*********** .[perex] -SmartObject PHP sınıflarına *property* desteği ekler. StaticClass statik sınıfları belirtmek için kullanılır. +SmartObject nesnelerin davranışını birçok yönden düzeltirdi, ancak günümüz PHP'si bu iyileştirmelerin çoğunu zaten yerel olarak içermektedir. Bununla birlikte, hala *property* için destek ekler. Kurulum: @@ -65,21 +65,6 @@ echo $circle->visible; // isVisible() işlevini çağırır Özellikler öncelikle "sözdizimsel şeker"((syntactic sugar)) olup, kodu basitleştirerek programcının hayatını daha tatlı hale getirmeyi amaçlar. Eğer onları istemiyorsanız, kullanmak zorunda değilsiniz. -Statik Sınıflar .[#toc-static-classes] -====================================== - -Statik sınıflar, yani örneklenmesi amaçlanmayan sınıflar, `Nette\StaticClass` özelliği ile işaretlenebilir: - -```php -class Strings -{ - use Nette\StaticClass; -} -``` - -Bir örnek oluşturmaya çalıştığınızda, sınıfın statik olduğunu belirten `Error` istisnası atılır. - - Tarihe Bir Bakış .[#toc-a-look-into-the-history] ================================================ diff --git a/utils/tr/staticclass.texy b/utils/tr/staticclass.texy new file mode 100644 index 0000000000..15fc8950d6 --- /dev/null +++ b/utils/tr/staticclass.texy @@ -0,0 +1,21 @@ +Statik Sınıflar +*************** + +.[perex] +StaticClass statik sınıfları belirtmek için kullanılır. + + +Kurulum: + +```shell +composer require nette/utils +``` + +Statik sınıflar, yani örneklenmesi amaçlanmayan sınıflar, [api:Nette\StaticClass] özelliği ile işaretlenebilir: + +```php +class Strings +{ + use Nette\StaticClass; +} +``` diff --git a/utils/uk/@home.texy b/utils/uk/@home.texy index da37bd7e7d..5db9800444 100644 --- a/utils/uk/@home.texy +++ b/utils/uk/@home.texy @@ -11,7 +11,6 @@ | [Генерація випадкових рядків |random] | Nette\Utils\Random | [Дата і час |datetime] | Nette\Utils\DateTime | [Зображення |images] | Nette\Utils\Image -| [Модель об'єкта |smartobject] | Nette\SmartObject & Nette\StaticClass | [Пагінація |paginator] | Nette\Utils\Paginator | [Парсинг і генерація JSON |json] | Nette\Utils\Json | [Поле |arrays] | Nette\Utils\Arrays @@ -20,6 +19,7 @@ | [Файлова система |filesystem] | Nette\Utils\FileSystem | [Функції-помічники |helpers] | Nette\Utils\Helpers | [Елементи HTML |html-elements] | Nette\Utils\Html +| [SmartObject] & [StaticClass] | Nette\SmartObject & Nette\StaticClass | [PHP Відображення |reflection] | Nette\Utils\Reflection diff --git a/utils/uk/@left-menu.texy b/utils/uk/@left-menu.texy index 6f4022e2d2..69dc75a6e1 100644 --- a/utils/uk/@left-menu.texy +++ b/utils/uk/@left-menu.texy @@ -15,8 +15,9 @@ - [Файлова система |filesystem] - [Функції-помічники |helpers] - [Елементи HTML |html-elements] +- [SmartObject] +- [StaticClass] - [PHP Відображення |reflection] -- [SmartObject |smartobject] Інші інструменти diff --git a/utils/uk/smartobject.texy b/utils/uk/smartobject.texy index 4695c2fde2..e57ca2cee5 100644 --- a/utils/uk/smartobject.texy +++ b/utils/uk/smartobject.texy @@ -1,8 +1,8 @@ -SmartObject і StaticClass -************************* +SmartObject +*********** .[perex] -SmartObject додає підтримку *властивостей* у класи PHP. StaticClass використовується для позначення статичних класів. +Раніше SmartObject виправляв поведінку об'єктів багатьма способами, але сьогоднішній PHP вже містить більшість з цих покращень вбудовано. Проте, він все ще додає підтримку *property*. Встановлення: @@ -65,21 +65,6 @@ echo $circle->visible; // викликаємо isVisible() Властивості - це насамперед "синтаксичний цукор"((syntactic sugar)), який покликаний зробити життя програміста солодшим за рахунок спрощення коду. Якщо вони вам не потрібні, ви не зобов'язані їх використовувати. -Статичні класи .[#toc-static-classes] -===================================== - -Статичні класи, тобто класи, які не призначені для інстанціювання, можуть бути позначені ознакою `Nette\StaticClass`: - -```php -class Strings -{ - use Nette\StaticClass; -} -``` - -Коли ви намагаєтеся створити екземпляр, виникає виняток `Error`, який вказує на те, що клас є статичним. - - Погляд в історію .[#toc-a-look-into-the-history] ================================================ diff --git a/utils/uk/staticclass.texy b/utils/uk/staticclass.texy new file mode 100644 index 0000000000..585730463f --- /dev/null +++ b/utils/uk/staticclass.texy @@ -0,0 +1,21 @@ +Статичні класи +************** + +.[perex] +StaticClass використовується для позначення статичних класів. + + +Встановлення: + +```shell +composer require nette/utils +``` + +Статичні класи, тобто класи, які не призначені для екземплярів, можна позначити ознакою [api:Nette\StaticClass]: + +```php +class Strings +{ + use Nette\StaticClass; +} +``` From bdeca628f1f289730d195a831b88de1693b2d609 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 12 Sep 2023 08:18:39 +0200 Subject: [PATCH 005/137] improved smartobject --- utils/bg/smartobject.texy | 18 +++++++-------- utils/cs/smartobject.texy | 6 ++--- utils/de/smartobject.texy | 18 +++++++-------- utils/el/smartobject.texy | 18 +++++++-------- utils/en/smartobject.texy | 46 +++++++++++++++++++-------------------- utils/es/smartobject.texy | 18 +++++++-------- utils/fr/smartobject.texy | 18 +++++++-------- utils/hu/smartobject.texy | 18 +++++++-------- utils/it/smartobject.texy | 16 +++++++------- utils/pl/smartobject.texy | 18 +++++++-------- utils/pt/smartobject.texy | 18 +++++++-------- utils/ro/smartobject.texy | 16 +++++++------- utils/ru/smartobject.texy | 18 +++++++-------- utils/sl/smartobject.texy | 18 +++++++-------- utils/tr/smartobject.texy | 16 +++++++------- utils/uk/smartobject.texy | 18 +++++++-------- 16 files changed, 149 insertions(+), 149 deletions(-) diff --git a/utils/bg/smartobject.texy b/utils/bg/smartobject.texy index 89997e6857..9e32435002 100644 --- a/utils/bg/smartobject.texy +++ b/utils/bg/smartobject.texy @@ -65,16 +65,16 @@ echo $circle->visible; // извиква isVisible() Свойствата са преди всичко "синтактична захар" и са предназначени да направят живота на програмиста по-сладък, като опростят кода. Ако нямате нужда от тях, не е нужно да ги използвате. -Поглед към историята .[#toc-a-look-into-the-history] -==================================================== +Поглед към историята .[#toc-a-glimpse-into-history] +=================================================== -SmartObject е използван за подобряване и коригиране на поведението на класовете по много начини, но развитието на PHP направи повечето от първоначалните функции излишни. Затова по-долу ще разгледаме историята на развитието на тези функции. +SmartObject усъвършенстваше поведението на обектите по множество начини, но днес PHP вече включва повечето от тези подобрения на роден език. Следващият текст е носталгичен поглед назад към историята, който ни напомня как са се развивали нещата. -От самото начало обектният модел на PHP страдаше от някои сериозни недостатъци и неефективност. Това доведе до създаването на класа `Nette\Object` (през 2007 г.), който се опита да коригира тези проблеми и да подобри работата на потребителите на PHP. Това беше достатъчно, за да могат други класове да го наследят и да се възползват от предимствата му. Когато в PHP 5.4 беше въведена поддръжка на черти, класът `Nette\Object` беше заменен с `Nette\SmartObject`. По този начин вече не е било необходимо да се наследява от общ прародител. Освен това чертата може да се използва в класове, които вече са наследени от друг клас. Окончателният край на `Nette\Object` настъпи с излизането на PHP 7.2, който забрани именуването на класове `Object`. +От самото си създаване обектният модел на PHP страдаше от множество сериозни недостатъци и пропуски. Това доведе до създаването на класа `Nette\Object` (през 2007 г.), който имаше за цел да поправи тези проблеми и да повиши удобството при използването на PHP. Всичко, което беше необходимо, беше други класове да наследят от него и да получат предимствата, които той предлагаше. Когато PHP 5.4 въведе поддръжка на черти, класът `Nette\Object` беше заменен с чертата `Nette\SmartObject`. Това премахна необходимостта от наследяване от общ предшественик. Освен това чертата можеше да се използва в класове, които вече наследяваха от друг клас. Окончателният край на `Nette\Object` настъпи с излизането на PHP 7.2, който забрани на класовете да се наричат `Object`. -С развитието на PHP обектният модел и функциите на езика се усъвършенстваха. Някои характеристики на класа `SmartObject` станаха излишни. След излизането на PHP 8.2 единствената функция, която все още не се поддържа директно в PHP, е възможността за използване на т.нар. [свойства |#Properties, getters and setters]. +С развитието на PHP обектният модел и възможностите на езика се усъвършенстваха. Различните функции на класа `SmartObject` станаха излишни. След излизането на PHP 8.2 остана само една функция, която не се поддържа директно в PHP: възможността да се използват така наречените [свойства |#Properties, getters, and setters]. -Какви функции предлагат `Nette\Object` и `Nette\Object`? Ето един преглед. (В примерите е използван класът `Nette\Object`, но повечето от свойствата се отнасят и за `Nette\SmartObject` ). +Какви функции предлагаха `Nette\Object` и, като следствие, `Nette\SmartObject`? Ето един преглед. (В примерите е използван класът `Nette\Object`, но повечето функции се отнасят и за признака `Nette\SmartObject` ). Непоследователни грешки .[#toc-inconsistent-errors] @@ -114,7 +114,7 @@ $foo = Foo::form($var); // "Call to undefined static method Foo::form(), did you mean from()?" ``` -Съвременният PHP може и да не разполага с формата "Искахте ли да кажете?", но [Трейси |tracy:] добавя тази добавка към грешките. Той дори може сам да [коригира |tracy:open-files-in-ide#toc-demos] такива грешки. +Въпреки че днешният PHP не разполага с функция "Искахте ли да кажете?", тази фраза може да бъде добавена към грешките от [Tracy |tracy:]. Тя дори може да [коригира такива грешки автоматично |tracy:open-files-in-ide#toc-demos]. Методи за разширение .[#toc-extension-methods] @@ -158,7 +158,7 @@ class Foo extends Nette\Object $obj = new Foo; $reflection = $obj->getReflection(); -$reflection->getAnnotation('author'); // връща 'John Doe +$reflection->getAnnotation('author'); // връща 'John Doe' ``` От версия 8.0 на PHP вече е възможен достъп до метаинформация под формата на атрибути: @@ -216,7 +216,7 @@ class Circle extends Nette\Object public function setRadius(float $radius): void { $this->onChange($this, $radius); - $this->radius = $radius + $this->radius = $radius; } } ``` diff --git a/utils/cs/smartobject.texy b/utils/cs/smartobject.texy index a7cc76b200..7aeca5b7b2 100644 --- a/utils/cs/smartobject.texy +++ b/utils/cs/smartobject.texy @@ -68,7 +68,7 @@ Properties jsou především "syntaktickým cukříkem"((syntactic sugar)), jeho Pohled do historie ================== -SmartObject dříve vylepšovala a opravovala chování tříd v mnoha směrech, ale díky vývoji PHP se většina původních funkcí stala zbytečnou. Následující text je tak pohledem do historie, jak se věci vyvíjely. +SmartObject opravovala chování objektů v mnoha směrech, ale dnešní PHP již obsahuje většinu vylepšení nativně. Následující text je tak nostalgickým pohledem do historie a připomínkou toho, jak se věci vyvíjely. Objektový model PHP trpěl od počátku celou řadou vážných nedostatků a necnostní. To byl důvod vzniku třídy `Nette\Object` (v roce 2007), která se je pokoušela napravovat a zlepšit komfort při používání PHP. Stačilo, aby ostatní třídy od ní dědily, a získaly výhody, které přinášela. Když PHP 5.4 přišlo s podporou trait, byla třída `Nette\Object` nahrazena traitou `Nette\SmartObject`. Nebylo tak nutné už dědit od společného předka. Navíc traita se dala použít i ve třídách, které již dědily od jiné třídy. Definitivní konec `Nette\Object` přišel s vydáním PHP 7.2, které zakázalo třídám jmenovat se `Object`. @@ -158,7 +158,7 @@ class Foo extends Nette\Object $obj = new Foo; $reflection = $obj->getReflection(); -$reflection->getAnnotation('author'); // vrátí 'John Doe +$reflection->getAnnotation('author'); // vrátí 'John Doe' ``` Od PHP 8.0 je možné přistupovat k metainformacím v podobě atributů: @@ -216,7 +216,7 @@ class Circle extends Nette\Object public function setRadius(float $radius): void { $this->onChange($this, $radius); - $this->radius = $radius + $this->radius = $radius; } } ``` diff --git a/utils/de/smartobject.texy b/utils/de/smartobject.texy index 3ea9f4b074..65643bc2e0 100644 --- a/utils/de/smartobject.texy +++ b/utils/de/smartobject.texy @@ -65,16 +65,16 @@ echo $circle->visible; // calls isVisible() Eigenschaften sind in erster Linie "syntaktischer Zucker" ((syntactic sugar)), der das Leben des Programmierers durch Vereinfachung des Codes versüßen soll. Wenn Sie sie nicht wollen, müssen Sie sie nicht verwenden. -Ein Blick in die Geschichte .[#toc-a-look-into-the-history] -=========================================================== +Ein Blick in die Geschichte .[#toc-a-glimpse-into-history] +========================================================== -SmartObject hat das Verhalten von Klassen in vielerlei Hinsicht verbessert und korrigiert, aber die Entwicklung von PHP hat die meisten der ursprünglichen Funktionen überflüssig gemacht. Im Folgenden werfen wir einen Blick in die Geschichte, wie sich die Dinge entwickelt haben. +SmartObject verfeinerte das Verhalten von Objekten auf zahlreiche Arten, aber das heutige PHP enthält die meisten dieser Erweiterungen bereits von Haus aus. Der folgende Text ist ein nostalgischer Blick zurück in die Geschichte, der uns daran erinnert, wie sich die Dinge entwickelt haben. -Von Anfang an litt das PHP-Objektmodell unter einer Reihe von schwerwiegenden Mängeln und Ineffizienzen. Dies war der Grund für die Schaffung der Klasse `Nette\Object` (im Jahr 2007), mit der versucht wurde, diese zu beheben und die Benutzung von PHP zu verbessern. Es reichte aus, dass andere Klassen von ihr erbten und von den Vorteilen profitierten, die sie mit sich brachte. Als PHP 5.4 mit Trait-Unterstützung kam, wurde die Klasse `Nette\Object` durch `Nette\SmartObject` ersetzt. Somit war es nicht mehr notwendig, von einem gemeinsamen Vorfahren zu erben. Darüber hinaus konnte Trait in Klassen verwendet werden, die bereits von einer anderen Klasse geerbt hatten. Das endgültige Ende von `Nette\Object` kam mit der Veröffentlichung von PHP 7.2, die es verbot, Klassen den Namen `Object` zu geben. +Seit seinen Anfängen litt das Objektmodell von PHP unter einer Vielzahl von ernsthaften Mängeln und Unzulänglichkeiten. Dies führte zur Schaffung der Klasse `Nette\Object` (im Jahr 2007), die diese Probleme beheben und den Komfort bei der Verwendung von PHP erhöhen sollte. Andere Klassen brauchten nur von dieser Klasse zu erben, um die Vorteile zu nutzen, die sie bot. Als mit PHP 5.4 die Unterstützung für Traits eingeführt wurde, wurde die Klasse `Nette\Object` durch den Trait `Nette\SmartObject` ersetzt. Damit entfiel die Notwendigkeit, von einem gemeinsamen Vorfahren zu erben. Außerdem konnte der Trait in Klassen verwendet werden, die bereits von einer anderen Klasse geerbt hatten. Das endgültige Ende von `Nette\Object` kam mit der Veröffentlichung von PHP 7.2, die es verbot, Klassen den Namen `Object` zu geben. -Im weiteren Verlauf der PHP-Entwicklung wurden das Objektmodell und die Sprachfähigkeiten verbessert. Die einzelnen Funktionen der Klasse `SmartObject` wurden überflüssig. Seit der Veröffentlichung von PHP 8.2 ist die einzige Funktion, die noch nicht direkt in PHP unterstützt wird, die Möglichkeit, sogenannte [Properties |#Properties, getters and setters] zu verwenden. +Mit der weiteren Entwicklung von PHP wurden das Objektmodell und die Sprachfähigkeiten verbessert. Verschiedene Funktionen der Klasse `SmartObject` wurden überflüssig. Seit der Veröffentlichung von PHP 8.2 gibt es nur noch eine Funktion, die in PHP nicht direkt unterstützt wird: die Möglichkeit, so genannte [Properties |#Properties, getters, and setters] zu verwenden. -Welche Funktionen boten `Nette\Object` und `Nette\Object` früher? Hier ist ein Überblick. (Die Beispiele verwenden die Klasse `Nette\Object`, aber die meisten der Eigenschaften gelten auch für die Eigenschaft `Nette\SmartObject` ). +Welche Funktionen boten `Nette\Object` und in der Folge `Nette\SmartObject`? Hier ist ein Überblick. (In den Beispielen wird die Klasse `Nette\Object` verwendet, aber die meisten Funktionen gelten auch für den Trait `Nette\SmartObject` ). Inkonsistente Fehler .[#toc-inconsistent-errors] @@ -114,7 +114,7 @@ $foo = Foo::form($var); // "Call to undefined static method Foo::form(), did you mean from()?" ``` -Das heutige PHP hat zwar keine Form von "did you mean?", aber [Tracy |tracy:] fügt diesen Zusatz zu Fehlern hinzu. Und es kann solche Fehler sogar selbst [beheben |tracy:open-files-in-ide#toc-demos]. +Das heutige PHP hat zwar keine "Meinten Sie?"-Funktion, aber dieser Satz kann von [Tracy |tracy:] zu Fehlern hinzugefügt werden. Es kann [solche Fehler |tracy:open-files-in-ide#toc-demos] sogar [automatisch korrigieren |tracy:open-files-in-ide#toc-demos]. Erweiterungsmethoden .[#toc-extension-methods] @@ -158,7 +158,7 @@ class Foo extends Nette\Object $obj = new Foo; $reflection = $obj->getReflection(); -$reflection->getAnnotation('author'); // returns 'John Doe +$reflection->getAnnotation('author'); // returns 'John Doe' ``` Seit PHP 8.0 ist es möglich, auf Metainformationen in Form von Attributen zuzugreifen: @@ -216,7 +216,7 @@ class Circle extends Nette\Object public function setRadius(float $radius): void { $this->onChange($this, $radius); - $this->radius = $radius + $this->radius = $radius; } } ``` diff --git a/utils/el/smartobject.texy b/utils/el/smartobject.texy index 54e24aa5fd..e73cc73d15 100644 --- a/utils/el/smartobject.texy +++ b/utils/el/smartobject.texy @@ -65,16 +65,16 @@ echo $circle->visible; // καλεί την isVisible() Οι ιδιότητες είναι κατά κύριο λόγο "συντακτική ζάχαρη"((syntactic sugar)), η οποία έχει σκοπό να κάνει τη ζωή του προγραμματιστή πιο γλυκιά απλοποιώντας τον κώδικα. Αν δεν τις θέλετε, δεν χρειάζεται να τις χρησιμοποιήσετε. -Μια ματιά στην ιστορία .[#toc-a-look-into-the-history] -====================================================== +Μια ματιά στην ιστορία .[#toc-a-glimpse-into-history] +===================================================== -Το SmartObject βελτίωνε και διόρθωνε τη συμπεριφορά των κλάσεων με πολλούς τρόπους, αλλά η εξέλιξη της PHP έχει καταστήσει τα περισσότερα από τα αρχικά χαρακτηριστικά περιττά. Έτσι, το παρακάτω είναι μια ματιά στην ιστορία της εξέλιξης των πραγμάτων. +Το SmartObject χρησιμοποιείται για να βελτιώσει τη συμπεριφορά των αντικειμένων με πολλούς τρόπους, αλλά η σημερινή PHP ενσωματώνει ήδη τις περισσότερες από αυτές τις βελτιώσεις εγγενώς. Το κείμενο που ακολουθεί είναι μια νοσταλγική αναδρομή στην ιστορία, υπενθυμίζοντάς μας πώς εξελίχθηκαν τα πράγματα. -Από την αρχή, το μοντέλο αντικειμένων της PHP υπέφερε από μια σειρά σοβαρών ελαττωμάτων και αναποτελεσματικότητας. Αυτός ήταν ο λόγος για τη δημιουργία της κλάσης `Nette\Object` (το 2007), η οποία προσπάθησε να τις διορθώσει και να βελτιώσει την εμπειρία χρήσης της PHP. Ήταν αρκετό για να κληρονομήσουν και άλλες κλάσεις από αυτήν και να αποκτήσουν τα οφέλη που έφερε. Όταν η PHP 5.4 ήρθε με υποστήριξη γνωρισμάτων, η κλάση `Nette\Object` αντικαταστάθηκε από την `Nette\SmartObject`. Έτσι, δεν ήταν πλέον απαραίτητη η κληρονομικότητα από έναν κοινό πρόγονο. Επιπλέον, το trait μπορούσε να χρησιμοποιηθεί σε κλάσεις που ήδη κληρονομούσαν από μια άλλη κλάση. Το οριστικό τέλος της `Nette\Object` ήρθε με την κυκλοφορία της PHP 7.2, η οποία απαγόρευσε στις κλάσεις να έχουν το όνομα `Object`. +Από την αρχή της δημιουργίας του, το μοντέλο αντικειμένων της PHP υπέφερε από μυριάδες σοβαρές ελλείψεις και αδυναμίες. Αυτό οδήγησε στη δημιουργία της κλάσης `Nette\Object` (το 2007), η οποία είχε ως στόχο να διορθώσει αυτά τα προβλήματα και να βελτιώσει την άνεση της χρήσης της PHP. Το μόνο που χρειαζόταν ήταν άλλες κλάσεις να κληρονομήσουν από αυτήν και θα αποκτούσαν τα οφέλη που προσέφερε. Όταν η PHP 5.4 εισήγαγε την υποστήριξη για γνωρίσματα, η κλάση `Nette\Object` αντικαταστάθηκε από το γνώρισμα `Nette\SmartObject`. Αυτό εξάλειψε την ανάγκη να κληρονομήσετε από έναν κοινό πρόγονο. Επιπλέον, το γνώρισμα μπορούσε να χρησιμοποιηθεί σε κλάσεις που ήδη κληρονομούσαν από μια άλλη κλάση. Το οριστικό τέλος του `Nette\Object` ήρθε με την κυκλοφορία της PHP 7.2, η οποία απαγόρευσε στις κλάσεις να ονομάζονται `Object`. -Καθώς η ανάπτυξη της PHP προχωρούσε, το μοντέλο αντικειμένων και οι δυνατότητες της γλώσσας βελτιώνονταν. Οι επιμέρους λειτουργίες της κλάσης `SmartObject` έγιναν περιττές. Από την έκδοση της PHP 8.2, το μόνο χαρακτηριστικό που παραμένει και δεν υποστηρίζεται ακόμη άμεσα από την PHP είναι η δυνατότητα χρήσης των λεγόμενων [ιδιοτήτων |#Properties, Getters and Setters]. +Καθώς η ανάπτυξη της PHP συνεχιζόταν, το μοντέλο αντικειμένων και οι δυνατότητες της γλώσσας βελτιώνονταν. Διάφορες λειτουργίες της κλάσης `SmartObject` έγιναν περιττές. Από την έκδοση της PHP 8.2, παραμένει μόνο ένα χαρακτηριστικό που δεν υποστηρίζεται άμεσα στην PHP: η δυνατότητα χρήσης των λεγόμενων [ιδιοτήτων |#Properties, getters, and setters]. -Ποια χαρακτηριστικά προσέφεραν κάποτε οι `Nette\Object` και `Nette\Object`; Ακολουθεί μια επισκόπηση. (Τα παραδείγματα χρησιμοποιούν την κλάση `Nette\Object`, αλλά οι περισσότερες από τις ιδιότητες ισχύουν και για την ιδιότητα `Nette\SmartObject` ). +Ποια χαρακτηριστικά προσέφερε η `Nette\Object` και, κατ' επέκταση, η `Nette\SmartObject`; Ακολουθεί μια επισκόπηση. (Στα παραδείγματα χρησιμοποιείται η κλάση `Nette\Object`, αλλά τα περισσότερα χαρακτηριστικά ισχύουν και για την ιδιότητα `Nette\SmartObject` ). Ασυνεπή σφάλματα .[#toc-inconsistent-errors] @@ -114,7 +114,7 @@ $foo = Foo::form($var); // "Call to undefined static method Foo::form(), did you mean from()?" ``` -Η σημερινή PHP μπορεί να μην έχει καμία μορφή του "did you mean?", αλλά [η Tracy |tracy:] προσθέτει αυτή την προσθήκη στα σφάλματα. Και μπορεί ακόμη και να [διορθώσει |tracy:open-files-in-ide#toc-demos] η ίδια τέτοια σφάλματα. +Αν και η σημερινή PHP δεν διαθέτει τη δυνατότητα "εννοούσατε;", αυτή η φράση μπορεί να προστεθεί στα σφάλματα από [την Tracy |tracy:]. Μπορεί ακόμη και να [διορθώσει αυτόματα τέτοια σφάλματα |tracy:open-files-in-ide#toc-demos]. Μέθοδοι επέκτασης .[#toc-extension-methods] @@ -158,7 +158,7 @@ class Foo extends Nette\Object $obj = new Foo; $reflection = $obj->getReflection(); -$reflection->getAnnotation('author'); // returns 'John Doe +$reflection->getAnnotation('author'); // returns 'John Doe' ``` Από την PHP 8.0, είναι δυνατή η πρόσβαση σε μετα-πληροφορίες με τη μορφή χαρακτηριστικών: @@ -216,7 +216,7 @@ class Circle extends Nette\Object public function setRadius(float $radius): void { $this->onChange($this, $radius); - $this->radius = $radius + $this->radius = $radius; } } ``` diff --git a/utils/en/smartobject.texy b/utils/en/smartobject.texy index a45751b3d1..27ec6370bb 100644 --- a/utils/en/smartobject.texy +++ b/utils/en/smartobject.texy @@ -2,7 +2,7 @@ SmartObject *********** .[perex] -SmartObject used to fix objects behavior in many ways, but today's PHP already includes most of these improvements natively. However, it still adds support for *property*. +SmartObject used to fix objects behavior in many ways, but today's PHP already includes most of these improvements natively. However, it still adds support for *properties*. Installation: @@ -65,16 +65,16 @@ echo $circle->visible; // calls isVisible() Properties are primarily "syntactic sugar"((syntactic sugar)), which is intended to make the programmer's life sweeter by simplifying the code. If you don't want them, you don't have to use them. -A Look into the History -======================= +A Glimpse into History +====================== -SmartObject used to improve and fix class behavior in many ways, but the evolution of PHP has made most of the original features redundant. So the following is a look into the history of how things have evolved. +SmartObject used to refine the behavior of objects in numerous ways, but today's PHP already incorporates most of these enhancements natively. The following text is a nostalgic look back at history, reminding us of how things evolved. -From the beginning, the PHP object model suffered from a number of serious flaws and inefficiencies. This was the reason for the creation of the `Nette\Object` class (in 2007), which attempted to remedy them and improve the experience of using PHP. It was enough for other classes to inherit from it, and gain the benefits it brought. When PHP 5.4 came with trait support, the `Nette\Object` class was replaced by `Nette\SmartObject`. Thus, it was no longer necessary to inherit from a common ancestor. In addition, trait could be used in classes that already inherited from another class. The final end of `Nette\Object` came with the release of PHP 7.2, which forbade classes to be named `Object`. +From its inception, PHP's object model suffered from a myriad of serious shortcomings and deficiencies. This led to the creation of the `Nette\Object` class (in 2007), which aimed to rectify these issues and enhance the comfort of using PHP. All that was needed was for other classes to inherit from it, and they would gain the benefits it offered. When PHP 5.4 introduced support for traits, the `Nette\Object` class was replaced by the `Nette\SmartObject` trait. This eliminated the need to inherit from a common ancestor. Moreover, the trait could be used in classes that already inherited from another class. The definitive end of `Nette\Object` came with the release of PHP 7.2, which prohibited classes from being named `Object`. -As PHP development went on, the object model and language capabilities were improved. The individual functions of the `SmartObject` class became redundant. Since the release of PHP 8.2, the only feature that remains that is not yet directly supported in PHP is the ability to use so-called [properties |#Properties, Getters and Setters]. +As PHP development continued, its object model and language capabilities improved. Various functions of the `SmartObject` class became redundant. Since the release of PHP 8.2, there remains only one feature not directly supported in PHP: the ability to use so-called [properties|#Properties, getters, and setters]. -What features did `Nette\Object` and `Nette\Object` once offer? Here is an overview. (The examples use the `Nette\Object` class, but most of the properties also apply to the `Nette\SmartObject` trait.) +What features did `Nette\Object` and, by extension, `Nette\SmartObject` offer? Here's an overview. (In the examples, the `Nette\Object` class is used, but most features also apply to the `Nette\SmartObject` trait). Inconsistent Errors @@ -87,14 +87,14 @@ $obj->undeclared = 1; // passes silently without reporting $obj->unknownMethod(); // Fatal error (not catchable by try/catch) ``` -Fatal error terminated the application without any possibility to react. Silently writing to non-existent members without warning could lead to serious errors that were difficult to detect. `Nette\Object` All of these cases were caught and an exception `MemberAccessException` was thrown. +A fatal error would terminate the application without any chance of response. Silently writing to non-existent members without warning could lead to serious errors that were hard to detect. `Nette\Object` caught all these cases and threw a `MemberAccessException` exception. ```php -echo $obj->undeclared; // throw Nette\MemberAccessException -$obj->undeclared = 1; // throw Nette\MemberAccessException -$obj->unknownMethod(); // throw Nette\MemberAccessException +echo $obj->undeclared; // throws Nette\MemberAccessException +$obj->undeclared = 1; // throws Nette\MemberAccessException +$obj->unknownMethod(); // throws Nette\MemberAccessException ``` -Since PHP 7.0, PHP no longer causes not catchable fatal errors, and accessing undeclared members has been a bug since PHP 8.2. +From PHP version 7.0 onwards, uncatchable fatal errors no longer occur, and accessing undeclared members becomes an error from PHP 8.2. Did you mean? @@ -110,16 +110,16 @@ class Foo extends Nette\Object } $foo = Foo::form($var); -// throw Nette\MemberAccessException +// throws Nette\MemberAccessException // "Call to undefined static method Foo::form(), did you mean from()?" ``` -Today's PHP may not have any form of "did you mean?", but [Tracy |tracy:] adds this addendum to errors. And it can even [fix |tracy:open-files-in-ide#toc-demos] such errors itself. +While today's PHP doesn't have a "did you mean?" feature, this phrase can be added to errors by [Tracy|tracy:]. It can even [auto-correct such errors|tracy:open-files-in-ide#toc-demos]. -Extension methods +Extension Methods ----------------- -Inspired by extension methods from C#. They gave the possibility to add new methods to existing classes. For example, you could add the `addDateTime()` method to a form to add your own DateTimePicker. +Inspired by the extension methods from the C# language, they provided the ability to add new methods to existing classes. For instance, you could add a `addDateTime()` method to a form, which would introduce a custom DateTimePicker. ```php Form::extensionMethod( @@ -131,15 +131,15 @@ $form = new Form; $form->addDateTime('date'); ``` -Extension methods proved to be impractical because their names was not autocompleted by editors, instead they reported that the method did not exist. Therefore, their support was discontinued. +Extension methods turned out to be impractical because their names were not suggested by editors; on the contrary, they reported that the method did not exist. Therefore, their support was discontinued. -Getting the Class Name ----------------------- +Determining the Class Name +-------------------------- ```php $class = $obj->getClass(); // using Nette\Object -$class = $obj::class; // since PHP 8.0 +$class = $obj::class; // from PHP 8.0 ``` @@ -158,7 +158,7 @@ class Foo extends Nette\Object $obj = new Foo; $reflection = $obj->getReflection(); -$reflection->getAnnotation('author'); // returns 'John Doe +$reflection->getAnnotation('author'); // returns 'John Doe' ``` As of PHP 8.0, it is possible to access meta-information in the form of attributes: @@ -216,7 +216,7 @@ class Circle extends Nette\Object public function setRadius(float $radius): void { $this->onChange($this, $radius); - $this->radius = $radius + $this->radius = $radius; } } ``` @@ -229,7 +229,7 @@ foreach ($this->onChange as $callback) { } ``` -For the sake of clarity we recommend to avoid the magic method `$this->onChange()`. A practical substitute is the [Nette\Utils\Arrays::invoke |arrays#invoke] function: +For clarity, we recommend avoiding the magic method `$this->onChange()`. A practical alternative is the [Nette\Utils\Arrays::invoke |arrays#invoke] function: ```php Nette\Utils\Arrays::invoke($this->onChange, $this, $radius); diff --git a/utils/es/smartobject.texy b/utils/es/smartobject.texy index 247743a38f..b3b4cbc5b3 100644 --- a/utils/es/smartobject.texy +++ b/utils/es/smartobject.texy @@ -65,16 +65,16 @@ echo $circle->visible; // calls isVisible() Las propiedades son principalmente "azúcar sintáctico"((syntactic sugar)), que pretende hacer la vida del programador más dulce simplificando el código. Si no las quieres, no tienes por qué usarlas. -Un vistazo a la historia .[#toc-a-look-into-the-history] -======================================================== +Un vistazo a la Historia .[#toc-a-glimpse-into-history] +======================================================= -SmartObject solía mejorar y arreglar el comportamiento de las clases de muchas maneras, pero la evolución de PHP ha hecho que la mayoría de las características originales sean redundantes. Así que lo siguiente es una mirada a la historia de cómo han evolucionado las cosas. +SmartObject solía refinar el comportamiento de los objetos de numerosas maneras, pero el PHP actual ya incorpora la mayoría de estas mejoras de forma nativa. El siguiente texto es una mirada nostálgica a la historia, recordándonos como evolucionaron las cosas. -Desde el principio, el modelo de objetos de PHP sufrió de un número de serios defectos e ineficiencias. Este fue el motivo de la creación de la clase `Nette\Object` (en 2007), que intentaba remediarlos y mejorar la experiencia de uso de PHP. Fue suficiente para que otras clases heredaran de ella y obtuvieran los beneficios que aportaba. Cuando PHP 5.4 llegó con soporte para traits, la clase `Nette\Object` fue reemplazada por `Nette\SmartObject`. Así, ya no era necesario heredar de un ancestro común. Además, trait podía usarse en clases que ya heredaban de otra clase. El fin definitivo de `Nette\Object` llegó con el lanzamiento de PHP 7.2, que prohibió que las clases se llamaran `Object`. +Desde sus inicios, el modelo de objetos de PHP sufrió de una miríada de serios defectos y deficiencias. Esto llevó a la creación de la clase `Nette\Object` (en 2007), que pretendía rectificar estos problemas y mejorar la comodidad de uso de PHP. Todo lo que se necesitaba era que otras clases heredaran de ella, y obtendrían los beneficios que ofrecía. Cuando PHP 5.4 introdujo el soporte para traits, la clase `Nette\Object` fue reemplazada por el trait `Nette\SmartObject`. Esto eliminó la necesidad de heredar de un ancestro común. Además, el trait podía ser usado en clases que ya heredaban de otra clase. El fin definitivo de `Nette\Object` llegó con el lanzamiento de PHP 7.2, que prohibió que las clases se llamaran `Object`. -A medida que avanzaba el desarrollo de PHP, el modelo de objetos y las capacidades del lenguaje fueron mejorando. Las funciones individuales de la clase `SmartObject` se volvieron redundantes. Desde el lanzamiento de PHP 8.2, la única característica que aún no está soportada directamente en PHP es la capacidad de usar las llamadas [propiedades |#Properties, getters and setters]. +A medida que el desarrollo de PHP continuaba, su modelo de objetos y las capacidades del lenguaje mejoraron. Varias funciones de la clase `SmartObject` se volvieron redundantes. Desde el lanzamiento de PHP 8.2, sólo queda una característica no soportada directamente en PHP: la capacidad de usar las llamadas [propiedades |#Properties, getters, and setters]. -¿Qué características ofrecían `Nette\Object` y `Nette\Object`? He aquí un resumen. (Los ejemplos usan la clase `Nette\Object`, pero la mayoría de las propiedades también se aplican al rasgo `Nette\SmartObject` ). +¿Qué características ofrecían `Nette\Object` y, por extensión, `Nette\SmartObject`? He aquí un resumen. (En los ejemplos, se usa la clase `Nette\Object`, pero la mayoría de las características también se aplican al rasgo `Nette\SmartObject` ). Errores incoherentes .[#toc-inconsistent-errors] @@ -114,7 +114,7 @@ $foo = Foo::form($var); // "Call to undefined static method Foo::form(), did you mean from()?" ``` -Puede que el PHP actual no tenga ninguna forma de "¿querías decir?", pero [Tracy |tracy:] añade este apéndice a los errores. E incluso puede [corregir |tracy:open-files-in-ide#toc-demos] esos errores por sí mismo. +Aunque el PHP actual no tiene la función "¿Querías decir?", esta frase puede ser añadida a los errores por [Tracy |tracy:]. Incluso puede [autocorregir dichos errores |tracy:open-files-in-ide#toc-demos]. Métodos de extensión .[#toc-extension-methods] @@ -158,7 +158,7 @@ class Foo extends Nette\Object $obj = new Foo; $reflection = $obj->getReflection(); -$reflection->getAnnotation('author'); // returns 'John Doe +$reflection->getAnnotation('author'); // returns 'John Doe' ``` A partir de PHP 8.0, es posible acceder a meta-información en forma de atributos: @@ -216,7 +216,7 @@ class Circle extends Nette\Object public function setRadius(float $radius): void { $this->onChange($this, $radius); - $this->radius = $radius + $this->radius = $radius; } } ``` diff --git a/utils/fr/smartobject.texy b/utils/fr/smartobject.texy index 01912cad49..9458d913bb 100644 --- a/utils/fr/smartobject.texy +++ b/utils/fr/smartobject.texy @@ -65,16 +65,16 @@ echo $circle->visible; // calls isVisible() Les propriétés sont principalement du "sucre syntaxique" ((sucre syntaxique)), destiné à rendre la vie du programmeur plus douce en simplifiant le code. Si vous n'en voulez pas, vous n'êtes pas obligé de les utiliser. -Un regard sur l'histoire .[#toc-a-look-into-the-history] -======================================================== +Un aperçu de l'histoire .[#toc-a-glimpse-into-history] +====================================================== -SmartObject améliorait et corrigeait le comportement des classes de plusieurs façons, mais l'évolution de PHP a rendu la plupart des fonctionnalités originales superflues. Ce qui suit est donc un regard sur l'histoire de l'évolution des choses. +SmartObject permettait d'affiner le comportement des objets de nombreuses manières, mais le PHP d'aujourd'hui incorpore déjà la plupart de ces améliorations de manière native. Le texte suivant est un regard nostalgique sur l'histoire, nous rappelant comment les choses ont évolué. -Dès le début, le modèle objet de PHP a souffert d'un certain nombre de défauts sérieux et d'inefficacités. C'est la raison de la création de la classe `Nette\Object` (en 2007), qui a tenté d'y remédier et d'améliorer l'expérience d'utilisation de PHP. Il a suffi que d'autres classes héritent d'elle pour bénéficier de ses avantages. Lorsque PHP 5.4 a intégré le support des traits, la classe `Nette\Object` a été remplacée par `Nette\SmartObject`. Ainsi, il n'était plus nécessaire d'hériter d'un ancêtre commun. De plus, les traits pouvaient être utilisés dans des classes qui héritaient déjà d'une autre classe. La fin définitive de `Nette\Object` est intervenue avec la sortie de PHP 7.2, qui interdisait aux classes d'être nommées `Object`. +Dès le début, le modèle objet de PHP a souffert d'une myriade de lacunes et de déficiences. Cela a conduit à la création de la classe `Nette\Object` (en 2007), qui visait à corriger ces problèmes et à améliorer le confort d'utilisation de PHP. Il suffisait que d'autres classes héritent de cette classe pour bénéficier des avantages qu'elle offrait. Lorsque PHP 5.4 a introduit le support des traits, la classe `Nette\Object` a été remplacée par le trait `Nette\SmartObject`. Cela a éliminé le besoin d'hériter d'un ancêtre commun. De plus, le trait pouvait être utilisé dans des classes qui héritaient déjà d'une autre classe. La fin définitive de `Nette\Object` est intervenue avec la publication de PHP 7.2, qui a interdit aux classes d'être nommées `Object`. -Au fur et à mesure du développement de PHP, le modèle objet et les capacités du langage ont été améliorés. Les fonctions individuelles de la classe `SmartObject` sont devenues redondantes. Depuis la version 8.2 de PHP, la seule fonctionnalité qui n'est pas encore directement supportée par PHP est la possibilité d'utiliser des [propriétés |#Properties, getters and setters]. +Au fur et à mesure du développement de PHP, le modèle d'objet et les capacités du langage se sont améliorés. Plusieurs fonctions de la classe `SmartObject` sont devenues redondantes. Depuis la sortie de PHP 8.2, il ne reste plus qu'une seule fonctionnalité non directement supportée par PHP : la possibilité d'utiliser ce que l'on appelle des [propriétés |#Properties, getters, and setters]. -Quelles fonctionnalités offraient autrefois `Nette\Object` et `Nette\Object`? En voici un aperçu. (Les exemples utilisent la classe `Nette\Object`, mais la plupart des propriétés s'appliquent également au trait `Nette\SmartObject` ). +Quelles sont les fonctionnalités offertes par `Nette\Object` et, par extension, par `Nette\SmartObject`? En voici un aperçu. (Dans les exemples, la classe `Nette\Object` est utilisée, mais la plupart des fonctionnalités s'appliquent également au trait `Nette\SmartObject` ). Erreurs de cohérence .[#toc-inconsistent-errors] @@ -114,7 +114,7 @@ $foo = Foo::form($var); // "Call to undefined static method Foo::form(), did you mean from()?" ``` -Le PHP d'aujourd'hui n'a peut-être pas de forme de "did you mean ?", mais [Tracy |tracy:] ajoute cet addendum aux erreurs. Et il peut même [corriger |tracy:open-files-in-ide#toc-demos] ces erreurs lui-même. +Bien que le PHP d'aujourd'hui n'ait pas de fonction "did you mean ?", cette phrase peut être ajoutée aux erreurs par [Tracy |tracy:]. Il peut même [corriger automatiquement ces erreurs |tracy:open-files-in-ide#toc-demos]. Méthodes d'extension .[#toc-extension-methods] @@ -158,7 +158,7 @@ class Foo extends Nette\Object $obj = new Foo; $reflection = $obj->getReflection(); -$reflection->getAnnotation('author'); // returns 'John Doe +$reflection->getAnnotation('author'); // returns 'John Doe' ``` Depuis PHP 8.0, il est possible d'accéder aux méta-informations sous forme d'attributs : @@ -216,7 +216,7 @@ class Circle extends Nette\Object public function setRadius(float $radius): void { $this->onChange($this, $radius); - $this->radius = $radius + $this->radius = $radius; } } ``` diff --git a/utils/hu/smartobject.texy b/utils/hu/smartobject.texy index a050640455..eb81664c98 100644 --- a/utils/hu/smartobject.texy +++ b/utils/hu/smartobject.texy @@ -65,16 +65,16 @@ echo $circle->visible; // hívja az isVisible() függvényt A tulajdonságok elsősorban "szintaktikai cukor"((syntactic sugar)), amelynek célja, hogy a kód egyszerűsítésével megédesítse a programozó életét. Ha nem akarod őket, nem kell használni őket. -Egy pillantás a történelembe .[#toc-a-look-into-the-history] -============================================================ +Pillantás a történelembe .[#toc-a-glimpse-into-history] +======================================================= -A SmartObject korábban sokféleképpen javította és javította az osztályok viselkedését, de a PHP fejlődése az eredeti funkciók nagy részét feleslegessé tette. A következőkben tehát a dolgok fejlődésének történetébe pillantunk bele. +A SmartObject korábban számos módon finomította az objektumok viselkedését, de a mai PHP már natívan tartalmazza ezen fejlesztések nagy részét. A következő szöveg egy nosztalgikus visszatekintés a történelembe, emlékeztetve minket a dolgok fejlődésére. -A PHP objektummodellje a kezdetektől fogva számos komoly hibától és hiányosságtól szenvedett. Ez volt az oka a `Nette\Object` osztály létrehozásának (2007-ben), amely megpróbálta ezeket orvosolni és javítani a PHP használatának élményét. Ez elég volt ahhoz, hogy más osztályok is örököljenek belőle, és elnyerjék az általa nyújtott előnyöket. Amikor a PHP 5.4-ben megjelent a trait-támogatás, a `Nette\Object` osztályt a `Nette\SmartObject` osztály váltotta fel. Így már nem volt szükség arra, hogy egy közös őstől örököljenek. Ráadásul a trait olyan osztályokban is használható volt, amelyek már egy másik osztálytól örököltek. A `Nette\Object` végleges végét a PHP 7.2 kiadása jelentette, amely megtiltotta az osztályok `Object` nevének használatát. +A PHP objektummodellje a kezdetektől fogva számtalan komoly hiányosságtól és hiányosságtól szenvedett. Ez vezetett a `Nette\Object` osztály létrehozásához (2007-ben), amelynek célja ezen problémák orvoslása és a PHP használatának kényelmesebbé tétele volt. Mindössze arra volt szükség, hogy más osztályok is örököljenek belőle, és máris élvezhették az általa kínált előnyöket. Amikor a PHP 5.4 bevezette a tulajdonságok támogatását, a `Nette\Object` osztály helyébe a `Nette\SmartObject` tulajdonság lépett. Ezzel megszűnt a közös őstől való öröklés szükségessége. Sőt, a tulajdonságot olyan osztályokban is lehetett használni, amelyek már örököltek egy másik osztálytól. A `Nette\Object` végleges megszűnését a PHP 7.2 kiadása jelentette, amely megtiltotta, hogy az osztályok neve `Object` legyen. -A PHP fejlesztésének előrehaladtával az objektummodell és a nyelvi képességek tovább fejlődtek. A `SmartObject` osztály egyes függvényei feleslegessé váltak. A PHP 8.2 kiadása óta az egyetlen olyan funkció, amely megmaradt, és amelyet a PHP még nem támogat közvetlenül, az úgynevezett [tulajdonságok |#Properties, Getters and Setters] használatának lehetősége. +A PHP fejlesztésének előrehaladtával az objektummodell és a nyelvi képességek tovább fejlődtek. A `SmartObject` osztály különböző funkciói feleslegessé váltak. A PHP 8.2 kiadása óta csak egyetlen olyan funkció maradt, amelyet a PHP közvetlenül nem támogat: az úgynevezett [tulajdonságok |#Properties, getters, and setters] használatának lehetősége. -Milyen funkciókat kínált egykor a `Nette\Object` és a `Nette\Object`? Íme egy áttekintés. (A példák a `Nette\Object` osztályt használják, de a tulajdonságok többsége a `Nette\SmartObject` tulajdonságra is vonatkozik). +Milyen funkciókat kínált a `Nette\Object` és ennek folytán a `Nette\SmartObject`? Íme egy áttekintés. (A példákban a `Nette\Object` osztályt használjuk, de a legtöbb funkció a `Nette\SmartObject` tulajdonságra is vonatkozik). Inkonzisztens hibák .[#toc-inconsistent-errors] @@ -114,7 +114,7 @@ $foo = Foo::form($var); // "Call to undefined static method Foo::form(), did you mean from()?" ``` -A mai PHP-ben talán nincs a "did you mean?" semmilyen formája, de [Tracy |tracy:] ezt a kiegészítést hozzáadja a hibákhoz. És még maga is képes [kijavítani |tracy:open-files-in-ide#toc-demos] az ilyen hibákat. +Bár a mai PHP nem rendelkezik "úgy értetted?" funkcióval, ez a mondat hozzáadható a hibákhoz a [Tracy |tracy:] által. Még az [ilyen hibákat |tracy:open-files-in-ide#toc-demos] is képes [automatikusan kijavítani |tracy:open-files-in-ide#toc-demos]. Bővítési módszerek .[#toc-extension-methods] @@ -158,7 +158,7 @@ class Foo extends Nette\Object $obj = new Foo; $reflection = $obj->getReflection(); -$reflection->getAnnotation('author'); // visszaadja 'John Doe'. +$reflection->getAnnotation('author'); // visszaadja 'John Doe' ``` A PHP 8.0-tól kezdve a metainformációkat attribútumok formájában is elérhetjük: @@ -216,7 +216,7 @@ class Circle extends Nette\Object public function setRadius(float $radius): void { $this->onChange($this, $radius); - $this->radius = $radius + $this->radius = $radius; } } ``` diff --git a/utils/it/smartobject.texy b/utils/it/smartobject.texy index 0e5feea57c..a9247d68bc 100644 --- a/utils/it/smartobject.texy +++ b/utils/it/smartobject.texy @@ -65,16 +65,16 @@ echo $circle->visible; // chiama isVisible() Le proprietà sono principalmente "zucchero sintattico" ((syntactic sugar)), che ha lo scopo di rendere più dolce la vita del programmatore semplificando il codice. Se non le si vuole, non è necessario usarle. -Uno sguardo alla storia .[#toc-a-look-into-the-history] -======================================================= +Uno sguardo alla storia .[#toc-a-glimpse-into-history] +====================================================== -SmartObject correggeva il comportamento degli oggetti in molti modi, ma il PHP di oggi include già la maggior parte dei miglioramenti in modo nativo. Quello che segue è uno sguardo nostalgico alla storia e un promemoria di come le cose si sono evolute. +SmartObject era solito perfezionare il comportamento degli oggetti in molti modi, ma il PHP di oggi incorpora già la maggior parte di questi miglioramenti in modo nativo. Il testo che segue è uno sguardo nostalgico alla storia, che ci ricorda come si sono evolute le cose. -Fin dall'inizio, il modello a oggetti di PHP soffriva di una serie di gravi difetti e inefficienze. Questo è stato il motivo della creazione della classe `Nette\Object` (nel 2007), che ha cercato di porvi rimedio e di migliorare l'esperienza d'uso di PHP. È bastato che altre classi ereditassero da essa per trarne i benefici. Quando PHP 5.4 ha introdotto il supporto ai trait, la classe `Nette\Object` è stata sostituita da `Nette\SmartObject`. Pertanto, non era più necessario ereditare da un antenato comune. Inoltre, i trait potevano essere usati in classi che già ereditavano da un'altra classe. La fine definitiva di `Nette\Object` avvenne con il rilascio di PHP 7.2, che proibiva alle classi di chiamarsi `Object`. +Fin dall'inizio, il modello a oggetti di PHP soffriva di una miriade di gravi mancanze e carenze. Questo ha portato alla creazione della classe `Nette\Object` (nel 2007), che mirava a correggere questi problemi e a migliorare il comfort dell'utilizzo di PHP. Bastava che altre classi ereditassero da essa per ottenere i vantaggi che offriva. Quando PHP 5.4 ha introdotto il supporto ai tratti, la classe `Nette\Object` è stata sostituita dal tratto `Nette\SmartObject`. Questo ha eliminato la necessità di ereditare da un antenato comune. Inoltre, il tratto poteva essere usato in classi che già ereditavano da un'altra classe. La fine definitiva di `Nette\Object` avvenne con il rilascio di PHP 7.2, che proibiva alle classi di chiamarsi `Object`. -Con il proseguire dello sviluppo di PHP, il modello a oggetti e le funzionalità del linguaggio sono stati migliorati. Le singole funzioni della classe `SmartObject` sono diventate superflue. Dal rilascio di PHP 8.2, l'unica caratteristica rimasta che non è ancora direttamente supportata in PHP è la possibilità di usare le cosiddette [proprietà |#Properties, Getters and Setters]. +Con il proseguire dello sviluppo di PHP, il suo modello di oggetti e le capacità del linguaggio sono migliorati. Diverse funzioni della classe `SmartObject` sono diventate superflue. Dal rilascio di PHP 8.2, rimane solo una caratteristica non supportata direttamente da PHP: la possibilità di usare le cosiddette [proprietà |#Properties, getters, and setters]. -Quali funzioni offrivano un tempo `Nette\Object` e `Nette\Object`? Ecco una panoramica. (Gli esempi utilizzano la classe `Nette\Object`, ma la maggior parte delle proprietà si applicano anche al tratto `Nette\SmartObject` ). +Quali caratteristiche offrivano `Nette\Object` e, per estensione, `Nette\SmartObject`? Ecco una panoramica. (Negli esempi viene utilizzata la classe `Nette\Object`, ma la maggior parte delle caratteristiche si applicano anche al tratto `Nette\SmartObject` ). Errori inconsistenti .[#toc-inconsistent-errors] @@ -114,7 +114,7 @@ $foo = Foo::form($var); // "Call to undefined static method Foo::form(), did you mean from()?" ``` -Il PHP di oggi potrebbe non avere alcuna forma di "did you mean?", ma [Tracy |tracy:] aggiunge questa appendice agli errori. E può persino [correggere |tracy:open-files-in-ide#toc-demos] tali errori da solo. +Sebbene il PHP di oggi non disponga di una funzione di "hai inteso?", questa frase può essere aggiunta agli errori da [Tracy |tracy:]. Può anche [correggere automaticamente tali errori |tracy:open-files-in-ide#toc-demos]. Metodi di estensione .[#toc-extension-methods] @@ -216,7 +216,7 @@ class Circle extends Nette\Object public function setRadius(float $radius): void { $this->onChange($this, $radius); - $this->radius = $radius + $this->radius = $radius; } } ``` diff --git a/utils/pl/smartobject.texy b/utils/pl/smartobject.texy index d76d67d8f2..199dd1fd8c 100644 --- a/utils/pl/smartobject.texy +++ b/utils/pl/smartobject.texy @@ -65,16 +65,16 @@ echo $circle->visible; // volá isVisible() Właściwości to przede wszystkim "cukier syntaktyczny"((syntactic sugar)), który ma uczynić życie programisty słodszym poprzez uproszczenie kodu. Jeśli ich nie chcesz, nie musisz z nich korzystać. -Spojrzenie na historię -====================== +Rzut oka na historię .[#toc-a-glimpse-into-history] +=================================================== -SmartObject kiedyś poprawiał i naprawiał zachowanie klasy na wiele sposobów, ale ewolucja PHP sprawiła, że większość oryginalnych funkcji stała się zbędna. Poniżej przedstawiamy więc spojrzenie na historię tego, jak sprawy się rozwijały. +SmartObject udoskonalał zachowanie obiektów na wiele sposobów, ale dzisiejszy PHP zawiera już większość tych ulepszeń natywnie. Poniższy tekst jest nostalgicznym spojrzeniem wstecz na historię, przypominającym nam, jak rzeczy ewoluowały. -Model obiektowy PHP od początku cierpiał na szereg poważnych wad i nieefektywności. Z tego powodu powstała klasa `Nette\Object` (w 2007 roku), która starała się im zaradzić i poprawić doświadczenia związane z używaniem PHP. Wystarczyło, aby inne klasy dziedziczyły po niej i czerpały korzyści, które przynosiła. Kiedy w PHP 5.4 pojawiła się obsługa cech, klasa `Nette\Object` została zastąpiona przez `Nette\SmartObject`. Tym samym nie było już konieczności dziedziczenia po wspólnym przodku. Dodatkowo trait można było wykorzystać w klasach, które już dziedziczyły po innej klasie. Ostateczny koniec `Nette\Object` nastąpił wraz z wydaniem PHP 7.2, który zabronił klasom nadawania nazw `Object`. +Od samego początku model obiektowy PHP cierpiał na niezliczoną ilość poważnych niedociągnięć i braków. Doprowadziło to do stworzenia klasy `Nette\Object` (w 2007 roku), która miała na celu naprawienie tych problemów i zwiększenie komfortu korzystania z PHP. Wystarczyło tylko, by inne klasy po niej dziedziczyły, a zyskałyby oferowane przez nią korzyści. Gdy w PHP 5.4 wprowadzono obsługę cech, klasa `Nette\Object` została zastąpiona cechą `Nette\SmartObject`. Wyeliminowało to potrzebę dziedziczenia po wspólnym przodku. Co więcej, cecha mogła być używana w klasach, które już dziedziczyły po innej klasie. Ostateczny koniec `Nette\Object` nastąpił wraz z wydaniem PHP 7.2, które zabroniło klasom nazywania się `Object`. -Wraz z rozwojem PHP udoskonalano model obiektowy i możliwości języka. Poszczególne funkcje klasy `SmartObject` stały się zbędne. Od wydania PHP 8.2 jedyną cechą, która pozostała, a która nie jest jeszcze bezpośrednio wspierana w PHP, jest możliwość korzystania z tzw. [właściwości |#Properties, gettery a settery]. +W miarę rozwoju PHP, jego model obiektowy i możliwości językowe ulegały poprawie. Różne funkcje klasy `SmartObject` stały się zbędne. Od wydania PHP 8.2 pozostała tylko jedna funkcja nieobsługiwana bezpośrednio w PHP: możliwość korzystania z tak zwanych [właściwości |#Properties, getters, and setters]. -Jakie funkcje oferowały kiedyś `Nette\Object` i `Nette\Object`? Oto przegląd. (W przykładach użyto klasy `Nette\Object`, ale większość właściwości dotyczy również cechy `Nette\SmartObject`). +Jakie funkcje oferowały `Nette\Object` i, rozszerzając, `Nette\SmartObject`? Oto przegląd. (W przykładach użyto klasy `Nette\Object`, ale większość funkcji dotyczy również cechy `Nette\SmartObject` ). Niespójne błędy .[#toc-nekonzistentni-chyby] @@ -114,7 +114,7 @@ $foo = Foo::form($var); // "Call to undefined static method Foo::form(), did you mean from()?" ``` -Dzisiejszy PZP może nie ma żadnej formy "czy miałeś na myśli?", ale [Tracy |tracy:] może dodać ten dodatek do błędów. I może nawet [sam naprawić |tracy:open-files-in-ide#Demos] takie błędy. +Podczas gdy dzisiejszy PHP nie ma funkcji "czy miałeś na myśli?", ta fraza może być dodawana do błędów przez [Tracy |tracy:]. Może nawet [automatycznie korygować takie błędy |tracy:open-files-in-ide#toc-demos]. Metody rozszerzania .[#toc-extension-methods] @@ -158,7 +158,7 @@ class Foo extends Nette\Object $obj = new Foo; $reflection = $obj->getReflection(); -$reflection->getAnnotation('author'); // vrátí 'John Doe +$reflection->getAnnotation('author'); // vrátí 'John Doe' ``` Od PHP 8.0 możliwy jest dostęp do metainformacji w postaci atrybutów: @@ -216,7 +216,7 @@ class Circle extends Nette\Object public function setRadius(float $radius): void { $this->onChange($this, $radius); - $this->radius = $radius + $this->radius = $radius; } } ``` diff --git a/utils/pt/smartobject.texy b/utils/pt/smartobject.texy index 31736e235f..e3f7e5f255 100644 --- a/utils/pt/smartobject.texy +++ b/utils/pt/smartobject.texy @@ -65,16 +65,16 @@ echo $circle->visible; // chamadas isVisible() As propriedades são principalmente o "açúcar sintático"((açúcar sintático)), que se destina a tornar a vida do programador mais doce, simplificando o código. Se você não os quer, não precisa usá-los. -Um olhar sobre a história .[#toc-a-look-into-the-history] -========================================================= +Um vislumbre da história .[#toc-a-glimpse-into-history] +======================================================= -SmartObject usado para melhorar e corrigir o comportamento de classe de muitas maneiras, mas a evolução do PHP tornou redundante a maioria das características originais. Portanto, o seguinte é um olhar sobre a história de como as coisas evoluíram. +O SmartObject costumava refinar o comportamento dos objetos de várias maneiras, mas o PHP atual já incorpora a maioria desses aprimoramentos de forma nativa. O texto a seguir é um olhar nostálgico para a história, lembrando-nos de como as coisas evoluíram. -Desde o início, o modelo de objeto PHP sofreu uma série de falhas graves e ineficiências. Esta foi a razão da criação da classe `Nette\Object` (em 2007), que tentou remediá-los e melhorar a experiência de uso do PHP. Era o suficiente para que outras classes herdassem dela, e ganhassem os benefícios que ela trazia. Quando o PHP 5.4 veio com suporte de características, a classe `Nette\Object` foi substituída por `Nette\SmartObject`. Assim, não era mais necessário herdar de um ancestral comum. Além disso, a característica podia ser usada em classes que já herdaram de outra classe. O fim final de `Nette\Object` veio com o lançamento do PHP 7.2, que proibiu as classes de serem nomeadas `Object`. +Desde seu início, o modelo de objeto do PHP sofria de uma infinidade de falhas e deficiências graves. Isso levou à criação da classe `Nette\Object` (em 2007), cujo objetivo era corrigir esses problemas e aumentar o conforto do uso do PHP. Tudo o que era necessário era que outras classes herdassem essa classe e obtivessem os benefícios que ela oferecia. Quando o PHP 5.4 introduziu o suporte a características, a classe `Nette\Object` foi substituída pela característica `Nette\SmartObject`. Isso eliminou a necessidade de herdar de um ancestral comum. Além disso, a característica poderia ser usada em classes que já herdavam de outra classe. O fim definitivo de `Nette\Object` veio com o lançamento do PHP 7.2, que proibiu que as classes fossem nomeadas `Object`. -Com o desenvolvimento do PHP em andamento, o modelo de objeto e as capacidades de linguagem foram melhorados. As funções individuais da classe `SmartObject` se tornaram redundantes. Desde o lançamento do PHP 8.2, a única característica que ainda não é suportada diretamente no PHP é a capacidade de usar as chamadas [propriedades |#Properties, Getters and Setters]. +À medida que o desenvolvimento do PHP continuava, seu modelo de objeto e os recursos da linguagem foram aprimorados. Várias funções da classe `SmartObject` tornaram-se redundantes. Desde o lançamento do PHP 8.2, resta apenas um recurso não suportado diretamente no PHP: a capacidade de usar as chamadas [propriedades |#Properties, getters, and setters]. -Que características `Nette\Object` e `Nette\Object` ofereceram uma vez? Aqui está uma visão geral. (Os exemplos utilizam a classe `Nette\Object`, mas a maioria das propriedades também se aplica ao traço `Nette\SmartObject` ). +Quais recursos o `Nette\Object` e, por extensão, o `Nette\SmartObject` ofereceram? Aqui está uma visão geral. (Nos exemplos, a classe `Nette\Object` é usada, mas a maioria dos recursos também se aplica à característica `Nette\SmartObject` ). Erros Inconsistentes .[#toc-inconsistent-errors] @@ -114,7 +114,7 @@ $foo = Foo::form($var); // "Call to undefined static method Foo::form(), did you mean from()?" ``` -O PHP de hoje pode não ter nenhuma forma de "você quis dizer?", mas [Tracy |tracy:] acrescenta este adendo aos erros. E ele pode até [corrigir |tracy:open-files-in-ide#toc-demos] tais erros por si só. +Embora o PHP atual não tenha um recurso "você quis dizer?", essa frase pode ser adicionada aos erros pela [Tracy |tracy:]. Ele pode até mesmo [corrigir automaticamente esses erros |tracy:open-files-in-ide#toc-demos]. Métodos de extensão .[#toc-extension-methods] @@ -158,7 +158,7 @@ class Foo extends Nette\Object $obj = new Foo; $reflection = $obj->getReflection(); -$reflection->getAnnotation('author'); // devolve 'John Doe +$reflection->getAnnotation('author'); // devolve 'John Doe' ``` A partir do PHP 8.0, é possível acessar meta-informação sob a forma de atributos: @@ -216,7 +216,7 @@ class Circle extends Nette\Object public function setRadius(float $radius): void { $this->onChange($this, $radius); - $this->radius = $radius + $this->radius = $radius; } } ``` diff --git a/utils/ro/smartobject.texy b/utils/ro/smartobject.texy index 5cbc348305..3d1ed9e89f 100644 --- a/utils/ro/smartobject.texy +++ b/utils/ro/smartobject.texy @@ -65,16 +65,16 @@ echo $circle->visible; // solicită isVisible() Proprietățile sunt în primul rând "zahăr sintactic"((zahăr sintactic)), care are rolul de a face viața programatorului mai ușoară prin simplificarea codului. Dacă nu le doriți, nu trebuie să le folosiți. -O privire în istorie .[#toc-a-look-into-the-history] -==================================================== +O privire în istorie .[#toc-a-glimpse-into-history] +=================================================== -SmartObject obișnuia să îmbunătățească și să corecteze comportamentul clasei în multe feluri, dar evoluția PHP a făcut ca majoritatea caracteristicilor originale să fie redundante. Așadar, în cele ce urmează este o privire în istoria evoluției lucrurilor. +SmartObject obișnuia să rafineze comportamentul obiectelor în numeroase moduri, dar PHP-ul de astăzi încorporează deja majoritatea acestor îmbunătățiri în mod nativ. Următorul text este o privire nostalgică asupra istoriei, amintindu-ne cum au evoluat lucrurile. -Încă de la început, modelul de obiecte PHP a suferit de o serie de defecte și ineficiențe grave. Acesta a fost motivul pentru crearea clasei `Nette\Object` (în 2007), care a încercat să le remedieze și să îmbunătățească experiența de utilizare a PHP. A fost suficient pentru ca alte clase să moștenească din ea și să obțină beneficiile pe care le-a adus. Când PHP 5.4 a venit cu suport pentru trăsături, clasa `Nette\Object` a fost înlocuită cu `Nette\SmartObject`. Astfel, nu a mai fost necesară moștenirea de la un strămoș comun. În plus, trait putea fi utilizat în clase care moșteneau deja de la o altă clasă. Sfârșitul final al `Nette\Object` a venit odată cu lansarea PHP 7.2, care a interzis ca clasele să fie denumite `Object`. +Încă de la începuturile sale, modelul de obiecte din PHP a suferit de o multitudine de deficiențe și neajunsuri grave. Acest lucru a dus la crearea clasei `Nette\Object` (în 2007), care a avut ca scop rectificarea acestor probleme și îmbunătățirea confortului de utilizare a PHP. Tot ceea ce era necesar era ca alte clase să moștenească din ea și să obțină beneficiile oferite de aceasta. Când PHP 5.4 a introdus suportul pentru trăsături, clasa `Nette\Object` a fost înlocuită cu trăsătura `Nette\SmartObject`. Acest lucru a eliminat necesitatea de a moșteni de la un strămoș comun. În plus, trăsătura putea fi utilizată în clase care moșteneau deja de la o altă clasă. Sfârșitul definitiv al `Nette\Object` a venit odată cu lansarea PHP 7.2, care a interzis ca clasele să fie denumite `Object`. -Pe măsură ce dezvoltarea PHP a continuat, modelul de obiecte și capacitățile limbajului au fost îmbunătățite. Funcțiile individuale ale clasei `SmartObject` au devenit redundante. De la lansarea PHP 8.2, singura caracteristică rămasă care nu este încă direct suportată în PHP este capacitatea de a utiliza așa-numitele [proprietăți |#Properties, Getters and Setters]. +Pe măsură ce dezvoltarea PHP a continuat, modelul său de obiecte și capacitățile limbajului s-au îmbunătățit. Diverse funcții ale clasei `SmartObject` au devenit redundante. De la lansarea PHP 8.2, a rămas o singură funcție care nu este direct suportată în PHP: capacitatea de a utiliza așa-numitele [proprietăți |#Properties, getters, and setters]. -Ce caracteristici ofereau cândva `Nette\Object` și `Nette\Object`? Iată o prezentare generală. (Exemplele folosesc clasa `Nette\Object`, dar majoritatea proprietăților se aplică și la trăsătura `Nette\SmartObject` ). +Ce caracteristici au oferit `Nette\Object` și, prin extensie, `Nette\SmartObject`? Iată o prezentare generală. (În exemple, este utilizată clasa `Nette\Object`, dar majoritatea caracteristicilor se aplică și trăsăturii `Nette\SmartObject` ). Erori inconsistente .[#toc-inconsistent-errors] @@ -114,7 +114,7 @@ $foo = Foo::form($var); // "Call to undefined static method Foo::form(), did you mean from()?" ``` -Este posibil ca PHP-ul de astăzi să nu aibă nicio formă de "ai vrut să spui?", dar [Tracy |tracy:] adaugă acest addendum la erori. Și poate chiar să [corecteze |tracy:open-files-in-ide#toc-demos] singur astfel de erori. +În timp ce PHP-ul actual nu are o funcție "ai vrut să spui?", această frază poate fi adăugată la erori de către [Tracy |tracy:]. Acesta poate chiar să [corecteze automat astfel de erori |tracy:open-files-in-ide#toc-demos]. Metode de extensie .[#toc-extension-methods] @@ -216,7 +216,7 @@ class Circle extends Nette\Object public function setRadius(float $radius): void { $this->onChange($this, $radius); - $this->radius = $radius + $this->radius = $radius; } } ``` diff --git a/utils/ru/smartobject.texy b/utils/ru/smartobject.texy index 444ea955e8..e0301323fd 100644 --- a/utils/ru/smartobject.texy +++ b/utils/ru/smartobject.texy @@ -65,16 +65,16 @@ echo $circle->visible; // calls isVisible() Свойства - это прежде всего "синтаксический сахар"((syntactic sugar)), который призван сделать жизнь программиста слаще за счет упрощения кода. Если они вам не нужны, вы не обязаны их использовать. -Взгляд в историю .[#toc-a-look-into-the-history] -================================================ +Взгляд в историю .[#toc-a-glimpse-into-history] +=============================================== -SmartObject использовался для улучшения и исправления поведения класса во многих отношениях, но развитие PHP сделало большинство первоначальных функций излишними. Поэтому ниже мы рассмотрим историю развития этих функций. +SmartObject использовался для улучшения поведения объектов различными способами, но современный PHP уже включает в себя большинство из этих улучшений. Следующий текст - это ностальгический взгляд в историю, напоминающий нам о том, как все развивалось. -С самого начала объектная модель PHP страдала от ряда серьезных недостатков и неэффективности. Это послужило причиной создания класса `Nette\Object` (в 2007 году), который попытался устранить их и улучшить опыт использования PHP. Этого оказалось достаточно, чтобы другие классы унаследовали от него и получили те преимущества, которые он принес. Когда в PHP 5.4 появилась поддержка трейтов, класс `Nette\Object` был заменен на `Nette\SmartObject`. Таким образом, больше не было необходимости наследоваться от общего предка. Кроме того, trait можно было использовать в классах, которые уже наследовались от другого класса. Окончательный конец `Nette\Object` наступил с выходом PHP 7.2, в котором было запрещено давать классам имена `Object`. +С самого начала своего существования объектная модель PHP страдала от множества серьезных недостатков и недоработок. Это привело к созданию класса `Nette\Object` (в 2007 году), который был призван исправить эти недостатки и повысить удобство работы с PHP. Достаточно было наследовать от него другие классы, чтобы они получили те преимущества, которые он дает. Когда в PHP 5.4 появилась поддержка трейтов, класс `Nette\Object` был заменен трейтом `Nette\SmartObject`. Это избавило от необходимости наследоваться от общего предка. Более того, трейты можно было использовать в классах, которые уже наследовались от другого класса. Окончательный конец `Nette\Object` наступил с выходом PHP 7.2, который запретил называть классы `Object`. -По мере развития PHP объектная модель и возможности языка совершенствовались. Отдельные функции класса `SmartObject` стали излишними. После выхода PHP 8.2 единственной функцией, которая пока не поддерживается в PHP напрямую, осталась возможность использовать так называемые [свойства |#Properties, getters and setters]. +По мере развития PHP его объектная модель и возможности языка совершенствовались. Различные функции класса `SmartObject` стали излишними. После выхода PHP 8.2 в PHP осталась только одна функция, не поддерживаемая напрямую: возможность использования так называемых [свойств |#Properties, getters, and setters]. -Какие функции предлагали `Nette\Object` и `Nette\Object`? Вот обзор. (В примерах используется класс `Nette\Object`, но большинство свойств применимо и к признаку `Nette\SmartObject` ). +Какие же возможности предоставляли `Nette\Object` и, соответственно, `Nette\SmartObject`? Вот обзор. (В примерах используется класс `Nette\Object`, но большинство возможностей применимо и к свойству `Nette\SmartObject` ). Непоследовательные ошибки .[#toc-inconsistent-errors] @@ -114,7 +114,7 @@ $foo = Foo::form($var); // "Call to undefined static method Foo::form(), did you mean from()?" ``` -Современный PHP, возможно, не имеет формы "Вы имели в виду?", но [Tracy |tracy:] добавляет это дополнение к ошибкам. И он даже может сам [исправлять |tracy:open-files-in-ide#toc-demos] такие ошибки. +Хотя современный PHP не имеет функции "Вы имели в виду?", эта фраза может быть добавлена к ошибкам [Tracy |tracy:]. Она даже может [автоматически исправлять такие ошибки |tracy:open-files-in-ide#toc-demos]. Методы расширения .[#toc-extension-methods] @@ -158,7 +158,7 @@ class Foo extends Nette\Object $obj = new Foo; $reflection = $obj->getReflection(); -$reflection->getAnnotation('author'); // returns 'John Doe +$reflection->getAnnotation('author'); // returns 'John Doe' ``` Начиная с PHP 8.0, появилась возможность доступа к мета-информации в виде атрибутов: @@ -216,7 +216,7 @@ class Circle extends Nette\Object public function setRadius(float $radius): void { $this->onChange($this, $radius); - $this->radius = $radius + $this->radius = $radius; } } ``` diff --git a/utils/sl/smartobject.texy b/utils/sl/smartobject.texy index 26548988f2..1045e03c54 100644 --- a/utils/sl/smartobject.texy +++ b/utils/sl/smartobject.texy @@ -65,16 +65,16 @@ echo $circle->visible; // pokliče isVisible() Lastnosti so predvsem "sintaktični sladkor"((sintactic sugar)), ki je namenjen temu, da programerju s poenostavitvijo kode osladi življenje. Če jih ne želite, vam jih ni treba uporabljati. -Pogled v zgodovino .[#toc-a-look-into-the-history] -================================================== +Pogled v zgodovino .[#toc-a-glimpse-into-history] +================================================= -SmartObject je v preteklosti na različne načine izboljševal in popravljal obnašanje razredov, vendar je zaradi razvoja PHP večina prvotnih funkcij postala odveč. Zato je v nadaljevanju podan pogled v zgodovino, kako so se stvari razvijale. +SmartObject je v preteklosti na številne načine izboljševal obnašanje predmetov, vendar današnji PHP večino teh izboljšav že vključuje. Naslednje besedilo je nostalgičen pogled v zgodovino, ki nas spominja na razvoj stvari. -Objektni model PHP je že od začetka trpel zaradi številnih resnih pomanjkljivosti in neučinkovitosti. Zato je bil leta 2007 oblikovan razred `Nette\Object`, ki jih je poskušal odpraviti in izboljšati izkušnjo uporabe PHP. Dovolj je bilo, da so ga podedovali tudi drugi razredi in pridobili prednosti, ki jih je prinesel. Ko je PHP 5.4 začel podpirati lastnosti, je razred `Nette\Object` nadomestil razred `Nette\SmartObject`. Tako ni bilo več treba dedovati po skupnem predniku. Poleg tega je bilo trait mogoče uporabiti v razredih, ki so že dedovali od drugega razreda. Dokončni konec razreda `Nette\Object` se je zgodil z izdajo PHP 7.2, ki je prepovedal, da bi se razredi imenovali `Object`. +Objektni model PHP je že od samega začetka trpel zaradi številnih resnih pomanjkljivosti in pomanjkljivosti. To je privedlo do oblikovanja razreda `Nette\Object` (leta 2007), katerega cilj je bil odpraviti te težave in povečati udobje pri uporabi PHP. Vse, kar je bilo potrebno, je bilo, da so drugi razredi podedovali razred in pridobili prednosti, ki jih je ponujal. Ko je PHP 5.4 uvedel podporo za lastnosti, je bil razred `Nette\Object` nadomeščen z lastnostjo `Nette\SmartObject`. S tem se je odpravila potreba po dedovanju od skupnega prednika. Poleg tega je bilo mogoče lastnost uporabiti v razredih, ki so že dedovali od drugega razreda. Dokončen konec `Nette\Object` se je zgodil z izdajo PHP 7.2, ki je prepovedal, da bi se razredi imenovali `Object`. -Z nadaljnjim razvojem jezika PHP sta se izboljšala objektni model in zmožnosti jezika. Posamezne funkcije razreda `SmartObject` so postale nepotrebne. Od izdaje PHP 8.2 je ostala edina funkcija, ki še ni neposredno podprta v PHP, možnost uporabe tako imenovanih [lastnosti |#Properties, Getters and Setters]. +Z nadaljnjim razvojem PHP sta se izboljšala njegov objektni model in jezikovne zmožnosti. Različne funkcije razreda `SmartObject` so postale nepotrebne. Od izdaje PHP 8.2 je ostala le ena funkcija, ki ni neposredno podprta v PHP: možnost uporabe tako imenovanih [lastnosti |#Properties, getters, and setters]. -Katere funkcije sta nekoč ponujala razreda `Nette\Object` in `Nette\Object`? Tukaj je pregled. (Primeri uporabljajo razred `Nette\Object`, vendar večina lastnosti velja tudi za lastnost `Nette\SmartObject`.) +Katere funkcije sta ponujala `Nette\Object` in posledično `Nette\SmartObject`? Tukaj je pregled. (V primerih je uporabljen razred `Nette\Object`, vendar večina lastnosti velja tudi za lastnost `Nette\SmartObject` ). Nedosledne napake .[#toc-inconsistent-errors] @@ -114,7 +114,7 @@ $foo = Foo::form($var); // "Call to undefined static method Foo::form(), did you mean from()?" ``` -Današnji PHP morda nima oblike "ali ste mislili?", vendar [Tracy |tracy:] napakam dodaja ta dodatek. In take napake lahko celo sam [popravi |tracy:open-files-in-ide#toc-demos]. +Čeprav današnji PHP nima funkcije "Ali ste mislili?", lahko [Tracy |tracy:] napakam doda ta stavek. [Takšne napake |tracy:open-files-in-ide#toc-demos] lahko celo [samodejno popravi |tracy:open-files-in-ide#toc-demos]. Metode razširitve .[#toc-extension-methods] @@ -158,7 +158,7 @@ class Foo extends Nette\Object $obj = new Foo; $reflection = $obj->getReflection(); -$reflection->getAnnotation('author'); // vrne 'John Doe +$reflection->getAnnotation('author'); // vrne 'John Doe' ``` Od različice PHP 8.0 je mogoče dostopati do metainformacij v obliki atributov: @@ -216,7 +216,7 @@ class Circle extends Nette\Object public function setRadius(float $radius): void { $this->onChange($this, $radius); - $this->radius = $radius + $this->radius = $radius; } } ``` diff --git a/utils/tr/smartobject.texy b/utils/tr/smartobject.texy index 1617abc805..b08dcbca57 100644 --- a/utils/tr/smartobject.texy +++ b/utils/tr/smartobject.texy @@ -65,16 +65,16 @@ echo $circle->visible; // isVisible() işlevini çağırır Özellikler öncelikle "sözdizimsel şeker"((syntactic sugar)) olup, kodu basitleştirerek programcının hayatını daha tatlı hale getirmeyi amaçlar. Eğer onları istemiyorsanız, kullanmak zorunda değilsiniz. -Tarihe Bir Bakış .[#toc-a-look-into-the-history] -================================================ +Tarihe Bir Bakış .[#toc-a-glimpse-into-history] +=============================================== -SmartObject eskiden sınıf davranışını birçok yönden geliştirir ve düzeltirdi, ancak PHP'nin evrimi orijinal özelliklerin çoğunu gereksiz hale getirdi. Bu nedenle aşağıda, işlerin nasıl geliştiğinin geçmişine bir bakış yer almaktadır. +SmartObject, nesnelerin davranışlarını çeşitli şekillerde iyileştirmek için kullanılırdı, ancak bugünün PHP'si bu geliştirmelerin çoğunu zaten yerel olarak içeriyor. Aşağıdaki metin geçmişe nostaljik bir bakıştır ve bize işlerin nasıl geliştiğini hatırlatır. -PHP nesne modeli en başından beri bir dizi ciddi kusur ve verimsizlikten muzdaripti. Bu eksiklikleri gidermeye ve PHP kullanım deneyimini iyileştirmeye çalışan `Nette\Object` sınıfının (2007'de) yaratılmasının nedeni buydu. Diğer sınıfların bu sınıftan miras alması ve sağladığı avantajlardan yararlanması için yeterliydi. PHP 5.4 trait desteği ile geldiğinde, `Nette\Object` sınıfı `Nette\SmartObject` ile değiştirildi. Böylece artık ortak bir atadan miras almaya gerek kalmamıştı. Ayrıca, trait zaten başka bir sınıftan miras alan sınıflarda da kullanılabiliyordu. `Nette\Object` 'un nihai sonu, sınıfların `Object` olarak adlandırılmasını yasaklayan PHP 7.2 sürümüyle geldi. +PHP'nin nesne modeli, başlangıcından itibaren sayısız ciddi eksiklik ve yetersizlikten muzdaripti. Bu durum, bu sorunları gidermeyi ve PHP'nin kullanım rahatlığını artırmayı amaçlayan `Nette\Object` sınıfının (2007'de) oluşturulmasına yol açtı. İhtiyaç duyulan tek şey diğer sınıfların bu sınıftan miras almasıydı ve onlar da bu sınıfın sunduğu avantajlardan yararlanabileceklerdi. PHP 5.4 özellikler için destek sunduğunda, `Nette\Object` sınıfının yerini `Nette\SmartObject` özelliği aldı. Bu, ortak bir atadan miras alma ihtiyacını ortadan kaldırdı. Dahası, özellik zaten başka bir sınıftan miras alan sınıflarda kullanılabiliyordu. `Nette\Object` 'un kesin sonu, sınıfların `Object` olarak adlandırılmasını yasaklayan PHP 7.2'nin yayınlanmasıyla geldi. -PHP'nin gelişimi devam ettikçe, nesne modeli ve dil yetenekleri geliştirildi. `SmartObject` sınıfının bireysel işlevleri gereksiz hale geldi. PHP 8.2'nin yayınlanmasından bu yana, PHP'de henüz doğrudan desteklenmeyen tek özellik, sözde [özellikleri |#Properties, Getters and Setters] kullanma yeteneğidir. +PHP'nin gelişimi devam ettikçe, nesne modeli ve dil yetenekleri de gelişti. `SmartObject` sınıfının çeşitli işlevleri gereksiz hale geldi. PHP 8.2'nin yayınlanmasından bu yana, PHP'de doğrudan desteklenmeyen tek bir özellik kaldı: sözde [özellikleri |#Properties, getters, and setters] kullanma yeteneği. -`Nette\Object` ve `Nette\Object` bir zamanlar hangi özellikleri sunuyordu? İşte genel bir bakış. (Örnekler `Nette\Object` sınıfını kullanmaktadır, ancak özelliklerin çoğu `Nette\SmartObject` özelliği için de geçerlidir). + `Nette\Object` ve buna bağlı olarak `Nette\SmartObject` hangi özellikleri sunuyordu? İşte genel bir bakış. (Örneklerde `Nette\Object` sınıfı kullanılmıştır, ancak çoğu özellik `Nette\SmartObject` özelliği için de geçerlidir). Tutarsız Hatalar .[#toc-inconsistent-errors] @@ -114,7 +114,7 @@ $foo = Foo::form($var); // "Call to undefined static method Foo::form(), did you mean from()?" ``` -Günümüz PHP'sinde "demek istediniz mi?" gibi bir ifade bulunmayabilir, ancak [Tracy |tracy:] hatalara bu eki ekler. Ve bu tür hataları kendisi bile [düzeltebilir |tracy:open-files-in-ide#toc-demos]. +Günümüz PHP'sinde "demek istediniz mi?" özelliği olmasa da, bu ifade [Tracy |tracy:] tarafından hatalara eklenebilir. Hatta bu [tür hataları otomatik olarak düzeltebilir |tracy:open-files-in-ide#toc-demos]. Uzatma yöntemleri .[#toc-extension-methods] @@ -216,7 +216,7 @@ class Circle extends Nette\Object public function setRadius(float $radius): void { $this->onChange($this, $radius); - $this->radius = $radius + $this->radius = $radius; } } ``` diff --git a/utils/uk/smartobject.texy b/utils/uk/smartobject.texy index e57ca2cee5..446738b83e 100644 --- a/utils/uk/smartobject.texy +++ b/utils/uk/smartobject.texy @@ -65,16 +65,16 @@ echo $circle->visible; // викликаємо isVisible() Властивості - це насамперед "синтаксичний цукор"((syntactic sugar)), який покликаний зробити життя програміста солодшим за рахунок спрощення коду. Якщо вони вам не потрібні, ви не зобов'язані їх використовувати. -Погляд в історію .[#toc-a-look-into-the-history] -================================================ +Погляд в історію .[#toc-a-glimpse-into-history] +=============================================== -SmartObject використовували для поліпшення і виправлення поведінки класу в багатьох відношеннях, але розвиток PHP зробив більшість початкових функцій зайвими. Тому нижче ми розглянемо історію розвитку цих функцій. +SmartObject використовувався для покращення поведінки об'єктів багатьма способами, але сьогоднішній PHP вже включає в себе більшість з цих покращень нативно. Наступний текст - це ностальгічний погляд в історію, що нагадує нам про те, як все розвивалося. -Від самого початку об'єктна модель PHP страждала від низки серйозних недоліків і неефективності. Це стало причиною створення класу `Nette\Object` (у 2007 році), який спробував усунути їх і поліпшити досвід використання PHP. Цього виявилося достатньо, щоб інші класи успадкували від нього і отримали ті переваги, які він приніс. Коли в PHP 5.4 з'явилася підтримка трейтів, клас `Nette\Object` було замінено на `Nette\SmartObject`. Таким чином, більше не було необхідності успадковуватися від спільного предка. Крім того, trait можна було використовувати в класах, які вже успадковувалися від іншого класу. Остаточний кінець `Nette\Object` настав з виходом PHP 7.2, в якому було заборонено давати класам імена `Object`. +Від самого початку об'єктна модель PHP страждала від безлічі серйозних недоліків і недоробок. Це призвело до створення класу `Nette\Object` (у 2007 році), який мав на меті виправити ці проблеми та підвищити комфорт використання PHP. Все, що було потрібно - це щоб інші класи успадковували його, і вони отримували переваги, які він пропонував. Коли в PHP 5.4 було введено підтримку трейтів, клас `Nette\Object` було замінено на трейт `Nette\SmartObject`. Це усунуло необхідність успадковувати від спільного предка. Крім того, ознаку можна було використовувати в класах, які вже були успадковані від іншого класу. Остаточний кінець `Nette\Object` настав з виходом PHP 7.2, який заборонив класам називатися `Object`. -У міру розвитку PHP об'єктна модель і можливості мови вдосконалювалися. Окремі функції класу `SmartObject` стали зайвими. Після виходу PHP 8.2 єдиною функцією, яка поки що не підтримується в PHP безпосередньо, залишилася можливість використовувати так звані [властивості |#Properties, getters and setters]. +З розвитком PHP його об'єктна модель і можливості мови покращувалися. Різні функції класу `SmartObject` стали надлишковими. З виходом PHP 8.2 залишилася лише одна функція, яка не підтримується безпосередньо в PHP: можливість використання так званих [властивостей |#Properties, getters, and setters]. -Які функції пропонували `Nette\Object` і `Nette\Object`? Ось огляд. (У прикладах використовується клас `Nette\Object`, але більшість властивостей може бути застосована і до ознаки `Nette\SmartObject` ). +Які ж можливості пропонували `Nette\Object` і, відповідно, `Nette\SmartObject`? Ось короткий огляд. (У прикладах використовується клас `Nette\Object`, але більшість можливостей також застосовні до властивості `Nette\SmartObject` ). Непослідовні помилки .[#toc-inconsistent-errors] @@ -114,7 +114,7 @@ $foo = Foo::form($var); // "Call to undefined static method Foo::form(), did you mean from()?" ``` -Сучасний PHP, можливо, не має форми "Ви мали на увазі?", але [Tracy |tracy:] додає це доповнення до помилок. І він навіть може сам [виправляти |tracy:open-files-in-ide#toc-demos] такі помилки. +Хоча сучасний PHP не має функції "ви мали на увазі?", цю фразу можна додати до помилок за допомогою [Трейсі |tracy:]. Він навіть може [автоматично виправляти такі помилки |tracy:open-files-in-ide#toc-demos]. Методи розширення .[#toc-extension-methods] @@ -158,7 +158,7 @@ class Foo extends Nette\Object $obj = new Foo; $reflection = $obj->getReflection(); -$reflection->getAnnotation('author'); // повертає 'John Doe +$reflection->getAnnotation('author'); // повертає 'John Doe' ``` Починаючи з PHP 8.0, з'явилася можливість доступу до мета-інформації у вигляді атрибутів: @@ -216,7 +216,7 @@ class Circle extends Nette\Object public function setRadius(float $radius): void { $this->onChange($this, $radius); - $this->radius = $radius + $this->radius = $radius; } } ``` From 8a961eb7f2e4c23f0e0c96234a7814e5fce62e8e Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 17 Jan 2024 16:03:12 +0100 Subject: [PATCH 006/137] nette/utils 4.0.1 --- utils/bg/images.texy | 73 ++++++++++++++++++++++++++------------------ utils/cs/images.texy | 73 ++++++++++++++++++++++++++------------------ utils/de/images.texy | 73 ++++++++++++++++++++++++++------------------ utils/el/images.texy | 73 ++++++++++++++++++++++++++------------------ utils/en/images.texy | 73 ++++++++++++++++++++++++++------------------ utils/es/images.texy | 73 ++++++++++++++++++++++++++------------------ utils/fr/images.texy | 73 ++++++++++++++++++++++++++------------------ utils/hu/images.texy | 73 ++++++++++++++++++++++++++------------------ utils/it/images.texy | 73 ++++++++++++++++++++++++++------------------ utils/pl/images.texy | 73 ++++++++++++++++++++++++++------------------ utils/pt/images.texy | 73 ++++++++++++++++++++++++++------------------ utils/ro/images.texy | 73 ++++++++++++++++++++++++++------------------ utils/ru/images.texy | 73 ++++++++++++++++++++++++++------------------ utils/sl/images.texy | 73 ++++++++++++++++++++++++++------------------ utils/tr/images.texy | 73 ++++++++++++++++++++++++++------------------ utils/uk/images.texy | 73 ++++++++++++++++++++++++++------------------ 16 files changed, 704 insertions(+), 464 deletions(-) diff --git a/utils/bg/images.texy b/utils/bg/images.texy index ea5a079c9e..4f2f25bee9 100644 --- a/utils/bg/images.texy +++ b/utils/bg/images.texy @@ -17,6 +17,7 @@ composer require nette/utils ```php use Nette\Utils\Image; +use Nette\Utils\ImageType; ``` @@ -41,17 +42,6 @@ $image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0)); $image = Image::fromFile('nette.jpg'); ``` -Поддържаните формати са JPEG, PNG, GIF, WebP, AVIF и BMP, но вашата версия на PHP също трябва да ги поддържа (проверете `phpinfo()`, раздел GD). Анимациите не се поддържат. - -Трябва ли да определям формата на изображението при качване? Методът го връща във втория параметър: - -```php -$image = Image::fromFile('nette.jpg', $type); -// $type е Image::JPEG, Image::PNG, Image::GIF, Image::WEBP, Image::AVIF или Image::BMP -``` - -Само откриването без зареждане на изображението се извършва от `Image::detectTypeFromFile()`. - Запазване на изображения .[#toc-save-the-image] =============================================== @@ -68,25 +58,45 @@ $image->save('resampled.jpg'); $image->save('resampled.jpg', 80); // JPEG, 80% качество ``` -Ако форматът не е очевиден от разширението на файла, той може да бъде посочен с една от константите `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` и `Image::BMP`: +Ако форматът не е очевиден от файловото разширение, той може да бъде посочен с [константа |#Formats]: ```php -$image->save('resampled.tmp', null, Image::JPEG); +$image->save('resampled.tmp', null, ImageType::JPEG); ``` Изображението може да бъде записано на променлива вместо на диск: ```php -$data = $image->toString(Image::JPEG, 80); // JPEG, 80% качество +$data = $image->toString(ImageType::JPEG, 80); // JPEG, 80% качество ``` или се изпраща директно на браузъра със съответния HTTP хедър `Content-Type`: ```php // изпраща заглавие Content-Type: image/png -$image->send(Image::PNG); +$image->send(ImageType::PNG); +``` + + +Формати .[#toc-formats] +======================= + +Поддържаните формати са JPEG, PNG, GIF, WebP, AVIF и BMP. Те обаче трябва да се поддържат и от вашата версия на PHP, което може да се провери чрез функцията [isTypeSupported(). |#isTypeSupported()] Анимациите не се поддържат. + +Форматите са представени от константите `ImageType::JPEG`, `ImageType::PNG`, `ImageType::GIF`, `ImageType::WEBP`, `ImageType::AVIF` и `ImageType::BMP`. + +```php +$supported = Image::isTypeSupported(ImageType::JPEG); ``` +Трябва да определите формата на дадено изображение при зареждане? Методът го връща във втория параметър: + +```php +$image = Image::fromFile('nette.jpg', $type); +``` + +Действителното откриване, без да се зарежда изображението, се извършва от `Image::detectTypeFromFile()`. + Промяна на размера .[#toc-image-resize] ======================================= @@ -226,12 +236,12 @@ static fromBlank(int $width, int $height, array $color=null): Image .[method] static fromFile(string $file, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------- -Чете изображение от файл и връща неговия тип в `$detectedFormat`. Поддържаните типове са `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` и `Image::BMP`. +Чете изображение от файл и връща неговия [тип |#Formats] в `$detectedFormat`. static fromString(string $s, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------ -Чете изображение от низ и връща неговия тип в `$detectedFormat`. Поддържаните типове са `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` и `Image::BMP`. +Чете изображение от низ и връща неговия [тип |#Formats] в `$detectedFormat`. static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method] @@ -241,27 +251,32 @@ static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method static typeToExtension(int $type): string .[method] --------------------------------------------------- -Връща разширението на файла за дадената константа `Image::XXX`. +Връща разширението на файла за дадения [тип |#Formats]. static typeToMimeType(int $type): string .[method] -------------------------------------------------- -Връща типа mime за дадената константа `Image::XXX`. +Връща типа mime за дадения [тип |#Formats]. static extensionToType(string $extension): int .[method] -------------------------------------------------------- -Връща типа mime като константа `Image::XXX` според разширението на файла. +Връща [типа на |#Formats] изображението в съответствие с разширението на файла. static detectTypeFromFile(string $file, int &$width=null, int &$height=null): ?int .[method] -------------------------------------------------------------------------------------------- -Връща типа на изображението като константа `Image::XXX`, а размерите му - като `$width` и `$height`. +Връща [типа на |#Formats] файла с изображение, а в параметрите `$width` и `$height` - и неговите размери. static detectTypeFromString(string $s, int &$width=null, int &$height=null): ?int .[method] ------------------------------------------------------------------------------------------- -Връща типа на изображението от символния низ като константа `Image::XXX` и размерите му в параметрите `$width` и `$height`. +Връща [типа на |#Formats] изображението от низ, а в параметрите `$width` и `$height` - и неговите размери. + + +static isTypeSupported(int $type): bool .[method] +------------------------------------------------- +Определя дали даденият [тип |#Formats] изображение се поддържа. affine(array $affine, array $clip=null): Image .[method] @@ -586,7 +601,7 @@ save(string $file, int $quality=null, int $type=null): void .[method] --------------------------------------------------------------------- Записва изображението във файл. -Качеството на компресията е в диапазона 0..100 за JPEG (по подразбиране 85), WEBP (по подразбиране 80) и AVIF (по подразбиране 30) и 0..9 за PNG (по подразбиране 9). Ако типът не е очевиден от разширението на файла, можете да го посочите, като използвате една от константите `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` и `Image::BMP`. +Качеството на компресията е в диапазона 0..100 за JPEG (по подразбиране 85), WEBP (по подразбиране 80) и AVIF (по подразбиране 30) и 0..9 за PNG (по подразбиране 9). Ако типът не е очевиден от разширението на файла, можете да го посочите, като използвате една от константите на `ImageType`. saveAlpha(bool $saveflag): void .[method] @@ -601,11 +616,11 @@ scale(int $newWidth, int $newHeight=-1, int $mode=IMG_BILINEAR_FIXED): Image .[m Мащабирайте изображението, като използвате зададения алгоритъм за интерполация. ([повече подробности |https://www.php.net/manual/en/function.imagescale]) -send(int $type=Image::JPEG, int $quality=null): void .[method] --------------------------------------------------------------- +send(int $type=ImageType::JPEG, int $quality=null): void .[method] +------------------------------------------------------------------ Извежда изображението в браузъра. -Качеството на компресията е в диапазона 0..100 за JPEG (по подразбиране 85), WEBP (по подразбиране 80) и AVIF (по подразбиране 30) и 0..9 за PNG (по подразбиране 9). Типът е една от константите `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` и `Image::BMP`. +Качеството на компресията е в диапазона 0..100 за JPEG (по подразбиране 85), WEBP (по подразбиране 80) и AVIF (по подразбиране 30) и 0..9 за PNG (по подразбиране 9). setBrush(Image $brush): void .[method] @@ -663,11 +678,11 @@ stringUp(int $font, int $x, int $y, string $s, int $col): void .[method] Извежда низ по вертикала в зададените координати. ([повече подробности |https://www.php.net/manual/en/function.imagestringup]) -toString(int $type=Image::JPEG, int $quality=null): string .[method] --------------------------------------------------------------------- +toString(int $type=ImageType::JPEG, int $quality=null): string .[method] +------------------------------------------------------------------------ Записва изображението в низ. -Качеството на компресията е в диапазона 0..100 за JPEG (по подразбиране 85), WEBP (по подразбиране 80) и AVIF (по подразбиране 30) и 0..9 за PNG (по подразбиране 9). Типът е една от константите `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` и `Image::BMP`. +Качеството на компресията е в диапазона 0..100 за JPEG (по подразбиране 85), WEBP (по подразбиране 80) и AVIF (по подразбиране 30) и 0..9 за PNG (по подразбиране 9). trueColorToPalette(bool $dither, int $ncolors): void .[method] diff --git a/utils/cs/images.texy b/utils/cs/images.texy index 0e16ebff54..6c55e1df60 100644 --- a/utils/cs/images.texy +++ b/utils/cs/images.texy @@ -17,6 +17,7 @@ Všechny příklady předpokládají vytvořený alias: ```php use Nette\Utils\Image; +use Nette\Utils\ImageType; ``` @@ -41,17 +42,6 @@ Nebo obrázek načteme ze souboru: $image = Image::fromFile('nette.jpg'); ``` -Podporované formáty jsou JPEG, PNG, GIF, WebP, AVIF a BMP, nicméně musí je podporovat i vaše verze PHP (ověříte ve výpisu `phpinfo()` v sekci GD). Animace podporované nejsou. - -Potřebujete při načtení detekovat formát obrázku? Metoda ho vrátí v druhém parametru: - -```php -$image = Image::fromFile('nette.jpg', $type); -// $type bude Image::JPEG, Image::PNG, Image::GIF, Image::WEBP, Image::AVIF nebo Image::BMP -``` - -Samotnou detekci bez načtení obrázku provádí `Image::detectTypeFromFile()`. - Uložení obrázku =============== @@ -68,25 +58,45 @@ Můžeme určit kvalitu komprese v rozsahu 0..100 pro JPEG (výchozí 85), WEBP $image->save('resampled.jpg', 80); // JPEG, kvalita 80% ``` -Pokud z přípony souboru není zřejmý formát, lze ho určit jednou z konstant `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` a `Image::BMP`: +Pokud z přípony souboru není zřejmý formát, lze ho určit [konstantou|#Formáty]: ```php -$image->save('resampled.tmp', null, Image::JPEG); +$image->save('resampled.tmp', null, ImageType::JPEG); ``` Obrázek lze místo na disk zapsat do proměnné: ```php -$data = $image->toString(Image::JPEG, 80); // JPEG, kvalita 80% +$data = $image->toString(ImageType::JPEG, 80); // JPEG, kvalita 80% ``` nebo poslat přímo do prohlížeče s příslušnou HTTP hlavičkou `Content-Type`: ```php // odešle hlavičku Content-Type: image/png -$image->send(Image::PNG); +$image->send(ImageType::PNG); +``` + + +Formáty +======= + +Podporované formáty jsou JPEG, PNG, GIF, WebP, AVIF a BMP, nicméně musí je podporovat i vaše verze PHP, což ověříte funkcí [#isTypeSupported()]. Animace podporované nejsou. + +Formát představují konstanty `ImageType::JPEG`, `ImageType::PNG`, `ImageType::GIF`, `ImageType::WEBP`, `ImageType::AVIF` a `ImageType::BMP`. + +```php +$supported = Image::isTypeSupported(ImageType::JPEG); +``` + +Potřebujete při načtení detekovat formát obrázku? Metoda ho vrátí v druhém parametru: + +```php +$image = Image::fromFile('nette.jpg', $type); ``` +Samotnou detekci bez načtení obrázku provádí `Image::detectTypeFromFile()`. + Změna velikosti =============== @@ -226,12 +236,12 @@ Vytvoří nový true color obrázek daných rozměrů. Výchozí barva je čern static fromFile(string $file, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------- -Načte obrázek ze souboru a vrací jeho typ v `$detectedFormat`. Podporované typy jsou `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` a `Image::BMP`. +Načte obrázek ze souboru a vrací jeho [typ|#Formáty] v `$detectedFormat`. static fromString(string $s, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------ -Načte obrázek z řetezce a vrací jeho typ v `$detectedFormat`. Podporované typy jsou `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` a `Image::BMP`. +Načte obrázek z řetezce a vrací jeho [typ|#Formáty] v `$detectedFormat`. static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method] @@ -241,27 +251,32 @@ Vytvoří barvu, kterou lze použít v dalších metodách, jako třeba `ellipse static typeToExtension(int $type): string .[method] --------------------------------------------------- -Vrátí příponu souboru pro danou konstantu `Image::XXX`. +Vrátí příponu souboru pro daný [typ|#Formáty]. static typeToMimeType(int $type): string .[method] -------------------------------------------------- -Vrátí mime type pro danou konstantu `Image::XXX`. +Vrátí mime type pro daný [typ|#Formáty]. static extensionToType(string $extension): int .[method] -------------------------------------------------------- -Vrátí typ obrázku jako konstantu `Image::XXX` podle přípony souboru. +Vrátí [typ|#Formáty] obrázku podle přípony souboru. static detectTypeFromFile(string $file, int &$width=null, int &$height=null): ?int .[method] -------------------------------------------------------------------------------------------- -Vrátí typ obrázku jako konstantu `Image::XXX` a v parametrech `$width` a `$height` také jeho rozměry. +Vrátí [typ|#Formáty] obrázku a v parametrech `$width` a `$height` také jeho rozměry. static detectTypeFromString(string $s, int &$width=null, int &$height=null): ?int .[method] ------------------------------------------------------------------------------------------- -Vrátí typ obrázku z řetězce jako konstantu `Image::XXX` a v parametrech `$width` a `$height` také jeho rozměry. +Vrátí [typ|#Formáty] obrázku z řetězce a v parametrech `$width` a `$height` také jeho rozměry. + + +static isTypeSupported(int $type): bool .[method] +------------------------------------------------- +Zjišťuje, zda je podporovaný daný [typ|#Formáty] obrázku. affine(array $affine, array $clip=null): Image .[method] @@ -586,7 +601,7 @@ save(string $file, int $quality=null, int $type=null): void .[method] --------------------------------------------------------------------- Uloží obrázek do souboru. -Kvalita komprese je v rozsahu 0..100 pro JPEG (výchozí 85), WEBP (výchozí 80) a AVIF (výchozí 30) a 0..9 pro PNG (výchozí 9). Pokud typ není zřejmý z přípony souboru, můžete jej zadat pomocí jedné z konstant `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` a `Image::BMP`. +Kvalita komprese je v rozsahu 0..100 pro JPEG (výchozí 85), WEBP (výchozí 80) a AVIF (výchozí 30) a 0..9 pro PNG (výchozí 9). Pokud typ není zřejmý z přípony souboru, můžete jej zadat pomocí jedné z konstant `ImageType`. saveAlpha(bool $saveflag): void .[method] @@ -601,11 +616,11 @@ scale(int $newWidth, int $newHeight=-1, int $mode=IMG_BILINEAR_FIXED): Image .[m Měřítko obrázku pomocí daného interpolačního algoritmu. ([více |https://www.php.net/manual/en/function.imagescale]) -send(int $type=Image::JPEG, int $quality=null): void .[method] --------------------------------------------------------------- +send(int $type=ImageType::JPEG, int $quality=null): void .[method] +------------------------------------------------------------------ Vypíše obrázek do prohlížeče. -Kvalita komprese je v rozsahu 0..100 pro JPEG (výchozí 85), WEBP (výchozí 80) a AVIF (výchozí 30) a 0..9 pro PNG (výchozí 9). Typ je jednou z konstant `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` a `Image::BMP`. +Kvalita komprese je v rozsahu 0..100 pro JPEG (výchozí 85), WEBP (výchozí 80) a AVIF (výchozí 30) a 0..9 pro PNG (výchozí 9). setBrush(Image $brush): void .[method] @@ -663,11 +678,11 @@ stringUp(int $font, int $x, int $y, string $s, int $col): void .[method] Vypíše řetězec svisle na dané souřadnice. ([více |https://www.php.net/manual/en/function.imagestringup]) -toString(int $type=Image::JPEG, int $quality=null): string .[method] --------------------------------------------------------------------- +toString(int $type=ImageType::JPEG, int $quality=null): string .[method] +------------------------------------------------------------------------ Uloží obrázek do řetezce. -Kvalita komprese je v rozsahu 0..100 pro JPEG (výchozí 85), WEBP (výchozí 80) a AVIF (výchozí 30) a 0..9 pro PNG (výchozí 9). Typ je jednou z konstant `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` a `Image::BMP`. +Kvalita komprese je v rozsahu 0..100 pro JPEG (výchozí 85), WEBP (výchozí 80) a AVIF (výchozí 30) a 0..9 pro PNG (výchozí 9). trueColorToPalette(bool $dither, int $ncolors): void .[method] diff --git a/utils/de/images.texy b/utils/de/images.texy index 30354d6095..d2aabbb60c 100644 --- a/utils/de/images.texy +++ b/utils/de/images.texy @@ -17,6 +17,7 @@ Die folgenden Beispiele gehen davon aus, dass der folgende Klassenalias definier ```php use Nette\Utils\Image; +use Nette\Utils\ImageType; ``` @@ -41,17 +42,6 @@ Oder wir laden das Bild aus einer Datei: $image = Image::fromFile('nette.jpg'); ``` -Unterstützte Formate sind JPEG, PNG, GIF, WebP, AVIF und BMP, aber Ihre PHP-Version muss diese Formate ebenfalls unterstützen (siehe `phpinfo()`, Abschnitt GD). Animationen werden nicht unterstützt. - -Müssen Sie das Bildformat beim Laden erkennen? Die Methode gibt das Format im zweiten Parameter zurück: - -```php -$image = Image::fromFile('nette.jpg', $type); -// $type ist Image::JPEG, Image::PNG, Image::GIF, Image::WEBP, Image::AVIF oder Image::BMP -``` - -Nur die Erkennung ohne Laden des Bildes wird von `Image::detectTypeFromFile()` durchgeführt. - Speichern Sie das Bild .[#toc-save-the-image] ============================================= @@ -68,25 +58,45 @@ Wir können die Komprimierungsqualität im Bereich 0..100 für JPEG (Standard 85 $image->save('resampled.jpg', 80); // JPEG, Qualität 80% ``` -Wenn das Format nicht aus der Dateierweiterung ersichtlich ist, kann es durch eine der Konstanten `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` und `Image::BMP` angegeben werden: +Wenn das Format nicht aus der Dateierweiterung ersichtlich ist, kann es durch eine [Konstante |#Formats] angegeben werden: ```php -$image->save('resampled.tmp', null, Image::JPEG); +$image->save('resampled.tmp', null, ImageType::JPEG); ``` Das Bild kann in eine Variable statt auf die Festplatte geschrieben werden: ```php -$data = $image->toString(Image::JPEG, 80); // JPEG, Qualität 80%. +$data = $image->toString(ImageType::JPEG, 80); // JPEG, Qualität 80%. ``` oder direkt an den Browser mit dem entsprechenden HTTP-Header `Content-Type` senden: ```php // sendet Kopfzeile Content-Type: image/png -$image->send(Image::PNG); +$image->send(ImageType::PNG); +``` + + +Formate .[#toc-formats] +======================= + +Unterstützte Formate sind JPEG, PNG, GIF, WebP, AVIF, und BMP. Sie müssen jedoch auch von Ihrer PHP-Version unterstützt werden, was mit der Funktion [isTypeSupported() |#isTypeSupported()] überprüft werden kann. Animationen werden nicht unterstützt. + +Die Formate werden durch die Konstanten `ImageType::JPEG`, `ImageType::PNG`, `ImageType::GIF`, `ImageType::WEBP`, `ImageType::AVIF`, und `ImageType::BMP` dargestellt. + +```php +$supported = Image::isTypeSupported(ImageType::JPEG); ``` +Müssen Sie das Format eines Bildes beim Laden erkennen? Die Methode gibt es im zweiten Parameter zurück: + +```php +$image = Image::fromFile('nette.jpg', $type); +``` + +Die eigentliche Erkennung ohne Laden des Bildes wird von `Image::detectTypeFromFile()` durchgeführt. + Bildgröße ändern .[#toc-image-resize] ===================================== @@ -226,12 +236,12 @@ Erzeugt ein neues Echtfarbbild mit den angegebenen Abmessungen. Die Standardfarb static fromFile(string $file, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------- -Liest ein Bild aus einer Datei und gibt seinen Typ in `$detectedFormat` zurück. Die unterstützten Typen sind `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` und `Image::BMP`. +Liest ein Bild aus einer Datei und gibt seinen [Typ |#Formats] in `$detectedFormat` zurück. static fromString(string $s, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------ -Liest ein Bild aus einer Zeichenkette und gibt seinen Typ in `$detectedFormat` zurück. Die unterstützten Typen sind `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, und `Image::BMP`. +Liest ein Bild aus einer Zeichenkette und gibt dessen [Typ |#Formats] in `$detectedFormat` zurück. static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method] @@ -241,27 +251,32 @@ Erzeugt eine Farbe, die in anderen Methoden verwendet werden kann, z. B. `ellips static typeToExtension(int $type): string .[method] --------------------------------------------------- -Gibt die Dateierweiterung für die angegebene Konstante `Image::XXX` zurück. +Gibt die Dateierweiterung für den angegebenen [Typ |#Formats] zurück. static typeToMimeType(int $type): string .[method] -------------------------------------------------- -Gibt den Mime-Typ für die angegebene Konstante `Image::XXX` zurück. +Gibt den Mime-Typ für den angegebenen [Typ |#Formats] zurück. static extensionToType(string $extension): int .[method] -------------------------------------------------------- -Gibt den Bildtyp als Konstante `Image::XXX` entsprechend der Dateierweiterung zurück. +Gibt den [Bildtyp |#Formats] entsprechend der Dateierweiterung zurück. static detectTypeFromFile(string $file, int &$width=null, int &$height=null): ?int .[method] -------------------------------------------------------------------------------------------- -Gibt den Typ der Bilddatei als Konstante `Image::XXX` zurück und in den Parametern `$width` und `$height` auch ihre Abmessungen. +Gibt den [Typ |#Formats] der Bilddatei und in den Parametern `$width` und `$height` auch die Abmessungen zurück. static detectTypeFromString(string $s, int &$width=null, int &$height=null): ?int .[method] ------------------------------------------------------------------------------------------- -Gibt den Typ des Bildes von string als `Image::XXX` Konstante zurück und in den Parametern `$width` und `$height` auch seine Abmessungen. +Gibt den [Typ |#Formats] des Bildes aus der Zeichenkette zurück und in den Parametern `$width` und `$height` auch seine Abmessungen. + + +static isTypeSupported(int $type): bool .[method] +------------------------------------------------- +Ermittelt, ob der angegebene [Bildtyp |#Formats] unterstützt wird. affine(array $affine, array $clip=null): Image .[method] @@ -586,7 +601,7 @@ save(string $file, int $quality=null, int $type=null): void .[method] --------------------------------------------------------------------- Speichert ein Bild in einer Datei. -Die Kompressionsqualität liegt im Bereich 0..100 für JPEG (Standard 85), WEBP (Standard 80) und AVIF (Standard 30) und 0..9 für PNG (Standard 9). Wenn der Typ nicht aus der Dateierweiterung ersichtlich ist, können Sie ihn mit einer der Konstanten `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` und `Image::BMP` angeben. +Die Kompressionsqualität liegt im Bereich 0..100 für JPEG (Standard 85), WEBP (Standard 80) und AVIF (Standard 30) und 0..9 für PNG (Standard 9). Wenn der Typ nicht aus der Dateierweiterung ersichtlich ist, können Sie ihn mit einer der Konstanten `ImageType` angeben. saveAlpha(bool $saveflag): void .[method] @@ -601,11 +616,11 @@ scale(int $newWidth, int $newHeight=-1, int $mode=IMG_BILINEAR_FIXED): Image .[m Skaliert ein Bild unter Verwendung des angegebenen Interpolationsalgorithmus. ([mehr |https://www.php.net/manual/en/function.imagescale]) -send(int $type=Image::JPEG, int $quality=null): void .[method] --------------------------------------------------------------- +send(int $type=ImageType::JPEG, int $quality=null): void .[method] +------------------------------------------------------------------ Gibt ein Bild an den Browser aus. -Die Kompressionsqualität liegt im Bereich 0..100 für JPEG (Standard 85), WEBP (Standard 80) und AVIF (Standard 30) und 0..9 für PNG (Standard 9). Typ ist eine der Konstanten `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` und `Image::BMP`. +Die Kompressionsqualität liegt im Bereich 0..100 für JPEG (Standard 85), WEBP (Standard 80) und AVIF (Standard 30) und 0..9 für PNG (Standard 9). setBrush(Image $brush): void .[method] @@ -663,11 +678,11 @@ stringUp(int $font, int $x, int $y, string $s, int $col): void .[method] Zeichnet eine Zeichenkette vertikal an den angegebenen Koordinaten. ([mehr |https://www.php.net/manual/en/function.imagestringup]) -toString(int $type=Image::JPEG, int $quality=null): string .[method] --------------------------------------------------------------------- +toString(int $type=ImageType::JPEG, int $quality=null): string .[method] +------------------------------------------------------------------------ Gibt ein Bild als String aus. -Die Kompressionsqualität liegt im Bereich 0..100 für JPEG (Standard 85), WEBP (Standard 80) und AVIF (Standard 30) und 0..9 für PNG (Standard 9). Typ ist eine der Konstanten `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` und `Image::BMP`. +Die Kompressionsqualität liegt im Bereich 0..100 für JPEG (Standard 85), WEBP (Standard 80) und AVIF (Standard 30) und 0..9 für PNG (Standard 9). trueColorToPalette(bool $dither, int $ncolors): void .[method] diff --git a/utils/el/images.texy b/utils/el/images.texy index 704d9f723c..e46fd27d6e 100644 --- a/utils/el/images.texy +++ b/utils/el/images.texy @@ -17,6 +17,7 @@ composer require nette/utils ```php use Nette\Utils\Image; +use Nette\Utils\ImageType; ``` @@ -41,17 +42,6 @@ $image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0)); $image = Image::fromFile('nette.jpg'); ``` -Οι υποστηριζόμενες μορφές είναι JPEG, PNG, GIF, WebP, AVIF και BMP, αλλά η έκδοση της PHP σας πρέπει επίσης να τις υποστηρίζει (ελέγξτε το `phpinfo()`, ενότητα GD). Τα κινούμενα σχέδια δεν υποστηρίζονται. - -Πρέπει να ανιχνεύσετε τη μορφή εικόνας κατά τη φόρτωση; Η μέθοδος επιστρέφει τη μορφή στη δεύτερη παράμετρο: - -```php -$image = Image::fromFile('nette.jpg', $type); -// $type είναι Image::JPEG, Image::PNG, Image::GIF, Image::WEBP, Image::AVIF ή Image::BMP -``` - -Μόνο η ανίχνευση χωρίς φόρτωση της εικόνας γίνεται από το `Image::detectTypeFromFile()`. - Αποθήκευση της εικόνας .[#toc-save-the-image] ============================================= @@ -68,25 +58,45 @@ $image->save('resampled.jpg'); $image->save('resampled.jpg', 80); // JPEG, ποιότητα 80% ``` -Εάν η μορφή δεν είναι προφανής από την επέκταση του αρχείου, μπορεί να καθοριστεί με μία από τις σταθερές `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` και `Image::BMP`: +Εάν η μορφή δεν είναι προφανής από την επέκταση του αρχείου, μπορεί να καθοριστεί με [σταθερά |#Formats]: ```php -$image->save('resampled.tmp', null, Image::JPEG); +$image->save('resampled.tmp', null, ImageType::JPEG); ``` Η εικόνα μπορεί να εγγραφεί σε μια μεταβλητή αντί στο δίσκο: ```php -$data = $image->toString(Image::JPEG, 80); // JPEG, ποιότητα 80% +$data = $image->toString(ImageType::JPEG, 80); // JPEG, ποιότητα 80% ``` ή να στείλετε απευθείας στο πρόγραμμα περιήγησης με την κατάλληλη επικεφαλίδα HTTP `Content-Type`: ```php // στέλνει επικεφαλίδα Content-Type: image/png -$image->send(Image::PNG); +$image->send(ImageType::PNG); +``` + + +Μορφές .[#toc-formats] +====================== + +Οι υποστηριζόμενοι μορφότυποι είναι JPEG, PNG, GIF, WebP, AVIF και BMP. Ωστόσο, πρέπει επίσης να υποστηρίζονται από την έκδοση της PHP σας, κάτι που μπορεί να επαληθευτεί με τη χρήση της συνάρτησης [isTypeSupported() |#isTypeSupported()]. Τα κινούμενα σχέδια δεν υποστηρίζονται. + +Οι μορφές αναπαρίστανται από τις σταθερές `ImageType::JPEG`, `ImageType::PNG`, `ImageType::GIF`, `ImageType::WEBP`, `ImageType::AVIF` και `ImageType::BMP`. + +```php +$supported = Image::isTypeSupported(ImageType::JPEG); ``` +Πρέπει να ανιχνεύσετε τη μορφή μιας εικόνας κατά τη φόρτωση; Η μέθοδος την επιστρέφει στη δεύτερη παράμετρο: + +```php +$image = Image::fromFile('nette.jpg', $type); +``` + +Η πραγματική ανίχνευση χωρίς φόρτωση της εικόνας πραγματοποιείται από τη διεύθυνση `Image::detectTypeFromFile()`. + Αλλαγή μεγέθους εικόνας .[#toc-image-resize] ============================================ @@ -226,12 +236,12 @@ static fromBlank(int $width, int $height, array $color=null): Image .[method] static fromFile(string $file, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------- -Διαβάζει μια εικόνα από ένα αρχείο και επιστρέφει τον τύπο της σε `$detectedFormat`. Οι υποστηριζόμενοι τύποι είναι `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` και `Image::BMP`. +Διαβάζει μια εικόνα από ένα αρχείο και επιστρέφει τον [τύπο |#Formats] της σε `$detectedFormat`. static fromString(string $s, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------ -Διαβάζει μια εικόνα από μια συμβολοσειρά και επιστρέφει τον τύπο της σε `$detectedFormat`. Οι υποστηριζόμενοι τύποι είναι `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` και `Image::BMP`. +Διαβάζει μια εικόνα από μια συμβολοσειρά και επιστρέφει τον [τύπο |#Formats] της σε `$detectedFormat`. static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method] @@ -241,27 +251,32 @@ static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method static typeToExtension(int $type): string .[method] --------------------------------------------------- -Επιστρέφει την επέκταση αρχείου για τη δεδομένη σταθερά `Image::XXX`. +Επιστρέφει την επέκταση αρχείου για τον δεδομένο [τύπο |#Formats]. static typeToMimeType(int $type): string .[method] -------------------------------------------------- -Επιστρέφει τον τύπο mime για τη δεδομένη σταθερά `Image::XXX`. +Επιστρέφει τον τύπο mime για τον δεδομένο [τύπο |#Formats]. static extensionToType(string $extension): int .[method] -------------------------------------------------------- -Επιστρέφει τον τύπο της εικόνας ως σταθερά `Image::XXX` σύμφωνα με την επέκταση του αρχείου. +Επιστρέφει τον [τύπο |#Formats] της εικόνας σύμφωνα με την επέκταση του αρχείου. static detectTypeFromFile(string $file, int &$width=null, int &$height=null): ?int .[method] -------------------------------------------------------------------------------------------- -Επιστρέφει τον τύπο του αρχείου εικόνας ως σταθερά `Image::XXX` και στις παραμέτρους `$width` και `$height` επίσης τις διαστάσεις του. +Επιστρέφει τον [τύπο |#Formats] του αρχείου εικόνας και στις παραμέτρους `$width` και `$height` επίσης τις διαστάσεις του. static detectTypeFromString(string $s, int &$width=null, int &$height=null): ?int .[method] ------------------------------------------------------------------------------------------- -Επιστρέφει τον τύπο της εικόνας από τη συμβολοσειρά ως σταθερά `Image::XXX` και στις παραμέτρους `$width` και `$height` επίσης τις διαστάσεις της. +Επιστρέφει τον [τύπο |#Formats] της εικόνας από το αλφαριθμητικό και στις παραμέτρους `$width` και `$height` επίσης τις διαστάσεις της. + + +static isTypeSupported(int $type): bool .[method] +------------------------------------------------- +Καθορίζει αν υποστηρίζεται ο συγκεκριμένος [τύπος |#Formats] εικόνας. affine(array $affine, array $clip=null): Image .[method] @@ -586,7 +601,7 @@ save(string $file, int $quality=null, int $type=null): void .[method] --------------------------------------------------------------------- Αποθηκεύει μια εικόνα σε ένα αρχείο. -Η ποιότητα συμπίεσης κυμαίνεται στο εύρος 0..100 για τα JPEG (προεπιλογή 85), WEBP (προεπιλογή 80) και AVIF (προεπιλογή 30) και 0..9 για το PNG (προεπιλογή 9). Εάν ο τύπος δεν είναι προφανής από την επέκταση του αρχείου, μπορείτε να τον καθορίσετε χρησιμοποιώντας μία από τις σταθερές `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` και `Image::BMP`. +Η ποιότητα συμπίεσης κυμαίνεται στο εύρος 0..100 για τα JPEG (προεπιλογή 85), WEBP (προεπιλογή 80) και AVIF (προεπιλογή 30) και 0..9 για το PNG (προεπιλογή 9). Εάν ο τύπος δεν είναι προφανής από την επέκταση του αρχείου, μπορείτε να τον καθορίσετε χρησιμοποιώντας μία από τις σταθερές `ImageType`. saveAlpha(bool $saveflag): void .[method] @@ -601,11 +616,11 @@ scale(int $newWidth, int $newHeight=-1, int $mode=IMG_BILINEAR_FIXED): Image .[m Κλιμακώνει μια εικόνα χρησιμοποιώντας τον δεδομένο αλγόριθμο παρεμβολής. ([περισσότερα |https://www.php.net/manual/en/function.imagescale]) -send(int $type=Image::JPEG, int $quality=null): void .[method] --------------------------------------------------------------- +send(int $type=ImageType::JPEG, int $quality=null): void .[method] +------------------------------------------------------------------ Εκδίδει μια εικόνα στο πρόγραμμα περιήγησης. -Η ποιότητα συμπίεσης κυμαίνεται στο εύρος 0..100 για τα JPEG (προεπιλογή 85), WEBP (προεπιλογή 80) και AVIF (προεπιλογή 30) και 0..9 για το PNG (προεπιλογή 9). Ο τύπος είναι μία από τις σταθερές `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` και `Image::BMP`. +Η ποιότητα συμπίεσης κυμαίνεται στο εύρος 0..100 για τα JPEG (προεπιλογή 85), WEBP (προεπιλογή 80) και AVIF (προεπιλογή 30) και 0..9 για το PNG (προεπιλογή 9). setBrush(Image $brush): void .[method] @@ -663,11 +678,11 @@ stringUp(int $font, int $x, int $y, string $s, int $col): void .[method] Σχεδιάζει μια συμβολοσειρά κάθετα στις δεδομένες συντεταγμένες. ([περισσότερα |https://www.php.net/manual/en/function.imagestringup]) -toString(int $type=Image::JPEG, int $quality=null): string .[method] --------------------------------------------------------------------- +toString(int $type=ImageType::JPEG, int $quality=null): string .[method] +------------------------------------------------------------------------ Εξάγει μια εικόνα σε συμβολοσειρά. -Η ποιότητα συμπίεσης κυμαίνεται στο εύρος 0..100 για τα JPEG (προεπιλογή 85), WEBP (προεπιλογή 80) και AVIF (προεπιλογή 30) και 0..9 για το PNG (προεπιλογή 9). Ο τύπος είναι μία από τις σταθερές `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` και `Image::BMP`. +Η ποιότητα συμπίεσης κυμαίνεται στο εύρος 0..100 για τα JPEG (προεπιλογή 85), WEBP (προεπιλογή 80) και AVIF (προεπιλογή 30) και 0..9 για το PNG (προεπιλογή 9). trueColorToPalette(bool $dither, int $ncolors): void .[method] diff --git a/utils/en/images.texy b/utils/en/images.texy index 8226cce7b6..d1d5c12c93 100644 --- a/utils/en/images.texy +++ b/utils/en/images.texy @@ -17,6 +17,7 @@ Following examples assume the following class alias is defined: ```php use Nette\Utils\Image; +use Nette\Utils\ImageType; ``` @@ -41,17 +42,6 @@ Or we load the image from a file: $image = Image::fromFile('nette.jpg'); ``` -Supported formats are JPEG, PNG, GIF, WebP, AVIF and BMP, but your version of PHP must also support them (check the `phpinfo()`, section GD). Animations are not supported. - -Need to detect the image format when loading? The method returns format in the second parameter: - -```php -$image = Image::fromFile('nette.jpg', $type); -// $type is Image::JPEG, Image::PNG, Image::GIF, Image::WEBP, Image::AVIF or Image::BMP -``` - -Only the detection without loading the image is done by `Image::detectTypeFromFile()`. - Save the Image ============== @@ -68,25 +58,45 @@ We can specify compression quality in the range 0..100 for JPEG (default 85), WE $image->save('resampled.jpg', 80); // JPEG, quality 80% ``` -If the format is not obvious from the file extension, it can be specified by one of the constants `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, and `Image::BMP`: +If the format is not obvious from the file extension, it can be specified by [constant|#Formats]: ```php -$image->save('resampled.tmp', null, Image::JPEG); +$image->save('resampled.tmp', null, ImageType::JPEG); ``` The image can be written to a variable instead of to disk: ```php -$data = $image->toString(Image::JPEG, 80); // JPEG, quality 80% +$data = $image->toString(ImageType::JPEG, 80); // JPEG, quality 80% ``` or send directly to the browser with the appropriate HTTP header `Content-Type`: ```php // sends header Content-Type: image/png -$image->send(Image::PNG); +$image->send(ImageType::PNG); +``` + + +Formats +======= + +Supported formats are JPEG, PNG, GIF, WebP, AVIF, and BMP. However, they must also be supported by your version of PHP, which can be verified using the [#isTypeSupported()] function. Animations are not supported. + +The formats are represented by constants `ImageType::JPEG`, `ImageType::PNG`, `ImageType::GIF`, `ImageType::WEBP`, `ImageType::AVIF`, and `ImageType::BMP`. + +```php +$supported = Image::isTypeSupported(ImageType::JPEG); ``` +Need to detect the format of an image upon loading? The method returns it in the second parameter: + +```php +$image = Image::fromFile('nette.jpg', $type); +``` + +The actual detection without loading the image is performed by `Image::detectTypeFromFile()`. + Image Resize ============ @@ -226,12 +236,12 @@ Creates a new true color image of the given dimensions. The default color is bla static fromFile(string $file, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------- -Reads an image from a file and returns its type in `$detectedFormat`. The supported types are `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` and `Image::BMP`. +Reads an image from a file and returns its [type|#Formats] in `$detectedFormat`. static fromString(string $s, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------ -Reads an image from a string and returns its type in `$detectedFormat`. The supported types are `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, and `Image::BMP`. +Reads an image from a string and returns its [type|#Formats] in `$detectedFormat`. static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method] @@ -241,27 +251,32 @@ Creates a color that can be used in other methods, such as `ellipse()`, `fill()` static typeToExtension(int $type): string .[method] --------------------------------------------------- -Returns the file extension for the given `Image::XXX` constant. +Returns the file extension for the given [type|#Formats]. static typeToMimeType(int $type): string .[method] -------------------------------------------------- -Returns the mime type for the given `Image::XXX` constant. +Returns the mime type for the given [type|#Formats]. static extensionToType(string $extension): int .[method] -------------------------------------------------------- -Returns the image type as a constant `Image::XXX` according to the file extension. +Returns the image [type|#Formats] according to the file extension. static detectTypeFromFile(string $file, int &$width=null, int &$height=null): ?int .[method] -------------------------------------------------------------------------------------------- -Returns the type of image file as `Image::XXX` constant and in the `$width` and `$height` parameters also its dimensions. +Returns the [type|#Formats] of image file and in the `$width` and `$height` parameters also its dimensions. static detectTypeFromString(string $s, int &$width=null, int &$height=null): ?int .[method] ------------------------------------------------------------------------------------------- -Returns the type of image from string as `Image::XXX` constant and in the `$width` and `$height` parameters also its dimensions. +Returns the [type|#Formats] of image from string and in the `$width` and `$height` parameters also its dimensions. + + +static isTypeSupported(int $type): bool .[method] +------------------------------------------------- +Determines if the given image [type|#Formats] is supported. affine(array $affine, array $clip=null): Image .[method] @@ -586,7 +601,7 @@ save(string $file, int $quality=null, int $type=null): void .[method] --------------------------------------------------------------------- Saves an image to a file. -The compression quality is in the range 0..100 for JPEG (default 85), WEBP (default 80) and AVIF (default 30) and 0..9 for PNG (default 9). If the type is not obvious from the file extension, you can specify it using one of the constants `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, and `Image::BMP`. +The compression quality is in the range 0..100 for JPEG (default 85), WEBP (default 80) and AVIF (default 30) and 0..9 for PNG (default 9). If the type is not obvious from the file extension, you can specify it using one of the `ImageType` constants. saveAlpha(bool $saveflag): void .[method] @@ -601,11 +616,11 @@ scale(int $newWidth, int $newHeight=-1, int $mode=IMG_BILINEAR_FIXED): Image .[m Scales an image using the given interpolation algorithm. ([more|https://www.php.net/manual/en/function.imagescale]) -send(int $type=Image::JPEG, int $quality=null): void .[method] --------------------------------------------------------------- +send(int $type=ImageType::JPEG, int $quality=null): void .[method] +------------------------------------------------------------------ Outputs an image to the browser. -The compression quality is in the range 0..100 for JPEG (default 85), WEBP (default 80) and AVIF (default 30) and 0..9 for PNG (default 9). Type is one of the constants `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` and `Image::BMP`. +The compression quality is in the range 0..100 for JPEG (default 85), WEBP (default 80) and AVIF (default 30) and 0..9 for PNG (default 9). setBrush(Image $brush): void .[method] @@ -663,11 +678,11 @@ stringUp(int $font, int $x, int $y, string $s, int $col): void .[method] Draws a string vertically at the given coordinates. ([more|https://www.php.net/manual/en/function.imagestringup]) -toString(int $type=Image::JPEG, int $quality=null): string .[method] --------------------------------------------------------------------- +toString(int $type=ImageType::JPEG, int $quality=null): string .[method] +------------------------------------------------------------------------ Outputs an image to string. -The compression quality is in the range 0..100 for JPEG (default 85), WEBP (default 80) and AVIF (default 30) and 0..9 for PNG (default 9). Type is one of the constants `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` and `Image::BMP`. +The compression quality is in the range 0..100 for JPEG (default 85), WEBP (default 80) and AVIF (default 30) and 0..9 for PNG (default 9). trueColorToPalette(bool $dither, int $ncolors): void .[method] diff --git a/utils/es/images.texy b/utils/es/images.texy index 2f9f140d87..f48770b3fb 100644 --- a/utils/es/images.texy +++ b/utils/es/images.texy @@ -17,6 +17,7 @@ Los siguientes ejemplos suponen que se ha definido el siguiente alias de clase: ```php use Nette\Utils\Image; +use Nette\Utils\ImageType; ``` @@ -41,17 +42,6 @@ O cargamos la imagen desde un archivo: $image = Image::fromFile('nette.jpg'); ``` -Los formatos soportados son JPEG, PNG, GIF, WebP, AVIF y BMP, pero su versión de PHP también debe soportarlos (compruebe la `phpinfo()`, sección GD). No se admiten animaciones. - -¿Necesita detectar el formato de la imagen al cargarla? El método devuelve el formato en el segundo parámetro: - -```php -$image = Image::fromFile('nette.jpg', $type); -// $type es Image::JPEG, Image::PNG, Image::GIF, Image::WEBP, Image::AVIF o Image::BMP -``` - -Sólo la detección sin carga de la imagen se realiza mediante `Image::detectTypeFromFile()`. - Guardar la imagen .[#toc-save-the-image] ======================================== @@ -68,26 +58,46 @@ Podemos especificar la calidad de compresión en el rango 0..100 para JPEG (por $image->save('resampled.jpg', 80); // JPEG, quality 80% ``` -Si el formato no resulta obvio a partir de la extensión del archivo, puede especificarse mediante una de las constantes `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` y `Image::BMP`: +Si el formato no es obvio a partir de la extensión del archivo, puede especificarse mediante [una constante |#Formats]: ```php -$image->save('resampled.tmp', null, Image::JPEG); +$image->save('resampled.tmp', null, ImageType::JPEG); ``` La imagen puede escribirse en una variable en lugar de en el disco: ```php -$data = $image->toString(Image::JPEG, 80); // JPEG, quality 80% +$data = $image->toString(ImageType::JPEG, 80); // JPEG, quality 80% ``` o enviar directamente al navegador con el encabezado HTTP apropiado `Content-Type`: ```php // sends header Content-Type: image/png -$image->send(Image::PNG); +$image->send(ImageType::PNG); ``` +Formatos .[#toc-formats] +======================== + +Los formatos soportados son JPEG, PNG, GIF, WebP, AVIF y BMP. Sin embargo, también deben ser soportados por su versión de PHP, lo cual puede ser verificado usando la función [isTypeSupported() |#isTypeSupported()]. Las animaciones no están soportadas. + +Los formatos están representados por las constantes `ImageType::JPEG`, `ImageType::PNG`, `ImageType::GIF`, `ImageType::WEBP`, `ImageType::AVIF`, y `ImageType::BMP`. + +```php +$supported = Image::isTypeSupported(ImageType::JPEG); +``` + +¿Necesita detectar el formato de una imagen al cargarla? El método lo devuelve en el segundo parámetro: + +```php +$image = Image::fromFile('nette.jpg', $type); +``` + +La detección real sin cargar la imagen la realiza `Image::detectTypeFromFile()`. + + Redimensionar imagen .[#toc-image-resize] ========================================= @@ -226,12 +236,12 @@ Crea una nueva imagen en color verdadero de las dimensiones dadas. El color por static fromFile(string $file, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------- -Lee una imagen de un archivo y devuelve su tipo en `$detectedFormat`. Los tipos admitidos son `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` y `Image::BMP`. +Lee una imagen de un archivo y devuelve su [tipo |#Formats] en `$detectedFormat`. static fromString(string $s, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------ -Lee una imagen de una cadena y devuelve su tipo en `$detectedFormat`. Los tipos admitidos son `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` y `Image::BMP`. +Lee una imagen de una cadena y devuelve su [tipo |#Formats] en `$detectedFormat`. static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method] @@ -241,27 +251,32 @@ Crea un color que puede utilizarse en otros métodos, como `ellipse()`, `fill()` static typeToExtension(int $type): string .[method] --------------------------------------------------- -Devuelve la extensión de archivo para la constante `Image::XXX` dada. +Devuelve la extensión de archivo para el [tipo |#Formats] dado. static typeToMimeType(int $type): string .[method] -------------------------------------------------- -Devuelve el tipo mime para la constante `Image::XXX` dada. +Devuelve el tipo mime para el [tipo |#Formats] dado. static extensionToType(string $extension): int .[method] -------------------------------------------------------- -Devuelve el tipo de imagen como una constante `Image::XXX` según la extensión del archivo. +Devuelve el [tipo de |#Formats] imagen según la extensión del archivo. static detectTypeFromFile(string $file, int &$width=null, int &$height=null): ?int .[method] -------------------------------------------------------------------------------------------- -Devuelve el tipo de archivo de imagen como constante `Image::XXX` y en los parámetros `$width` y `$height` también sus dimensiones. +Devuelve el [tipo |#Formats] de archivo de imagen y en los parámetros `$width` y `$height` también sus dimensiones. static detectTypeFromString(string $s, int &$width=null, int &$height=null): ?int .[method] ------------------------------------------------------------------------------------------- -Devuelve el tipo de imagen a partir de la cadena como constante `Image::XXX` y en los parámetros `$width` y `$height` también sus dimensiones. +Devuelve el [tipo |#Formats] de imagen a partir de la cadena y en los parámetros `$width` y `$height` también sus dimensiones. + + +static isTypeSupported(int $type): bool .[method] +------------------------------------------------- +Determina si el [tipo de |#Formats] imagen dado es compatible. affine(array $affine, array $clip=null): Image .[method] @@ -586,7 +601,7 @@ save(string $file, int $quality=null, int $type=null): void .[method] --------------------------------------------------------------------- Guarda una imagen en un archivo. -La calidad de compresión está en el rango 0..100 para JPEG (por defecto 85), WEBP (por defecto 80) y AVIF (por defecto 30) y 0..9 para PNG (por defecto 9). Si el tipo no es obvio a partir de la extensión del archivo, puede especificarlo utilizando una de las constantes `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, y `Image::BMP`. +La calidad de compresión está en el rango 0..100 para JPEG (por defecto 85), WEBP (por defecto 80) y AVIF (por defecto 30) y 0..9 para PNG (por defecto 9). Si el tipo no es obvio a partir de la extensión del archivo, puede especificarlo utilizando una de las constantes de `ImageType`. saveAlpha(bool $saveflag): void .[method] @@ -601,11 +616,11 @@ scale(int $newWidth, int $newHeight=-1, int $mode=IMG_BILINEAR_FIXED): Image .[m Escala una imagen utilizando el algoritmo de interpolación dado. ([más |https://www.php.net/manual/en/function.imagescale]) -send(int $type=Image::JPEG, int $quality=null): void .[method] --------------------------------------------------------------- +send(int $type=ImageType::JPEG, int $quality=null): void .[method] +------------------------------------------------------------------ Envía una imagen al navegador. -La calidad de compresión está en el rango 0..100 para JPEG (por defecto 85), WEBP (por defecto 80) y AVIF (por defecto 30) y 0..9 para PNG (por defecto 9). El tipo es una de las constantes `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` y `Image::BMP`. +La calidad de compresión está en el rango 0..100 para JPEG (por defecto 85), WEBP (por defecto 80) y AVIF (por defecto 30) y 0..9 para PNG (por defecto 9). setBrush(Image $brush): void .[method] @@ -663,11 +678,11 @@ stringUp(int $font, int $x, int $y, string $s, int $col): void .[method] Dibuja una cadena verticalmente en las coordenadas dadas. ([más |https://www.php.net/manual/en/function.imagestringup]) -toString(int $type=Image::JPEG, int $quality=null): string .[method] --------------------------------------------------------------------- +toString(int $type=ImageType::JPEG, int $quality=null): string .[method] +------------------------------------------------------------------------ Muestra una imagen en una cadena. -La calidad de compresión está en el rango 0..100 para JPEG (por defecto 85), WEBP (por defecto 80) y AVIF (por defecto 30) y 0..9 para PNG (por defecto 9). El tipo es una de las constantes `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` y `Image::BMP`. +La calidad de compresión está en el rango 0..100 para JPEG (por defecto 85), WEBP (por defecto 80) y AVIF (por defecto 30) y 0..9 para PNG (por defecto 9). trueColorToPalette(bool $dither, int $ncolors): void .[method] diff --git a/utils/fr/images.texy b/utils/fr/images.texy index 94e3677f74..2ec50576cf 100644 --- a/utils/fr/images.texy +++ b/utils/fr/images.texy @@ -17,6 +17,7 @@ Les exemples suivants supposent que l'alias de classe suivant est défini : ```php use Nette\Utils\Image; +use Nette\Utils\ImageType; ``` @@ -41,17 +42,6 @@ Ou nous chargeons l'image depuis un fichier : $image = Image::fromFile('nette.jpg'); ``` -Les formats pris en charge sont JPEG, PNG, GIF, WebP, AVIF et BMP, mais votre version de PHP doit également les prendre en charge (consultez le site `phpinfo()`, section GD). Les animations ne sont pas prises en charge. - -Vous avez besoin de détecter le format de l'image lors du chargement ? La méthode renvoie le format dans le deuxième paramètre : - -```php -$image = Image::fromFile('nette.jpg', $type); -// $type est Image::JPEG, Image::PNG, Image::GIF, Image::WEBP, Image::AVIF ou Image::BMP -``` - -Seule la détection sans chargement de l'image est effectuée par `Image::detectTypeFromFile()`. - Sauvegarder l'image .[#toc-save-the-image] ========================================== @@ -68,25 +58,45 @@ Nous pouvons spécifier une qualité de compression comprise entre 0 et 100 pour $image->save('resampled.jpg', 80); // JPEG, qualité 80 ``` -Si le format ne ressort pas clairement de l'extension du fichier, il peut être spécifié par l'une des constantes suivantes : `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, et `Image::BMP`: +Si le format ne ressort pas clairement de l'extension du fichier, il peut être spécifié par une [constante |#Formats]: ```php -$image->save('resampled.tmp', null, Image::JPEG); +$image->save('resampled.tmp', null, ImageType::JPEG); ``` L'image peut être écrite dans une variable plutôt que sur le disque : ```php -$data = $image->toString(Image::JPEG, 80); // JPEG, qualité 80%. +$data = $image->toString(ImageType::JPEG, 80); // JPEG, qualité 80%. ``` ou envoyer directement au navigateur avec l'en-tête HTTP approprié `Content-Type`: ```php // envoie l'en-tête Content-Type: image/png -$image->send(Image::PNG); +$image->send(ImageType::PNG); +``` + + +Formats .[#toc-formats] +======================= + +Les formats supportés sont JPEG, PNG, GIF, WebP, AVIF et BMP. Cependant, ils doivent également être supportés par votre version de PHP, ce qui peut être vérifié à l'aide de la fonction [isTypeSupported() |#isTypeSupported()]. Les animations ne sont pas prises en charge. + +Les formats sont représentés par les constantes `ImageType::JPEG`, `ImageType::PNG`, `ImageType::GIF`, `ImageType::WEBP`, `ImageType::AVIF`, et `ImageType::BMP`. + +```php +$supported = Image::isTypeSupported(ImageType::JPEG); ``` +Besoin de détecter le format d'une image au chargement ? La méthode le renvoie dans le second paramètre : + +```php +$image = Image::fromFile('nette.jpg', $type); +``` + +La détection proprement dite, sans chargement de l'image, est effectuée par `Image::detectTypeFromFile()`. + Redimensionnement de l'image .[#toc-image-resize] ================================================= @@ -226,12 +236,12 @@ Crée une nouvelle image en couleurs réelles avec les dimensions données. La c static fromFile(string $file, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------- -Lit une image à partir d'un fichier et renvoie son type à `$detectedFormat`. Les types supportés sont `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` et `Image::BMP`. +Lit une image à partir d'un fichier et renvoie son [type |#Formats] à `$detectedFormat`. static fromString(string $s, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------ -Lit une image à partir d'une chaîne de caractères et renvoie son type à `$detectedFormat`. Les types supportés sont `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, et `Image::BMP`. +Lit une image à partir d'une chaîne de caractères et renvoie son [type |#Formats] à `$detectedFormat`. static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method] @@ -241,27 +251,32 @@ Crée une couleur qui peut être utilisée dans d'autres méthodes, telles que ` static typeToExtension(int $type): string .[method] --------------------------------------------------- -Renvoie l'extension de fichier pour la constante `Image::XXX` donnée. +Renvoie l'extension du fichier pour le [type |#Formats] donné. static typeToMimeType(int $type): string .[method] -------------------------------------------------- -Renvoie le type de mime pour la constante `Image::XXX` donnée. +Renvoie le type de mime pour le [type |#Formats] donné. static extensionToType(string $extension): int .[method] -------------------------------------------------------- -Renvoie le type d'image sous la forme d'une constante `Image::XXX` en fonction de l'extension du fichier. +Renvoie le [type d' |#Formats] image en fonction de l'extension du fichier. static detectTypeFromFile(string $file, int &$width=null, int &$height=null): ?int .[method] -------------------------------------------------------------------------------------------- -Renvoie le type de fichier image comme constante `Image::XXX` et dans les paramètres `$width` et `$height` également ses dimensions. +Renvoie le [type de |#Formats] fichier image et, dans les paramètres `$width` et `$height`, ses dimensions. static detectTypeFromString(string $s, int &$width=null, int &$height=null): ?int .[method] ------------------------------------------------------------------------------------------- -Renvoie le type d'image de la chaîne de caractères comme constante `Image::XXX` et dans les paramètres `$width` et `$height` également ses dimensions. +Renvoie le [type d' |#Formats] image à partir d'une chaîne de caractères et, dans les paramètres `$width` et `$height`, ses dimensions. + + +static isTypeSupported(int $type): bool .[method] +------------------------------------------------- +Détermine si le [type d' |#Formats] image donné est pris en charge. affine(array $affine, array $clip=null): Image .[method] @@ -586,7 +601,7 @@ save(string $file, int $quality=null, int $type=null): void .[method] --------------------------------------------------------------------- Enregistre une image dans un fichier. -La qualité de la compression est comprise entre 0 et 100 pour JPEG (85 par défaut), WEBP (80 par défaut) et AVIF (30 par défaut) et entre 0 et 9 pour PNG (9 par défaut). Si le type n'est pas évident à partir de l'extension du fichier, vous pouvez le spécifier en utilisant l'une des constantes `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, et `Image::BMP`. +La qualité de la compression est comprise entre 0 et 100 pour JPEG (85 par défaut), WEBP (80 par défaut) et AVIF (30 par défaut) et entre 0 et 9 pour PNG (9 par défaut). Si le type n'est pas évident à partir de l'extension du fichier, vous pouvez le spécifier en utilisant l'une des constantes `ImageType`. saveAlpha(bool $saveflag): void .[method] @@ -601,11 +616,11 @@ scale(int $newWidth, int $newHeight=-1, int $mode=IMG_BILINEAR_FIXED): Image .[m Met à l'échelle une image en utilisant l'algorithme d'interpolation donné. ([plus |https://www.php.net/manual/en/function.imagescale]) -send(int $type=Image::JPEG, int $quality=null): void .[method] --------------------------------------------------------------- +send(int $type=ImageType::JPEG, int $quality=null): void .[method] +------------------------------------------------------------------ Affiche une image dans le navigateur. -La qualité de la compression est comprise entre 0 et 100 pour JPEG (85 par défaut), WEBP (80 par défaut) et AVIF (30 par défaut) et entre 0 et 9 pour PNG (9 par défaut). Type est l'une des constantes suivantes : `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` et `Image::BMP`. +La qualité de la compression est comprise entre 0 et 100 pour JPEG (85 par défaut), WEBP (80 par défaut) et AVIF (30 par défaut) et entre 0 et 9 pour PNG (9 par défaut). setBrush(Image $brush): void .[method] @@ -663,11 +678,11 @@ stringUp(int $font, int $x, int $y, string $s, int $col): void .[method] Dessine une chaîne verticalement aux coordonnées données. ([plus |https://www.php.net/manual/en/function.imagestringup]) -toString(int $type=Image::JPEG, int $quality=null): string .[method] --------------------------------------------------------------------- +toString(int $type=ImageType::JPEG, int $quality=null): string .[method] +------------------------------------------------------------------------ Produit une image sous forme de chaîne. -La qualité de la compression est comprise entre 0 et 100 pour JPEG (85 par défaut), WEBP (80 par défaut) et AVIF (30 par défaut) et entre 0 et 9 pour PNG (9 par défaut). Type est l'une des constantes suivantes : `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` et `Image::BMP`. +La qualité de la compression est comprise entre 0 et 100 pour JPEG (85 par défaut), WEBP (80 par défaut) et AVIF (30 par défaut) et entre 0 et 9 pour PNG (9 par défaut). trueColorToPalette(bool $dither, int $ncolors): void .[method] diff --git a/utils/hu/images.texy b/utils/hu/images.texy index f267d98de0..cbd13836c8 100644 --- a/utils/hu/images.texy +++ b/utils/hu/images.texy @@ -17,6 +17,7 @@ A következő példák feltételezik, hogy a következő osztály alias van defi ```php use Nette\Utils\Image; +use Nette\Utils\ImageType; ``` @@ -41,17 +42,6 @@ Vagy betöltjük a képet egy fájlból: $image = Image::fromFile('nette.jpg'); ``` -A támogatott formátumok a JPEG, PNG, GIF, WebP, AVIF és BMP, de a PHP verziójának támogatnia kell ezeket (ellenőrizze a `phpinfo()`, GD szakaszban). Az animációk nem támogatottak. - -Fel kell ismernie a képformátumot betöltéskor? A módszer a formátumot adja vissza a második paraméterben: - -```php -$image = Image::fromFile('nette.jpg', $type); -// $type az Image::JPEG, Image::PNG, Image::GIF, Image::WEBP, Image::AVIF vagy Image::BMP. -``` - -Csak a kép betöltése nélküli felismerést végzi a `Image::detectTypeFromFile()`. - A kép mentése .[#toc-save-the-image] ==================================== @@ -68,25 +58,45 @@ A tömörítési minőséget a JPEG (alapértelmezett 85), WEBP (alapértelmezet $image->save('resampled.jpg', 80); // JPEG, minőség 80% ``` -Ha a formátum nem egyértelmű a fájlkiterjesztésből, akkor a `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` és `Image::BMP` konstansok valamelyikével adható meg: +Ha a formátum nem egyértelmű a fájlkiterjesztésből, akkor [konstanssal |#Formats] is megadható: ```php -$image->save('resampled.tmp', null, Image::JPEG); +$image->save('resampled.tmp', null, ImageType::JPEG); ``` A képet lemez helyett egy változóba is ki lehet írni: ```php -$data = $image->toString(Image::JPEG, 80); // JPEG, minőség 80%. +$data = $image->toString(ImageType::JPEG, 80); // JPEG, minőség 80%. ``` vagy közvetlenül a böngészőnek a megfelelő HTTP fejléccel `Content-Type`: ```php // fejlécet küld Content-Type: image/png -$image->send(Image::PNG); +$image->send(ImageType::PNG); +``` + + +Formátumok .[#toc-formats] +========================== + +Támogatott formátumok: JPEG, PNG, GIF, WebP, AVIF és BMP. Ezeket azonban a PHP verziójának is támogatnia kell, amit az [isTypeSupported() |#isTypeSupported()] függvény segítségével ellenőrizhet. Az animációk nem támogatottak. + +A formátumokat a `ImageType::JPEG`, `ImageType::PNG`, `ImageType::GIF`, `ImageType::WEBP`, `ImageType::AVIF` és `ImageType::BMP` konstansok jelölik. + +```php +$supported = Image::isTypeSupported(ImageType::JPEG); ``` +Fel kell ismernie egy kép formátumát betöltéskor? A módszer ezt a második paraméterben adja vissza: + +```php +$image = Image::fromFile('nette.jpg', $type); +``` + +A tényleges felismerést a kép betöltése nélkül a `Image::detectTypeFromFile()` végzi. + Kép átméretezése .[#toc-image-resize] ===================================== @@ -226,12 +236,12 @@ static fromBlank(int $width, int $height, array $color=null): Image .[method] static fromFile(string $file, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------- -Beolvas egy képet egy fájlból, és visszaadja a típusát a `$detectedFormat` címen. A támogatott típusok: `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` és `Image::BMP`. +Beolvas egy képet egy fájlból, és visszaadja a [típusát |#Formats] a `$detectedFormat` címen. static fromString(string $s, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------ -Beolvas egy képet egy karakterláncból, és visszaadja a típusát a `$detectedFormat` címen. A támogatott típusok: `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` és `Image::BMP`. +Beolvas egy képet egy karakterláncból, és visszaadja [a típusát |#Formats] a `$detectedFormat` címen. static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method] @@ -241,27 +251,32 @@ Létrehoz egy színt, amely más módszerekben, például a `ellipse()`, `fill() static typeToExtension(int $type): string .[method] --------------------------------------------------- -Visszaadja az adott `Image::XXX` konstans fájlkiterjesztését. +Visszaadja az adott [típushoz |#Formats] tartozó fájlkiterjesztést. static typeToMimeType(int $type): string .[method] -------------------------------------------------- -Visszaadja a megadott `Image::XXX` konstans mime típusát. +Visszaadja az adott [típus |#Formats] mime típusát. static extensionToType(string $extension): int .[method] -------------------------------------------------------- -Visszaadja a kép típusát a `Image::XXX` konstansként a fájlkiterjesztésnek megfelelően. +Visszaadja a kép [típusát |#Formats] a fájlkiterjesztésnek megfelelően. static detectTypeFromFile(string $file, int &$width=null, int &$height=null): ?int .[method] -------------------------------------------------------------------------------------------- -Visszaadja a képfájl típusát a `Image::XXX` konstansként, valamint a `$width` és `$height` paraméterekben a méreteit is. +Visszaadja a képfájl [típusát |#Formats] és a `$width` és `$height` paraméterekben a méreteit is. static detectTypeFromString(string $s, int &$width=null, int &$height=null): ?int .[method] ------------------------------------------------------------------------------------------- -Visszaadja a kép típusát a stringből a `Image::XXX` konstansként, és a `$width` és `$height` paraméterekben a méreteit is. +Visszaadja a kép [típusát |#Formats] a stringből és a `$width` és `$height` paraméterekben a méreteit is. + + +static isTypeSupported(int $type): bool .[method] +------------------------------------------------- +Megállapítja, hogy az adott [képtípus |#Formats] támogatott-e. affine(array $affine, array $clip=null): Image .[method] @@ -586,7 +601,7 @@ save(string $file, int $quality=null, int $type=null): void .[method] --------------------------------------------------------------------- Kép mentése egy fájlba. -A tömörítési minőség a JPEG (alapértelmezett 85), WEBP (alapértelmezett 80) és AVIF (alapértelmezett 30) esetében 0..100, PNG (alapértelmezett 9) esetében pedig 0..9 tartományban van. Ha a típus nem egyértelmű a fájlkiterjesztésből, akkor a `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` és `Image::BMP` konstansok valamelyikével adhatja meg. +A tömörítési minőség a JPEG (alapértelmezett 85), WEBP (alapértelmezett 80) és AVIF (alapértelmezett 30) esetében 0..100, PNG (alapértelmezett 9) esetében 0..9 tartományban van. Ha a típus nem egyértelmű a fájlkiterjesztésből, akkor a `ImageType` konstansok egyikével adhatja meg. saveAlpha(bool $saveflag): void .[method] @@ -601,11 +616,11 @@ scale(int $newWidth, int $newHeight=-1, int $mode=IMG_BILINEAR_FIXED): Image .[m A megadott interpolációs algoritmus segítségével méretezi a képet. ([tovább |https://www.php.net/manual/en/function.imagescale]) -send(int $type=Image::JPEG, int $quality=null): void .[method] --------------------------------------------------------------- +send(int $type=ImageType::JPEG, int $quality=null): void .[method] +------------------------------------------------------------------ Kimeneti egy képet a böngészőbe. -A tömörítési minőség a JPEG (alapértelmezett 85), WEBP (alapértelmezett 80) és AVIF (alapértelmezett 30) esetében 0..100, PNG (alapértelmezett 9) esetében 0..9 tartományban van. A típus a `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` és `Image::BMP` konstansok egyike. +A tömörítési minőség a JPEG (alapértelmezett 85), WEBP (alapértelmezett 80) és AVIF (alapértelmezett 30) esetében 0..100, PNG (alapértelmezett 9) esetében 0..9 tartományban van. setBrush(Image $brush): void .[method] @@ -663,11 +678,11 @@ stringUp(int $font, int $x, int $y, string $s, int $col): void .[method] Egy sztringet rajzol függőlegesen a megadott koordinátákhoz. ([tovább |https://www.php.net/manual/en/function.imagestringup]) -toString(int $type=Image::JPEG, int $quality=null): string .[method] --------------------------------------------------------------------- +toString(int $type=ImageType::JPEG, int $quality=null): string .[method] +------------------------------------------------------------------------ Kimeneti képet ad ki stringként. -A tömörítési minőség a JPEG (alapértelmezett 85), WEBP (alapértelmezett 80) és AVIF (alapértelmezett 30) esetében 0..100, PNG (alapértelmezett 9) esetében 0..9 tartományban van. A típus a `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` és `Image::BMP` konstansok egyike. +A tömörítési minőség a JPEG (alapértelmezett 85), WEBP (alapértelmezett 80) és AVIF (alapértelmezett 30) esetében 0..100, PNG (alapértelmezett 9) esetében 0..9 tartományban van. trueColorToPalette(bool $dither, int $ncolors): void .[method] diff --git a/utils/it/images.texy b/utils/it/images.texy index f8888325f6..fe8b6ec2c0 100644 --- a/utils/it/images.texy +++ b/utils/it/images.texy @@ -17,6 +17,7 @@ Gli esempi seguenti presuppongono che sia stato definito il seguente alias di cl ```php use Nette\Utils\Image; +use Nette\Utils\ImageType; ``` @@ -41,17 +42,6 @@ Oppure si carica l'immagine da un file: $image = Image::fromFile('nette.jpg'); ``` -I formati supportati sono JPEG, PNG, GIF, WebP, AVIF e BMP, ma è necessario che anche la vostra versione di PHP li supporti (controllate `phpinfo()`, sezione GD). Le animazioni non sono supportate. - -È necessario rilevare il formato dell'immagine durante il caricamento? Il metodo restituisce il formato nel secondo parametro: - -```php -$image = Image::fromFile('nette.jpg', $type); -// $tipo è Immagine::JPEG, Immagine::PNG, Immagine::GIF, Immagine::WEBP, Immagine::AVIF o Immagine::BMP -``` - -Solo il rilevamento senza caricamento dell'immagine viene effettuato da `Image::detectTypeFromFile()`. - Salvare l'immagine .[#toc-save-the-image] ========================================= @@ -68,25 +58,45 @@ $image->save('resampled.jpg'); $image->save('resampled.jpg', 80); // JPEG, qualità 80% ``` -Se il formato non è evidente dall'estensione del file, può essere specificato da una delle costanti `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, e `Image::BMP`: +Se il formato non è evidente dall'estensione del file, può essere specificato con una [costante |#Formats]: ```php -$image->save('resampled.tmp', null, Image::JPEG); +$image->save('resampled.tmp', null, ImageType::JPEG); ``` L'immagine può essere scritta in una variabile invece che su disco: ```php -$data = $image->toString(Image::JPEG, 80); // JPEG, quality 80% +$data = $image->toString(ImageType::JPEG, 80); // JPEG, quality 80% ``` o inviare direttamente al browser con l'intestazione HTTP appropriata `Content-Type`: ```php // invia l'intestazione Content-Type: image/png -$image->send(Image::PNG); +$image->send(ImageType::PNG); +``` + + +Formati .[#toc-formats] +======================= + +I formati supportati sono JPEG, PNG, GIF, WebP, AVIF e BMP. Tuttavia, devono essere supportati anche dalla versione di PHP in uso, il che può essere verificato con la funzione [isTypeSupported() |#isTypeSupported()]. Le animazioni non sono supportate. + +I formati sono rappresentati dalle costanti `ImageType::JPEG`, `ImageType::PNG`, `ImageType::GIF`, `ImageType::WEBP`, `ImageType::AVIF` e `ImageType::BMP`. + +```php +$supported = Image::isTypeSupported(ImageType::JPEG); ``` +È necessario rilevare il formato di un'immagine al momento del caricamento? Il metodo lo restituisce nel secondo parametro: + +```php +$image = Image::fromFile('nette.jpg', $type); +``` + +Il rilevamento effettivo senza caricare l'immagine viene eseguito da `Image::detectTypeFromFile()`. + Ridimensionamento dell'immagine .[#toc-image-resize] ==================================================== @@ -226,12 +236,12 @@ Crea una nuova immagine a colori reali delle dimensioni indicate. Il colore pred static fromFile(string $file, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------- -Legge un'immagine da un file e ne restituisce il tipo in `$detectedFormat`. I tipi supportati sono `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` e `Image::BMP`. +Legge un'immagine da un file e ne restituisce il [tipo |#Formats] in `$detectedFormat`. static fromString(string $s, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------ -Legge un'immagine da una stringa e ne restituisce il tipo in `$detectedFormat`. I tipi supportati sono `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` e `Image::BMP`. +Legge un'immagine da una stringa e ne restituisce il [tipo |#Formats] in `$detectedFormat`. static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method] @@ -241,27 +251,32 @@ Crea un colore che può essere utilizzato in altri metodi, come `ellipse()`, `fi static typeToExtension(int $type): string .[method] --------------------------------------------------- -Restituisce l'estensione del file per la costante `Image::XXX` data. +Restituisce l'estensione del file per il [tipo |#Formats] dato. static typeToMimeType(int $type): string .[method] -------------------------------------------------- -Restituisce il tipo di mime per la costante `Image::XXX`. +Restituisce il tipo di mime per il [tipo |#Formats] dato. static extensionToType(string $extension): int .[method] -------------------------------------------------------- -Restituisce il tipo di immagine come costante `Image::XXX` in base all'estensione del file. +Restituisce il [tipo di |#Formats] immagine in base all'estensione del file. static detectTypeFromFile(string $file, int &$width=null, int &$height=null): ?int .[method] -------------------------------------------------------------------------------------------- -Restituisce il tipo di file immagine come costante `Image::XXX` e nei parametri `$width` e `$height` anche le sue dimensioni. +Restituisce il [tipo di |#Formats] file immagine e nei parametri `$width` e `$height` anche le sue dimensioni. static detectTypeFromString(string $s, int &$width=null, int &$height=null): ?int .[method] ------------------------------------------------------------------------------------------- -Restituisce il tipo di immagine dalla stringa come costante `Image::XXX` e nei parametri `$width` e `$height` anche le sue dimensioni. +Restituisce il [tipo |#Formats] di immagine dalla stringa e nei parametri `$width` e `$height` anche le sue dimensioni. + + +static isTypeSupported(int $type): bool .[method] +------------------------------------------------- +Determina se il [tipo di |#Formats] immagine dato è supportato. affine(array $affine, array $clip=null): Image .[method] @@ -586,7 +601,7 @@ save(string $file, int $quality=null, int $type=null): void .[method] --------------------------------------------------------------------- Salva un'immagine in un file. -La qualità di compressione è compresa nell'intervallo 0..100 per JPEG (valore predefinito 85), WEBP (valore predefinito 80) e AVIF (valore predefinito 30) e 0..9 per PNG (valore predefinito 9). Se il tipo non è evidente dall'estensione del file, è possibile specificarlo utilizzando una delle costanti `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, e `Image::BMP`. +La qualità di compressione è compresa nell'intervallo 0..100 per JPEG (valore predefinito 85), WEBP (valore predefinito 80) e AVIF (valore predefinito 30) e 0..9 per PNG (valore predefinito 9). Se il tipo non è evidente dall'estensione del file, è possibile specificarlo utilizzando una delle costanti `ImageType`. saveAlpha(bool $saveflag): void .[method] @@ -601,11 +616,11 @@ scale(int $newWidth, int $newHeight=-1, int $mode=IMG_BILINEAR_FIXED): Image .[m Ridimensiona un'immagine utilizzando l'algoritmo di interpolazione indicato. ([altro |https://www.php.net/manual/en/function.imagescale]) -send(int $type=Image::JPEG, int $quality=null): void .[method] --------------------------------------------------------------- +send(int $type=ImageType::JPEG, int $quality=null): void .[method] +------------------------------------------------------------------ Invia un'immagine al browser. -La qualità di compressione è compresa nell'intervallo 0..100 per JPEG (valore predefinito 85), WEBP (valore predefinito 80) e AVIF (valore predefinito 30) e 0..9 per PNG (valore predefinito 9). Il tipo è una delle costanti `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` e `Image::BMP`. +La qualità di compressione è compresa nell'intervallo 0..100 per JPEG (valore predefinito 85), WEBP (valore predefinito 80) e AVIF (valore predefinito 30) e 0..9 per PNG (valore predefinito 9). setBrush(Image $brush): void .[method] @@ -663,11 +678,11 @@ stringUp(int $font, int $x, int $y, string $s, int $col): void .[method] Disegna una stringa in verticale alle coordinate date. ([altro |https://www.php.net/manual/en/function.imagestringup]) -toString(int $type=Image::JPEG, int $quality=null): string .[method] --------------------------------------------------------------------- +toString(int $type=ImageType::JPEG, int $quality=null): string .[method] +------------------------------------------------------------------------ Emette un'immagine in stringa. -La qualità di compressione è compresa nell'intervallo 0..100 per JPEG (valore predefinito 85), WEBP (valore predefinito 80) e AVIF (valore predefinito 30) e 0..9 per PNG (valore predefinito 9). Il tipo è una delle costanti `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` e `Image::BMP`. +La qualità di compressione è compresa nell'intervallo 0..100 per JPEG (valore predefinito 85), WEBP (valore predefinito 80) e AVIF (valore predefinito 30) e 0..9 per PNG (valore predefinito 9). trueColorToPalette(bool $dither, int $ncolors): void .[method] diff --git a/utils/pl/images.texy b/utils/pl/images.texy index aff3da3f5d..419a9a011e 100644 --- a/utils/pl/images.texy +++ b/utils/pl/images.texy @@ -17,6 +17,7 @@ Wszystkie przykłady zakładają, że alias został utworzony: ```php use Nette\Utils\Image; +use Nette\Utils\ImageType; ``` @@ -41,17 +42,6 @@ Albo załadować obraz z pliku: $image = Image::fromFile('nette.jpg'); ``` -Obsługiwane formaty to JPEG, PNG, GIF, WebP, AVIF i BMP, ale twoja wersja PHP musi je również obsługiwać (sprawdź `phpinfo()`, sekcja GD). Animacje nie są obsługiwane. - -Czy musisz wykryć format obrazu podczas ładowania? Metoda zwraca go w drugim parametrze: - -```php -$image = Image::fromFile('nette.jpg', $type); -// $type to Image::JPEG, Image::PNG, Image::GIF, Image::WEBP, Image::AVIF lub Image::BMP -``` - -Tylko wykrywanie bez ładowania obrazu odbywa się przez `Image::detectTypeFromFile()`. - Zapisywanie obrazu .[#toc-save-the-image] ========================================= @@ -68,26 +58,46 @@ Możemy określić jakość kompresji w zakresie 0..100 dla JPEG (domyślnie 85) $image->save('resampled.jpg', 80); // JPEG, jakość 80% ``` -Jeśli format nie jest oczywisty na podstawie rozszerzenia pliku, może być określony przez jedną ze stałych `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, oraz `Image::BMP`: +Jeśli format nie jest oczywisty na podstawie rozszerzenia pliku, można go określić za pomocą [stałej |#Formats]: ```php -$image->save('resampled.tmp', null, Image::JPEG); +$image->save('resampled.tmp', null, ImageType::JPEG); ``` Obraz może być zapisany do zmiennej zamiast na dysk: ```php -$data = $image->toString(Image::JPEG, 80); // JPEG, qualita 80% +$data = $image->toString(ImageType::JPEG, 80); // JPEG, qualita 80% ``` lub wysyłane bezpośrednio do przeglądarki z odpowiednim nagłówkiem HTTP `Content-Type`: ```php // wysyła nagłówek Content-Type: image/png -$image->send(Image::PNG); +$image->send(ImageType::PNG); ``` +Formaty .[#toc-formats] +======================= + +Obsługiwane formaty to JPEG, PNG, GIF, WebP, AVIF i BMP. Muszą być one jednak również obsługiwane przez daną wersję PHP, co można zweryfikować za pomocą funkcji [isTypeSupported() |#isTypeSupported()]. Animacje nie są obsługiwane. + +Formaty są reprezentowane przez stałe `ImageType::JPEG`, `ImageType::PNG`, `ImageType::GIF`, `ImageType::WEBP`, `ImageType::AVIF` i `ImageType::BMP`. + +```php +$supported = Image::isTypeSupported(ImageType::JPEG); +``` + +Chcesz wykryć format obrazu podczas ładowania? Metoda zwraca go w drugim parametrze: + +```php +$image = Image::fromFile('nette.jpg', $type); +``` + +Rzeczywiste wykrywanie bez ładowania obrazu jest wykonywane przez `Image::detectTypeFromFile()`. + + Zmień rozmiar .[#toc-image-resize] ================================== @@ -226,12 +236,12 @@ Tworzy nowy obraz w kolorze rzeczywistym o podanych wymiarach. Domyślnym kolore static fromFile(string $file, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------- -Odczytuje obraz z pliku i zwraca jego typ w `$detectedFormat`. Obsługiwane typy to `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` oraz `Image::BMP`. +Odczytuje obraz z pliku i zwraca jego [typ |#Formats] w `$detectedFormat`. static fromString(string $s, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------ -Odczytuje obraz z łańcucha i zwraca jego typ w `$detectedFormat`. Obsługiwane typy to `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, oraz `Image::BMP`. +Odczytuje obraz z ciągu znaków i zwraca jego [typ |#Formats] w `$detectedFormat`. static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method] @@ -241,27 +251,32 @@ Tworzy kolor, który może być używany w innych metodach, takich jak `ellipse( static typeToExtension(int $type): string .[method] --------------------------------------------------- -Zwraca rozszerzenie pliku dla podanej stałej `Image::XXX`. +Zwraca rozszerzenie pliku dla podanego [typu |#Formats]. static typeToMimeType(int $type): string .[method] -------------------------------------------------- -Zwraca typ mime dla podanej stałej `Image::XXX`. +Zwraca typ mime dla podanego [typu |#Formats]. static extensionToType(string $extension): int .[method] -------------------------------------------------------- -Zwraca typ obrazu jako stałą `Image::XXX` zgodnie z rozszerzeniem pliku. +Zwraca [typ |#Formats] obrazu zgodnie z rozszerzeniem pliku. static detectTypeFromFile(string $file, int &$width=null, int &$height=null): ?int .[method] -------------------------------------------------------------------------------------------- -Zwraca typ obrazu jako stałą `Image::XXX`, a także jego wymiary w parametrach `$width` i `$height`. +Zwraca [typ |#Formats] pliku obrazu, a w parametrach `$width` i `$height` także jego wymiary. static detectTypeFromString(string $s, int &$width=null, int &$height=null): ?int .[method] ------------------------------------------------------------------------------------------- -Zwraca typ obrazu z ciągu jako stałą `Image::XXX` oraz jego wymiary w parametrach `$width` i `$height`. +Zwraca [typ |#Formats] obrazu z ciągu znaków, a w parametrach `$width` i `$height` również jego wymiary. + + +static isTypeSupported(int $type): bool .[method] +------------------------------------------------- +Określa, czy dany [typ |#Formats] obrazu jest obsługiwany. affine(array $affine, array $clip=null): Image .[method] @@ -586,7 +601,7 @@ save(string $file, int $quality=null, int $type=null): void .[method] --------------------------------------------------------------------- Zapisuje obraz do pliku. -Jakość kompresji jest w zakresie 0..100 dla JPEG (domyślnie 85), WEBP (domyślnie 80) i AVIF (domyślnie 30) oraz 0..9 dla PNG (domyślnie 9). Jeśli typ nie jest oczywisty na podstawie rozszerzenia pliku, można go określić za pomocą jednej ze stałych `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, oraz `Image::BMP`. +Jakość kompresji mieści się w zakresie 0..100 dla JPEG (domyślnie 85), WEBP (domyślnie 80) i AVIF (domyślnie 30) oraz 0..9 dla PNG (domyślnie 9). Jeśli typ nie jest oczywisty z rozszerzenia pliku, można go określić za pomocą jednej ze stałych `ImageType`. saveAlpha(bool $saveflag): void .[method] @@ -601,11 +616,11 @@ scale(int $newWidth, int $newHeight=-1, int $mode=IMG_BILINEAR_FIXED): Image .[m Skalowanie obrazu z wykorzystaniem podanego algorytmu interpolacji. ([więcej |https://www.php.net/manual/en/function.imagescale]) -send(int $type=Image::JPEG, int $quality=null): void .[method] --------------------------------------------------------------- +send(int $type=ImageType::JPEG, int $quality=null): void .[method] +------------------------------------------------------------------ Drukuje obraz do przeglądarki. -Jakość kompresji jest w zakresie 0..100 dla JPEG (domyślnie 85), WEBP (domyślnie 80) i AVIF (domyślnie 30) oraz 0..9 dla PNG (domyślnie 9). Typ jest jedną ze stałych `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` oraz `Image::BMP`. +Jakość kompresji mieści się w zakresie 0..100 dla JPEG (domyślnie 85), WEBP (domyślnie 80) i AVIF (domyślnie 30) oraz 0..9 dla PNG (domyślnie 9). setBrush(Image $brush): void .[method] @@ -663,11 +678,11 @@ stringUp(int $font, int $x, int $y, string $s, int $col): void .[method] Wypisuje ciąg znaków w pionie na podane współrzędne. ([więcej |https://www.php.net/manual/en/function.imagestringup]) -toString(int $type=Image::JPEG, int $quality=null): string .[method] --------------------------------------------------------------------- +toString(int $type=ImageType::JPEG, int $quality=null): string .[method] +------------------------------------------------------------------------ Zapisuje obraz w postaci ciągu znaków. -Jakość kompresji jest w zakresie 0..100 dla JPEG (domyślnie 85), WEBP (domyślnie 80) i AVIF (domyślnie 30) oraz 0..9 dla PNG (domyślnie 9). Typ jest jedną ze stałych `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` oraz `Image::BMP`. +Jakość kompresji mieści się w zakresie 0..100 dla JPEG (domyślnie 85), WEBP (domyślnie 80) i AVIF (domyślnie 30) oraz 0..9 dla PNG (domyślnie 9). trueColorToPalette(bool $dither, int $ncolors): void .[method] diff --git a/utils/pt/images.texy b/utils/pt/images.texy index fdf21d8eaa..9344efed84 100644 --- a/utils/pt/images.texy +++ b/utils/pt/images.texy @@ -17,6 +17,7 @@ Os exemplos a seguir assumem que a seguinte classe está definida: ```php use Nette\Utils\Image; +use Nette\Utils\ImageType; ``` @@ -41,17 +42,6 @@ Ou carregamos a imagem de um arquivo: $image = Image::fromFile('nette.jpg'); ``` -Os formatos suportados são JPEG, PNG, GIF, WebP, AVIF e BMP, mas sua versão do PHP também deve apoiá-los (verifique a `phpinfo()`, seção GD). As animações não são suportadas. - -Necessidade de detectar o formato da imagem ao carregar? O formato de retorno do método no segundo parâmetro: - -```php -$image = Image::fromFile('nette.jpg', $type); -// $type é Image::JPEG, Image::PNG, Image::GIF, Image::WEBP, Image::AVIF ou Image::BMP -``` - -Somente a detecção sem carregar a imagem é feita por `Image::detectTypeFromFile()`. - Salvar a imagem .[#toc-save-the-image] ====================================== @@ -68,26 +58,46 @@ Podemos especificar a qualidade de compressão na faixa 0..100 para JPEG (padrã $image->save('resampled.jpg', 80); // JPEG, qualidade 80% ``` -Se o formato não for óbvio pela extensão do arquivo, ele pode ser especificado por uma das constantes `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, e `Image::BMP`: +Se o formato não for óbvio a partir da extensão do arquivo, ele poderá ser especificado por uma [constante |#Formats]: ```php -$image->save('resampled.tmp', null, Image::JPEG); +$image->save('resampled.tmp', null, ImageType::JPEG); ``` A imagem pode ser escrita em uma variável ao invés de em disco: ```php -$data = $image->toString(Image::JPEG, 80); // JPEG, qualidade 80%. +$data = $image->toString(ImageType::JPEG, 80); // JPEG, qualidade 80%. ``` ou enviar diretamente para o navegador com o cabeçalho HTTP apropriado `Content-Type`: ```php // envia cabeçalho Content-Type: imagem/png -$image->send(Image::PNG); +$image->send(ImageType::PNG); ``` +Formatos .[#toc-formats] +======================== + +Os formatos suportados são JPEG, PNG, GIF, WebP, AVIF e BMP. No entanto, eles também devem ser compatíveis com sua versão do PHP, o que pode ser verificado usando a função [isTypeSupported() |#isTypeSupported()]. Não há suporte para animações. + +Os formatos são representados pelas constantes `ImageType::JPEG`, `ImageType::PNG`, `ImageType::GIF`, `ImageType::WEBP`, `ImageType::AVIF`, e `ImageType::BMP`. + +```php +$supported = Image::isTypeSupported(ImageType::JPEG); +``` + +Precisa detectar o formato de uma imagem ao ser carregada? O método o retorna no segundo parâmetro: + +```php +$image = Image::fromFile('nette.jpg', $type); +``` + +A detecção real sem carregar a imagem é realizada por `Image::detectTypeFromFile()`. + + Redimensionamento de imagem .[#toc-image-resize] ================================================ @@ -226,12 +236,12 @@ Cria uma nova imagem colorida verdadeira das dimensões dadas. A cor padrão é static fromFile(string $file, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------- -Lê uma imagem de um arquivo e retorna seu tipo em `$detectedFormat`. Os tipos suportados são `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` e `Image::BMP`. +Lê uma imagem de um arquivo e retorna seu [tipo |#Formats] em `$detectedFormat`. static fromString(string $s, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------ -Lê uma imagem de um fio e retorna seu tipo em `$detectedFormat`. Os tipos suportados são `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::AVIF`, `Image::WEBP`, , e `Image::BMP`. +Lê uma imagem de uma string e retorna seu [tipo |#Formats] em `$detectedFormat`. static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method] @@ -241,27 +251,32 @@ Cria uma cor que pode ser usada em outros métodos, tais como `ellipse()`, `fill static typeToExtension(int $type): string .[method] --------------------------------------------------- -Devolve a extensão do arquivo para a constante `Image::XXX` dada. +Retorna a extensão do arquivo para o [tipo |#Formats] fornecido. static typeToMimeType(int $type): string .[method] -------------------------------------------------- -Devolve o tipo de mímica para a constante `Image::XXX` dada. +Retorna o tipo de mime para o [tipo |#Formats] fornecido. static extensionToType(string $extension): int .[method] -------------------------------------------------------- -Retorna o tipo de imagem como uma constante `Image::XXX` de acordo com a extensão do arquivo. +Retorna o [tipo |#Formats] de imagem de acordo com a extensão do arquivo. static detectTypeFromFile(string $file, int &$width=null, int &$height=null): ?int .[method] -------------------------------------------------------------------------------------------- -Retorna o tipo de arquivo de imagem como constante `Image::XXX` e nos parâmetros `$width` e `$height` também suas dimensões. +Retorna o [tipo |#Formats] de arquivo de imagem e, nos parâmetros `$width` e `$height`, também suas dimensões. static detectTypeFromString(string $s, int &$width=null, int &$height=null): ?int .[method] ------------------------------------------------------------------------------------------- -Retorna o tipo de imagem de corda como constante `Image::XXX` e nos parâmetros `$width` e `$height` também suas dimensões. +Retorna o [tipo |#Formats] de imagem da string e, nos parâmetros `$width` e `$height`, também suas dimensões. + + +static isTypeSupported(int $type): bool .[method] +------------------------------------------------- +Determina se o [tipo |#Formats] de imagem fornecido é compatível. affine(array $affine, array $clip=null): Image .[method] @@ -586,7 +601,7 @@ save(string $file, int $quality=null, int $type=null): void .[method] --------------------------------------------------------------------- Salva uma imagem em um arquivo. -A qualidade da compressão está na faixa 0..100 para JPEG (padrão 85), WEBP (padrão 80) e AVIF (padrão 30) e 0..9 para PNG (padrão 9). Se o tipo não for óbvio a partir da extensão do arquivo, você pode especificá-lo usando uma das constantes `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, e `Image::BMP`. +A qualidade da compactação está no intervalo de 0 a 100 para JPEG (padrão 85), WEBP (padrão 80) e AVIF (padrão 30) e 0 a 9 para PNG (padrão 9). Se o tipo não for óbvio a partir da extensão do arquivo, você poderá especificá-lo usando uma das constantes do site `ImageType`. saveAlpha(bool $saveflag): void .[method] @@ -601,11 +616,11 @@ scale(int $newWidth, int $newHeight=-1, int $mode=IMG_BILINEAR_FIXED): Image .[m Escala uma imagem usando o algoritmo de interpolação dado. ([mais |https://www.php.net/manual/en/function.imagescale]) -send(int $type=Image::JPEG, int $quality=null): void .[method] --------------------------------------------------------------- +send(int $type=ImageType::JPEG, int $quality=null): void .[method] +------------------------------------------------------------------ Produz uma imagem para o navegador. -A qualidade da compressão está na faixa 0..100 para JPEG (padrão 85), WEBP (padrão 80) e AVIF (padrão 30) e 0..9 para PNG (padrão 9). O tipo é uma das constantes `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::AVIF`, `Image::WEBP`, e `Image::BMP`. +A qualidade da compactação está no intervalo de 0 a 100 para JPEG (padrão 85), WEBP (padrão 80) e AVIF (padrão 30) e 0 a 9 para PNG (padrão 9). setBrush(Image $brush): void .[method] @@ -663,11 +678,11 @@ stringUp(int $font, int $x, int $y, string $s, int $col): void .[method] Traça um cordel verticalmente nas coordenadas dadas. ([mais |https://www.php.net/manual/en/function.imagestringup]) -toString(int $type=Image::JPEG, int $quality=null): string .[method] --------------------------------------------------------------------- +toString(int $type=ImageType::JPEG, int $quality=null): string .[method] +------------------------------------------------------------------------ Produz uma imagem a fio. -A qualidade da compressão está na faixa 0..100 para JPEG (padrão 85), WEBP (padrão 80) e AVIF (padrão 30) e 0..9 para PNG (padrão 9). O tipo é uma das constantes `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::AVIF`, `Image::WEBP`, e `Image::BMP`. +A qualidade da compactação está no intervalo de 0 a 100 para JPEG (padrão 85), WEBP (padrão 80) e AVIF (padrão 30) e 0 a 9 para PNG (padrão 9). trueColorToPalette(bool $dither, int $ncolors): void .[method] diff --git a/utils/ro/images.texy b/utils/ro/images.texy index 996e346bc6..7098656312 100644 --- a/utils/ro/images.texy +++ b/utils/ro/images.texy @@ -17,6 +17,7 @@ Următoarele exemple presupun că este definit următorul alias de clasă: ```php use Nette\Utils\Image; +use Nette\Utils\ImageType; ``` @@ -41,17 +42,6 @@ Sau încărcăm imaginea dintr-un fișier: $image = Image::fromFile('nette.jpg'); ``` -Formatele acceptate sunt JPEG, PNG, GIF, WebP, AVIF și BMP, dar versiunea dvs. de PHP trebuie să le accepte și ea (consultați `phpinfo()`, secțiunea GD). Animațiile nu sunt acceptate. - -Trebuie să detectați formatul imaginii la încărcare? Metoda returnează formatul în cel de-al doilea parametru: - -```php -$image = Image::fromFile('nette.jpg', $type); -// $type este Image::JPEG, Image::PNG, Image::GIF, Image::WEBP, Image::AVIF sau Image::BMP -``` - -Doar detecția fără încărcarea imaginii este realizată de `Image::detectTypeFromFile()`. - Salvați imaginea .[#toc-save-the-image] ======================================= @@ -68,25 +58,45 @@ Putem specifica calitatea compresiei în intervalul 0..100 pentru JPEG (implicit $image->save('resampled.jpg', 80); // JPEG, calitate 80% ``` -În cazul în care formatul nu este evident din extensia fișierului, acesta poate fi specificat prin una dintre constantele `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, și `Image::BMP`: +În cazul în care formatul nu este evident din extensia fișierului, acesta poate fi specificat prin [constantă |#Formats]: ```php -$image->save('resampled.tmp', null, Image::JPEG); +$image->save('resampled.tmp', null, ImageType::JPEG); ``` Imaginea poate fi scrisă într-o variabilă în loc de pe disc: ```php -$data = $image->toString(Image::JPEG, 80); // JPEG, calitate 80% +$data = $image->toString(ImageType::JPEG, 80); // JPEG, calitate 80% ``` sau trimiteți direct la browser cu antetul HTTP corespunzător `Content-Type`: ```php // trimite antet Content-Type: image/png -$image->send(Image::PNG); +$image->send(ImageType::PNG); +``` + + +Formate .[#toc-formats] +======================= + +Formatele acceptate sunt JPEG, PNG, GIF, WebP, AVIF și BMP. Cu toate acestea, ele trebuie să fie acceptate și de versiunea dumneavoastră de PHP, ceea ce poate fi verificat cu ajutorul funcției [isTypeSupported() |#isTypeSupported()]. Animațiile nu sunt acceptate. + +Formatele sunt reprezentate de constantele `ImageType::JPEG`, `ImageType::PNG`, `ImageType::GIF`, `ImageType::WEBP`, `ImageType::AVIF`, și `ImageType::BMP`. + +```php +$supported = Image::isTypeSupported(ImageType::JPEG); ``` +Aveți nevoie să detectați formatul unei imagini la încărcare? Metoda îl returnează în cel de-al doilea parametru: + +```php +$image = Image::fromFile('nette.jpg', $type); +``` + +Detectarea efectivă fără a încărca imaginea este realizată de `Image::detectTypeFromFile()`. + Redimensionarea imaginii .[#toc-image-resize] ============================================= @@ -226,12 +236,12 @@ Creează o nouă imagine în culori reale cu dimensiunile date. Culoarea implici static fromFile(string $file, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------- -Citește o imagine dintr-un fișier și returnează tipul acesteia în `$detectedFormat`. Tipurile acceptate sunt `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` și `Image::BMP`. +Citește o imagine dintr-un fișier și returnează [tipul |#Formats] acesteia în `$detectedFormat`. static fromString(string $s, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------ -Citește o imagine dintr-un șir de caractere și returnează tipul acesteia în `$detectedFormat`. Tipurile acceptate sunt `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, și `Image::BMP`. +Citește o imagine dintr-un șir de caractere și returnează [tipul |#Formats] acesteia în `$detectedFormat`. static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method] @@ -241,27 +251,32 @@ Creează o culoare care poate fi utilizată în alte metode, cum ar fi `ellipse( static typeToExtension(int $type): string .[method] --------------------------------------------------- -Returnează extensia de fișier pentru constanta `Image::XXX` dată. +Returnează extensia de fișier pentru [tipul |#Formats] dat. static typeToMimeType(int $type): string .[method] -------------------------------------------------- -Returnează tipul mime pentru constanta `Image::XXX` dată. +Returnează tipul mime pentru [tipul |#Formats] dat. static extensionToType(string $extension): int .[method] -------------------------------------------------------- -Returnează tipul de imagine ca o constantă `Image::XXX` în funcție de extensia fișierului. +Returnează [tipul de |#Formats] imagine în funcție de extensia fișierului. static detectTypeFromFile(string $file, int &$width=null, int &$height=null): ?int .[method] -------------------------------------------------------------------------------------------- -Returnează tipul de fișier de imagine ca și constantă `Image::XXX`, iar în parametrii `$width` și `$height` și dimensiunile sale. +Returnează [tipul |#Formats] de fișier imagine și, în parametrii `$width` și `$height`, și dimensiunile acestuia. static detectTypeFromString(string $s, int &$width=null, int &$height=null): ?int .[method] ------------------------------------------------------------------------------------------- -Returnează tipul de imagine din șirul de caractere ca și constanta `Image::XXX`, iar în parametrii `$width` și `$height` și dimensiunile acesteia. +Returnează [tipul |#Formats] de imagine din șirul de caractere, iar în parametrii `$width` și `$height` și dimensiunile acesteia. + + +static isTypeSupported(int $type): bool .[method] +------------------------------------------------- +Determină dacă [tipul de |#Formats] imagine dat este acceptat. affine(array $affine, array $clip=null): Image .[method] @@ -586,7 +601,7 @@ save(string $file, int $quality=null, int $type=null): void .[method] --------------------------------------------------------------------- Salvează o imagine într-un fișier. -Calitatea compresiei este cuprinsă în intervalul 0...100 pentru JPEG (implicit 85), WEBP (implicit 80) și AVIF (implicit 30) și 0...9 pentru PNG (implicit 9). În cazul în care tipul nu este evident din extensia fișierului, îl puteți specifica folosind una dintre constantele `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF`, și `Image::BMP`. +Calitatea compresiei este cuprinsă în intervalul 0...100 pentru JPEG (implicit 85), WEBP (implicit 80) și AVIF (implicit 30) și 0...9 pentru PNG (implicit 9). În cazul în care tipul nu este evident din extensia fișierului, îl puteți specifica folosind una dintre constantele `ImageType`. saveAlpha(bool $saveflag): void .[method] @@ -601,11 +616,11 @@ scale(int $newWidth, int $newHeight=-1, int $mode=IMG_BILINEAR_FIXED): Image .[m Redimensionează o imagine folosind algoritmul de interpolare dat. ([mai mult |https://www.php.net/manual/en/function.imagescale]) -send(int $type=Image::JPEG, int $quality=null): void .[method] --------------------------------------------------------------- +send(int $type=ImageType::JPEG, int $quality=null): void .[method] +------------------------------------------------------------------ Trimite o imagine în browser. -Calitatea compresiei este cuprinsă în intervalul 0...100 pentru JPEG (implicit 85), WEBP (implicit 80) și AVIF (implicit 30) și 0...9 pentru PNG (implicit 9). Tipul este una dintre constantele `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` și `Image::BMP`. +Calitatea compresiei este cuprinsă în intervalul 0...100 pentru JPEG (implicit 85), WEBP (implicit 80) și AVIF (implicit 30) și 0...9 pentru PNG (implicit 9). setBrush(Image $brush): void .[method] @@ -663,11 +678,11 @@ stringUp(int $font, int $x, int $y, string $s, int $col): void .[method] Desenează un șir pe verticală la coordonatele date. ([mai mult |https://www.php.net/manual/en/function.imagestringup]) -toString(int $type=Image::JPEG, int $quality=null): string .[method] --------------------------------------------------------------------- +toString(int $type=ImageType::JPEG, int $quality=null): string .[method] +------------------------------------------------------------------------ Produce o imagine în șir de caractere. -Calitatea compresiei este cuprinsă în intervalul 0...100 pentru JPEG (implicit 85), WEBP (implicit 80) și AVIF (implicit 30) și 0...9 pentru PNG (implicit 9). Tipul este una dintre constantele `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` și `Image::BMP`. +Calitatea compresiei este cuprinsă în intervalul 0...100 pentru JPEG (implicit 85), WEBP (implicit 80) și AVIF (implicit 30) și 0...9 pentru PNG (implicit 9). trueColorToPalette(bool $dither, int $ncolors): void .[method] diff --git a/utils/ru/images.texy b/utils/ru/images.texy index e7c5cba4c3..fb7e92e7de 100644 --- a/utils/ru/images.texy +++ b/utils/ru/images.texy @@ -17,6 +17,7 @@ composer require nette/utils ```php use Nette\Utils\Image; +use Nette\Utils\ImageType; ``` @@ -41,17 +42,6 @@ $image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0)); $image = Image::fromFile('nette.jpg'); ``` -Поддерживаются форматы JPEG, PNG, GIF, WebP, AVIF и BMP, но ваша версия PHP также должна их поддерживать (проверьте `phpinfo()`, раздел GD). Анимация не поддерживается. - -Нужно ли определять формат изображения при загрузке? Метод возвращает его во втором параметре: - -```php -$image = Image::fromFile('nette.jpg', $type); -// $type - Image::JPEG, Image::PNG, Image::GIF, Image::WEBP, Image::AVIF или Image::BMP -``` - -Только обнаружение без загрузки изображения выполняется `Image::detectTypeFromFile()`. - Сохранение изображения .[#toc-save-the-image] ============================================= @@ -68,25 +58,45 @@ $image->save('resampled.jpg'); $image->save('resampled.jpg', 80); // JPEG, 80% качества ``` -Если формат не очевиден из расширения файла, он может быть указан одной из констант `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` и `Image::BMP`: +Если формат не очевиден из расширения файла, он может быть задан [константой |#Formats]: ```php -$image->save('resampled.tmp', null, Image::JPEG); +$image->save('resampled.tmp', null, ImageType::JPEG); ``` Изображение может быть записано не на диск, а в переменную: ```php -$data = $image->toString(Image::JPEG, 80); // JPEG, 80% качества +$data = $image->toString(ImageType::JPEG, 80); // JPEG, 80% качества ``` или отправляется непосредственно в браузер с соответствующим HTTP-заголовком `Content-Type`: ```php // отправляет заголовок Content-Type: image/png -$image->send(Image::PNG); +$image->send(ImageType::PNG); +``` + + +Форматы .[#toc-formats] +======================= + +Поддерживаются следующие форматы: JPEG, PNG, GIF, WebP, AVIF и BMP. Однако они также должны поддерживаться вашей версией PHP, что можно проверить с помощью функции [isTypeSupported() |#isTypeSupported()]. Анимация не поддерживается. + +Форматы представлены константами `ImageType::JPEG`, `ImageType::PNG`, `ImageType::GIF`, `ImageType::WEBP`, `ImageType::AVIF` и `ImageType::BMP`. + +```php +$supported = Image::isTypeSupported(ImageType::JPEG); ``` +Нужно определить формат изображения при загрузке? Метод возвращает его во втором параметре: + +```php +$image = Image::fromFile('nette.jpg', $type); +``` + +Фактическое определение без загрузки изображения выполняется с помощью `Image::detectTypeFromFile()`. + Изменить размер .[#toc-image-resize] ==================================== @@ -226,12 +236,12 @@ static fromBlank(int $width, int $height, array $color=null): Image .[method] static fromFile(string $file, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------- -Считывает изображение из файла и возвращает его тип в формате `$detectedFormat`. Поддерживаются следующие типы: `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` и `Image::BMP`. +Считывает изображение из файла и возвращает его [тип |#Formats] в формате `$detectedFormat`. static fromString(string $s, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------ -Считывает изображение из строки и возвращает его тип в формате `$detectedFormat`. Поддерживаются следующие типы: `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` и `Image::BMP`. +Считывает изображение из строки и возвращает его [тип |#Formats] в формате `$detectedFormat`. static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method] @@ -241,27 +251,32 @@ static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method static typeToExtension(int $type): string .[method] --------------------------------------------------- -Возвращает расширение файла для заданной константы `Image::XXX`. +Возвращает расширение файла для заданного [типа |#Formats]. static typeToMimeType(int $type): string .[method] -------------------------------------------------- -Возвращает тип mime для заданной константы `Image::XXX`. +Возвращает тип mime для заданного [типа |#Formats]. static extensionToType(string $extension): int .[method] -------------------------------------------------------- -Возвращает тип изображения в виде константы `Image::XXX` в соответствии с расширением файла. +Возвращает [тип |#Formats] изображения в соответствии с расширением файла. static detectTypeFromFile(string $file, int &$width=null, int &$height=null): ?int .[method] -------------------------------------------------------------------------------------------- -Возвращает тип изображения в виде константы `Image::XXX`, а также его размеры в параметрах `$width` и `$height`. +Возвращает [тип |#Formats] файла изображения, а в параметрах `$width` и `$height` также его размеры. static detectTypeFromString(string $s, int &$width=null, int &$height=null): ?int .[method] ------------------------------------------------------------------------------------------- -Возвращает тип изображения из строки в виде константы `Image::XXX` и его размеры в параметрах `$width` и `$height`. +Возвращает [тип |#Formats] изображения из строки, а в параметрах `$width` и `$height` также его размеры. + + +static isTypeSupported(int $type): bool .[method] +------------------------------------------------- +Определяет, поддерживается ли заданный [тип |#Formats] изображения. affine(array $affine, array $clip=null): Image .[method] @@ -586,7 +601,7 @@ save(string $file, int $quality=null, int $type=null): void .[method] --------------------------------------------------------------------- Сохраняет изображение в файл. -Качество сжатия находится в диапазоне 0...100 для JPEG (по умолчанию 85), WEBP (по умолчанию 80) и AVIF (по умолчанию 30) и 0...9 для PNG (по умолчанию 9). Если тип не очевиден из расширения файла, вы можете указать его с помощью одной из констант `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` и `Image::BMP`. +Качество сжатия находится в диапазоне 0...100 для JPEG (по умолчанию 85), WEBP (по умолчанию 80) и AVIF (по умолчанию 30) и 0...9 для PNG (по умолчанию 9). Если тип не очевиден из расширения файла, вы можете указать его с помощью одной из констант `ImageType`. saveAlpha(bool $saveflag): void .[method] @@ -601,11 +616,11 @@ scale(int $newWidth, int $newHeight=-1, int $mode=IMG_BILINEAR_FIXED): Image .[m Масштабирование изображения с использованием заданного алгоритма интерполяции. ([подробнее |https://www.php.net/manual/en/function.imagescale]) -send(int $type=Image::JPEG, int $quality=null): void .[method] --------------------------------------------------------------- +send(int $type=ImageType::JPEG, int $quality=null): void .[method] +------------------------------------------------------------------ Выводит изображение в браузер. -Качество сжатия находится в диапазоне 0...100 для JPEG (по умолчанию 85), WEBP (по умолчанию 80) и AVIF (по умолчанию 30) и 0...9 для PNG (по умолчанию 9). Тип - одна из констант `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` и `Image::BMP`. +Качество сжатия находится в диапазоне 0...100 для JPEG (по умолчанию 85), WEBP (по умолчанию 80) и AVIF (по умолчанию 30) и 0...9 для PNG (по умолчанию 9). setBrush(Image $brush): void .[method] @@ -663,11 +678,11 @@ stringUp(int $font, int $x, int $y, string $s, int $col): void .[method] Выводит строку по вертикали в заданных координатах. ([подробнее |https://www.php.net/manual/en/function.imagestringup]) -toString(int $type=Image::JPEG, int $quality=null): string .[method] --------------------------------------------------------------------- +toString(int $type=ImageType::JPEG, int $quality=null): string .[method] +------------------------------------------------------------------------ Сохраняет изображение в строке. -Качество сжатия находится в диапазоне 0...100 для JPEG (по умолчанию 85), WEBP (по умолчанию 80) и AVIF (по умолчанию 30) и 0...9 для PNG (по умолчанию 9). Тип - одна из констант `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` и `Image::BMP`. +Качество сжатия находится в диапазоне 0...100 для JPEG (по умолчанию 85), WEBP (по умолчанию 80) и AVIF (по умолчанию 30) и 0...9 для PNG (по умолчанию 9). trueColorToPalette(bool $dither, int $ncolors): void .[method] diff --git a/utils/sl/images.texy b/utils/sl/images.texy index 88c5d52f1f..79bed05a2f 100644 --- a/utils/sl/images.texy +++ b/utils/sl/images.texy @@ -17,6 +17,7 @@ Naslednji primeri predpostavljajo, da je definiran naslednji vzdevek razreda: ```php use Nette\Utils\Image; +use Nette\Utils\ImageType; ``` @@ -41,17 +42,6 @@ Sliko lahko naložimo iz datoteke: $image = Image::fromFile('nette.jpg'); ``` -Podprti formati so JPEG, PNG, GIF, WebP, AVIF in BMP, vendar jih mora podpirati tudi vaša različica PHP (preverite `phpinfo()`, oddelek GD). Animacije niso podprte. - -Potrebujete zaznati format slike pri nalaganju? Metoda vrne format v drugem parametru: - -```php -$image = Image::fromFile('nette.jpg', $type); -// $type je Image::JPEG, Image::PNG, Image::GIF, Image::WEBP, Image::AVIF ali Image::BMP -``` - -Samo zaznavanje brez nalaganja slike se izvede s spletno stranjo `Image::detectTypeFromFile()`. - Shranjevanje slike .[#toc-save-the-image] ========================================= @@ -68,25 +58,45 @@ Določimo lahko kakovost stiskanja v območju 0..100 za JPEG (privzeto 85), WEBP $image->save('resampled.jpg', 80); // JPEG, kakovost 80% ``` -Če format ni razviden iz končnice datoteke, ga lahko določite z eno od konstant `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` in `Image::BMP`: +Če format ni razviden iz končnice datoteke, ga lahko določite s [konstanto |#Formats]: ```php -$image->save('resampled.tmp', null, Image::JPEG); +$image->save('resampled.tmp', null, ImageType::JPEG); ``` Sliko lahko namesto na disk zapišete v spremenljivko: ```php -$data = $image->toString(Image::JPEG, 80); // JPEG, kakovost 80% +$data = $image->toString(ImageType::JPEG, 80); // JPEG, kakovost 80% ``` ali pošljete neposredno brskalniku z ustreznim glavo HTTP `Content-Type`: ```php // pošilja glavo Content-Type: image/png -$image->send(Image::PNG); +$image->send(ImageType::PNG); +``` + + +Formati .[#toc-formats] +======================= + +Podprti formati so JPEG, PNG, GIF, WebP, AVIF in BMP. Vendar jih mora podpirati tudi vaša različica PHP, kar lahko preverite s funkcijo [isTypeSupported() |#isTypeSupported()]. Animacije niso podprte. + +Formati so predstavljeni s konstantami `ImageType::JPEG`, `ImageType::PNG`, `ImageType::GIF`, `ImageType::WEBP`, `ImageType::AVIF` in `ImageType::BMP`. + +```php +$supported = Image::isTypeSupported(ImageType::JPEG); ``` +Potrebujete zaznati format slike ob nalaganju? Metoda ga vrne v drugem parametru: + +```php +$image = Image::fromFile('nette.jpg', $type); +``` + +Dejansko zaznavanje brez nalaganja slike izvede `Image::detectTypeFromFile()`. + Spreminjanje velikosti slike .[#toc-image-resize] ================================================= @@ -226,12 +236,12 @@ Ustvari novo pravo barvno sliko danih dimenzij. Privzeta barva je črna. static fromFile(string $file, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------- -Prebere sliko iz datoteke in vrne njeno vrsto v `$detectedFormat`. Podprte vrste so `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` in `Image::BMP`. +Prebere sliko iz datoteke in vrne njeno [vrsto |#Formats] v `$detectedFormat`. static fromString(string $s, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------ -Preberi sliko iz niza in vrne njeno vrsto v `$detectedFormat`. Podprte vrste so `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` in `Image::BMP`. +Preberi sliko iz niza in vrne njeno [vrsto |#Formats] v `$detectedFormat`. static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method] @@ -241,27 +251,32 @@ Ustvari barvo, ki jo lahko uporabite v drugih metodah, kot so `ellipse()`, `fill static typeToExtension(int $type): string .[method] --------------------------------------------------- -Vrne končnico datoteke za podano konstanto `Image::XXX`. +Vrne končnico datoteke za dano [vrsto |#Formats]. static typeToMimeType(int $type): string .[method] -------------------------------------------------- -Vrne vrsto mime za podano konstanto `Image::XXX`. +Vrne tip mime za dani [tip |#Formats]. static extensionToType(string $extension): int .[method] -------------------------------------------------------- -Vrne vrsto slike kot konstanto `Image::XXX` glede na končnico datoteke. +Vrne [vrsto |#Formats] slike glede na razširitev datoteke. static detectTypeFromFile(string $file, int &$width=null, int &$height=null): ?int .[method] -------------------------------------------------------------------------------------------- -Vrne vrsto slikovne datoteke kot konstanto `Image::XXX`, v parametrih `$width` in `$height` pa tudi njene dimenzije. +Vrne [vrsto |#Formats] slikovne datoteke in v parametrih `$width` in `$height` tudi njene dimenzije. static detectTypeFromString(string $s, int &$width=null, int &$height=null): ?int .[method] ------------------------------------------------------------------------------------------- -Vrne vrsto slike iz niza kot konstanto `Image::XXX`, v parametrih `$width` in `$height` pa tudi njene dimenzije. +Vrne [vrsto |#Formats] slike iz niza in v parametrih `$width` in `$height` tudi njene dimenzije. + + +static isTypeSupported(int $type): bool .[method] +------------------------------------------------- +Ugotovi, ali je dana [vrsta |#Formats] slike podprta. affine(array $affine, array $clip=null): Image .[method] @@ -586,7 +601,7 @@ save(string $file, int $quality=null, int $type=null): void .[method] --------------------------------------------------------------------- Sliko shrani v datoteko. -Kakovost stiskanja je v območju 0..100 za JPEG (privzeto 85), WEBP (privzeto 80) in AVIF (privzeto 30) ter 0..9 za PNG (privzeto 9). Če tip ni razviden iz končnice datoteke, ga lahko določite z eno od konstant `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` in `Image::BMP`. +Kakovost stiskanja je v območju 0..100 za JPEG (privzeto 85), WEBP (privzeto 80) in AVIF (privzeto 30) ter 0..9 za PNG (privzeto 9). Če vrsta ni razvidna iz končnice datoteke, jo lahko določite z eno od konstant `ImageType`. saveAlpha(bool $saveflag): void .[method] @@ -601,11 +616,11 @@ scale(int $newWidth, int $newHeight=-1, int $mode=IMG_BILINEAR_FIXED): Image .[m Skalira sliko z uporabo danega algoritma interpolacije. ([več |https://www.php.net/manual/en/function.imagescale]) -send(int $type=Image::JPEG, int $quality=null): void .[method] --------------------------------------------------------------- +send(int $type=ImageType::JPEG, int $quality=null): void .[method] +------------------------------------------------------------------ Izpiše sliko v brskalnik. -Kakovost stiskanja je v območju 0..100 za JPEG (privzeto 85), WEBP (privzeto 80) in AVIF (privzeto 30) ter 0..9 za PNG (privzeto 9). Tip je ena od konstant `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` in `Image::BMP`. +Kakovost stiskanja je v območju 0..100 za JPEG (privzeto 85), WEBP (privzeto 80) in AVIF (privzeto 30) ter 0..9 za PNG (privzeto 9). setBrush(Image $brush): void .[method] @@ -663,11 +678,11 @@ stringUp(int $font, int $x, int $y, string $s, int $col): void .[method] Vertikalno nariše niz na danih koordinatah. ([več |https://www.php.net/manual/en/function.imagestringup]) -toString(int $type=Image::JPEG, int $quality=null): string .[method] --------------------------------------------------------------------- +toString(int $type=ImageType::JPEG, int $quality=null): string .[method] +------------------------------------------------------------------------ Izpiše sliko v niz. -Kakovost stiskanja je v območju 0..100 za JPEG (privzeto 85), WEBP (privzeto 80) in AVIF (privzeto 30) ter 0..9 za PNG (privzeto 9). Tip je ena od konstant `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` in `Image::BMP`. +Kakovost stiskanja je v območju 0..100 za JPEG (privzeto 85), WEBP (privzeto 80) in AVIF (privzeto 30) ter 0..9 za PNG (privzeto 9). trueColorToPalette(bool $dither, int $ncolors): void .[method] diff --git a/utils/tr/images.texy b/utils/tr/images.texy index c041d8ec49..2e7c3b2ed0 100644 --- a/utils/tr/images.texy +++ b/utils/tr/images.texy @@ -17,6 +17,7 @@ Aşağıdaki örneklerde, aşağıdaki sınıf takma adının tanımlandığı v ```php use Nette\Utils\Image; +use Nette\Utils\ImageType; ``` @@ -41,17 +42,6 @@ Ya da görüntüyü bir dosyadan yükleriz: $image = Image::fromFile('nette.jpg'); ``` -Desteklenen formatlar JPEG, PNG, GIF, WebP, AVIF ve BMP'dir, ancak PHP sürümünüz de bunları desteklemelidir ( `phpinfo()`, GD bölümünü kontrol edin). Animasyonlar desteklenmez. - -Yükleme sırasında görüntü formatını tespit etmeniz mi gerekiyor? Yöntem, ikinci parametrede biçimi döndürür: - -```php -$image = Image::fromFile('nette.jpg', $type); -// $type Image::JPEG, Image::PNG, Image::GIF, Image::WEBP, Image::AVIF veya Image::BMP ise -``` - -Sadece görüntü yüklenmeden algılama `Image::detectTypeFromFile()` tarafından yapılır. - Görüntüyü Kaydet .[#toc-save-the-image] ======================================= @@ -68,25 +58,45 @@ Sıkıştırma kalitesini JPEG (varsayılan 85), WEBP (varsayılan 80) ve AVIF ( $image->save('resampled.jpg', 80); // JPEG, kalite %80 ``` -Format dosya uzantısından anlaşılmıyorsa, `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` ve `Image::BMP` sabitlerinden biriyle belirtilebilir: +Format dosya uzantısından anlaşılmıyorsa, [sabit |#Formats] ile belirtilebilir: ```php -$image->save('resampled.tmp', null, Image::JPEG); +$image->save('resampled.tmp', null, ImageType::JPEG); ``` Görüntü disk yerine bir değişkene yazılabilir: ```php -$data = $image->toString(Image::JPEG, 80); // JPEG, kalite %80. +$data = $image->toString(ImageType::JPEG, 80); // JPEG, kalite %80. ``` veya uygun HTTP başlığıyla doğrudan tarayıcıya gönderin `Content-Type`: ```php // başlık gönderir Content-Type: image/png -$image->send(Image::PNG); +$image->send(ImageType::PNG); +``` + + +Formatlar .[#toc-formats] +========================= + +Desteklenen biçimler JPEG, PNG, GIF, WebP, AVIF ve BMP'dir. Ancak, bunların PHP sürümünüz tarafından da destekleniyor olması gerekir; [isTypeSupported() |#isTypeSupported()] işlevi kullanılarak bu doğrulanabilir. Animasyonlar desteklenmez. + +Biçimler `ImageType::JPEG`, `ImageType::PNG`, `ImageType::GIF`, `ImageType::WEBP`, `ImageType::AVIF` ve `ImageType::BMP` sabitleri ile temsil edilir. + +```php +$supported = Image::isTypeSupported(ImageType::JPEG); ``` +Yükleme sırasında bir görüntünün formatını tespit etmeniz mi gerekiyor? Yöntem bunu ikinci parametrede döndürür: + +```php +$image = Image::fromFile('nette.jpg', $type); +``` + +Görüntü yüklenmeden gerçek algılama `Image::detectTypeFromFile()` tarafından gerçekleştirilir. + Görüntü Yeniden Boyutlandırma .[#toc-image-resize] ================================================== @@ -226,12 +236,12 @@ Verilen boyutlarda yeni bir gerçek renkli görüntü oluşturur. Varsayılan re static fromFile(string $file, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------- -Dosyadan bir görüntü okur ve türünü `$detectedFormat` olarak döndürür. Desteklenen türler `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` ve `Image::BMP`'dir. +Dosyadan bir görüntü okur ve [türünü |#Formats] `$detectedFormat` olarak döndürür. static fromString(string $s, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------ -Bir dizeden bir görüntü okur ve türünü `$detectedFormat` olarak döndürür. Desteklenen türler `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` ve `Image::BMP`'dir. +Bir dizeden bir görüntü okur ve [türünü |#Formats] `$detectedFormat` olarak döndürür. static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method] @@ -241,27 +251,32 @@ static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method static typeToExtension(int $type): string .[method] --------------------------------------------------- -Verilen `Image::XXX` sabiti için dosya uzantısını döndürür. +Verilen [tür |#Formats] için dosya uzantısını döndürür. static typeToMimeType(int $type): string .[method] -------------------------------------------------- -Verilen `Image::XXX` sabiti için mime türünü döndürür. +Verilen [tür |#Formats] için mime türünü döndürür. static extensionToType(string $extension): int .[method] -------------------------------------------------------- -Dosya uzantısına göre görüntü türünü sabit `Image::XXX` olarak döndürür. +Dosya uzantısına göre görüntü [türünü |#Formats] döndürür. static detectTypeFromFile(string $file, int &$width=null, int &$height=null): ?int .[method] -------------------------------------------------------------------------------------------- -Görüntü dosyasının türünü `Image::XXX` sabiti olarak ve `$width` ve `$height` parametrelerinde de boyutlarını döndürür. +Görüntü dosyasının [türünü |#Formats] ve `$width` ve `$height` parametrelerinde de boyutlarını döndürür. static detectTypeFromString(string $s, int &$width=null, int &$height=null): ?int .[method] ------------------------------------------------------------------------------------------- -Resmin türünü dizeden `Image::XXX` sabiti olarak ve `$width` ve `$height` parametrelerinde de boyutlarını döndürür. +Dizeden görüntünün [türünü |#Formats] ve `$width` ve `$height` parametrelerinden de boyutlarını döndürür. + + +static isTypeSupported(int $type): bool .[method] +------------------------------------------------- +Verilen görüntü [türünün |#Formats] desteklenip desteklenmediğini belirler. affine(array $affine, array $clip=null): Image .[method] @@ -586,7 +601,7 @@ save(string $file, int $quality=null, int $type=null): void .[method] --------------------------------------------------------------------- Bir görüntüyü bir dosyaya kaydeder. -Sıkıştırma kalitesi JPEG (varsayılan 85), WEBP (varsayılan 80) ve AVIF (varsayılan 30) için 0..100 ve PNG (varsayılan 9) için 0..9 aralığındadır. Dosya uzantısından tür belli değilse, `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` ve `Image::BMP` sabitlerinden birini kullanarak belirtebilirsiniz. +Sıkıştırma kalitesi JPEG (varsayılan 85), WEBP (varsayılan 80) ve AVIF (varsayılan 30) için 0..100 ve PNG (varsayılan 9) için 0..9 aralığındadır. Tür dosya uzantısından anlaşılmıyorsa, `ImageType` sabitlerinden birini kullanarak belirtebilirsiniz. saveAlpha(bool $saveflag): void .[method] @@ -601,11 +616,11 @@ scale(int $newWidth, int $newHeight=-1, int $mode=IMG_BILINEAR_FIXED): Image .[m Verilen enterpolasyon algoritmasını kullanarak bir görüntüyü ölçeklendirir. ([daha fazla |https://www.php.net/manual/en/function.imagescale]) -send(int $type=Image::JPEG, int $quality=null): void .[method] --------------------------------------------------------------- +send(int $type=ImageType::JPEG, int $quality=null): void .[method] +------------------------------------------------------------------ Tarayıcıya bir görüntü çıktısı verir. -Sıkıştırma kalitesi JPEG (varsayılan 85), WEBP (varsayılan 80) ve AVIF (varsayılan 30) için 0..100 ve PNG (varsayılan 9) için 0..9 aralığındadır. Tip `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` ve `Image::BMP` sabitlerinden biridir. +Sıkıştırma kalitesi JPEG (varsayılan 85), WEBP (varsayılan 80) ve AVIF (varsayılan 30) için 0..100 ve PNG (varsayılan 9) için 0..9 aralığındadır. setBrush(Image $brush): void .[method] @@ -663,11 +678,11 @@ stringUp(int $font, int $x, int $y, string $s, int $col): void .[method] Verilen koordinatlarda dikey olarak bir dize çizer. ([daha fazla |https://www.php.net/manual/en/function.imagestringup]) -toString(int $type=Image::JPEG, int $quality=null): string .[method] --------------------------------------------------------------------- +toString(int $type=ImageType::JPEG, int $quality=null): string .[method] +------------------------------------------------------------------------ Bir görüntüyü dizeye çıktı olarak verir. -Sıkıştırma kalitesi JPEG (varsayılan 85), WEBP (varsayılan 80) ve AVIF (varsayılan 30) için 0..100 ve PNG (varsayılan 9) için 0..9 aralığındadır. Tip `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` ve `Image::BMP` sabitlerinden biridir. +Sıkıştırma kalitesi JPEG (varsayılan 85), WEBP (varsayılan 80) ve AVIF (varsayılan 30) için 0..100 ve PNG (varsayılan 9) için 0..9 aralığındadır. trueColorToPalette(bool $dither, int $ncolors): void .[method] diff --git a/utils/uk/images.texy b/utils/uk/images.texy index 33392a2839..eb9439afac 100644 --- a/utils/uk/images.texy +++ b/utils/uk/images.texy @@ -17,6 +17,7 @@ composer require nette/utils ```php use Nette\Utils\Image; +use Nette\Utils\ImageType; ``` @@ -41,17 +42,6 @@ $image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0)); $image = Image::fromFile('nette.jpg'); ``` -Підтримуються формати JPEG, PNG, GIF, WebP, AVIF і BMP, але ваша версія PHP також повинна їх підтримувати (перевірте `phpinfo()`, розділ GD). Анімація не підтримується. - -Чи потрібно визначати формат зображення під час завантаження? Метод повертає його в другому параметрі: - -```php -$image = Image::fromFile('nette.jpg', $type); -// $type є Image::JPEG, Image::PNG, Image::GIF, Image::WEBP, Image::AVIF або Image::BMP -``` - -За допомогою `Image::detectTypeFromFile()` виконується лише детектування без завантаження зображення. - Збереження зображення .[#toc-save-the-image] ============================================ @@ -68,25 +58,45 @@ $image->save('resampled.jpg'); $image->save('resampled.jpg', 80); // JPEG, 80% якості ``` -Якщо формат не очевидний з розширення файлу, його можна вказати за допомогою однієї з констант `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` та `Image::BMP`: +Якщо формат не очевидний з розширення файлу, його можна вказати за допомогою [константи |#Formats]: ```php -$image->save('resampled.tmp', null, Image::JPEG); +$image->save('resampled.tmp', null, ImageType::JPEG); ``` Зображення може бути записано не на диск, а у змінну: ```php -$data = $image->toString(Image::JPEG, 80); // JPEG, 80% якості +$data = $image->toString(ImageType::JPEG, 80); // JPEG, 80% якості ``` або надсилається безпосередньо в браузер із відповідним HTTP-заголовком `Content-Type`: ```php // відправляє заголовок Content-Type: image/png -$image->send(Image::PNG); +$image->send(ImageType::PNG); +``` + + +Формати .[#toc-formats] +======================= + +Підтримуються формати JPEG, PNG, GIF, WebP, AVIF і BMP. Однак вони також повинні підтримуватися вашою версією PHP, що можна перевірити за допомогою функції [isTypeSupported( |#isTypeSupported()] ). Анімація не підтримується. + +Формати представлені константами `ImageType::JPEG`, `ImageType::PNG`, `ImageType::GIF`, `ImageType::WEBP`, `ImageType::AVIF` і `ImageType::BMP`. + +```php +$supported = Image::isTypeSupported(ImageType::JPEG); ``` +Потрібно визначити формат зображення при завантаженні? Метод повертає його у другому параметрі: + +```php +$image = Image::fromFile('nette.jpg', $type); +``` + +Власне визначення без завантаження зображення виконується за допомогою `Image::detectTypeFromFile()`. + Змінити розмір .[#toc-image-resize] =================================== @@ -226,12 +236,12 @@ static fromBlank(int $width, int $height, array $color=null): Image .[method] static fromFile(string $file, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------- -Читає зображення з файлу і повертає його тип у `$detectedFormat`. Підтримуються типи `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` і `Image::BMP`. +Читає зображення з файлу і повертає його [тип |#Formats] в `$detectedFormat`. static fromString(string $s, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------ -Читає зображення з рядка і повертає його тип у вигляді `$detectedFormat`. Підтримуються типи `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` та `Image::BMP`. +Читає зображення з рядка і повертає його [тип |#Formats] в `$detectedFormat`. static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method] @@ -241,27 +251,32 @@ static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method static typeToExtension(int $type): string .[method] --------------------------------------------------- -Повертає розширення файлу для заданої константи `Image::XXX`. +Повертає розширення файлу для заданого [типу |#Formats]. static typeToMimeType(int $type): string .[method] -------------------------------------------------- -Повертає тип mime для заданої константи `Image::XXX`. +Повертає тип mime для заданого [типу |#Formats]. static extensionToType(string $extension): int .[method] -------------------------------------------------------- -Повертає тип зображення у вигляді константи `Image::XXX` відповідно до розширення файлу. +Повертає [тип |#Formats] зображення відповідно до розширення файлу. static detectTypeFromFile(string $file, int &$width=null, int &$height=null): ?int .[method] -------------------------------------------------------------------------------------------- -Повертає тип зображення у вигляді константи `Image::XXX`, а також його розміри в параметрах `$width` і `$height`. +Повертає [тип |#Formats] файлу зображення, а в параметрах `$width` та `$height` також його розміри. static detectTypeFromString(string $s, int &$width=null, int &$height=null): ?int .[method] ------------------------------------------------------------------------------------------- -Повертає тип зображення з рядка у вигляді константи `Image::XXX` і його розміри в параметрах `$width` і `$height`. +Повертає [тип |#Formats] зображення з рядка, а в параметрах `$width` та `$height` також його розміри. + + +static isTypeSupported(int $type): bool .[method] +------------------------------------------------- +Визначає, чи підтримується даний [тип |#Formats] зображення. affine(array $affine, array $clip=null): Image .[method] @@ -586,7 +601,7 @@ save(string $file, int $quality=null, int $type=null): void .[method] --------------------------------------------------------------------- Зберігає зображення у файл. -Якість стиснення знаходиться в діапазоні 0...100 для JPEG (за замовчуванням 85), WEBP (за замовчуванням 80) і AVIF (за замовчуванням 30) та 0...9 для PNG (за замовчуванням 9). Якщо тип не очевидний з розширення файлу, ви можете вказати його за допомогою однієї з констант `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` та `Image::BMP`. +Якість стиснення знаходиться в діапазоні 0...100 для JPEG (за замовчуванням 85), WEBP (за замовчуванням 80) і AVIF (за замовчуванням 30) та 0...9 для PNG (за замовчуванням 9). Якщо тип не очевидний з розширення файлу, ви можете вказати його за допомогою однієї з констант `ImageType`. saveAlpha(bool $saveflag): void .[method] @@ -601,11 +616,11 @@ scale(int $newWidth, int $newHeight=-1, int $mode=IMG_BILINEAR_FIXED): Image .[m Масштабування зображення з використанням заданого алгоритму інтерполяції. ([докладніше |https://www.php.net/manual/en/function.imagescale]) -send(int $type=Image::JPEG, int $quality=null): void .[method] --------------------------------------------------------------- +send(int $type=ImageType::JPEG, int $quality=null): void .[method] +------------------------------------------------------------------ Виводить зображення в браузер. -Якість стиснення знаходиться в діапазоні 0...100 для JPEG (за замовчуванням 85), WEBP (за замовчуванням 80) і AVIF (за замовчуванням 30) та 0...9 для PNG (за замовчуванням 9). Тип - одна з констант `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` та `Image::BMP`. +Якість стиснення знаходиться в діапазоні 0...100 для JPEG (за замовчуванням 85), WEBP (за замовчуванням 80) і AVIF (за замовчуванням 30) та 0...9 для PNG (за замовчуванням 9). setBrush(Image $brush): void .[method] @@ -663,11 +678,11 @@ stringUp(int $font, int $x, int $y, string $s, int $col): void .[method] Виводить рядок по вертикалі в заданих координатах. ([докладніше |https://www.php.net/manual/en/function.imagestringup]) -toString(int $type=Image::JPEG, int $quality=null): string .[method] --------------------------------------------------------------------- +toString(int $type=ImageType::JPEG, int $quality=null): string .[method] +------------------------------------------------------------------------ Зберігає зображення в рядку. -Якість стиснення знаходиться в діапазоні 0...100 для JPEG (за замовчуванням 85), WEBP (за замовчуванням 80) і AVIF (за замовчуванням 30) та 0...9 для PNG (за замовчуванням 9). Тип - одна з констант `Image::JPEG`, `Image::PNG`, `Image::GIF`, `Image::WEBP`, `Image::AVIF` та `Image::BMP`. +Якість стиснення знаходиться в діапазоні 0...100 для JPEG (за замовчуванням 85), WEBP (за замовчуванням 80) і AVIF (за замовчуванням 30) та 0...9 для PNG (за замовчуванням 9). trueColorToPalette(bool $dither, int $ncolors): void .[method] From 93ff78abecec07d5f9fc19191dbad2af7dddac92 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 19 Sep 2023 13:55:48 +0200 Subject: [PATCH 007/137] nette/utils 4.0.2 --- utils/bg/filesystem.texy | 26 +++++++++++++++++++++++++- utils/bg/finder.texy | 2 ++ utils/cs/filesystem.texy | 26 +++++++++++++++++++++++++- utils/cs/finder.texy | 2 ++ utils/de/filesystem.texy | 26 +++++++++++++++++++++++++- utils/de/finder.texy | 2 ++ utils/el/filesystem.texy | 26 +++++++++++++++++++++++++- utils/el/finder.texy | 2 ++ utils/en/filesystem.texy | 26 +++++++++++++++++++++++++- utils/en/finder.texy | 2 ++ utils/es/filesystem.texy | 26 +++++++++++++++++++++++++- utils/es/finder.texy | 2 ++ utils/fr/filesystem.texy | 26 +++++++++++++++++++++++++- utils/fr/finder.texy | 2 ++ utils/hu/filesystem.texy | 26 +++++++++++++++++++++++++- utils/hu/finder.texy | 2 ++ utils/it/filesystem.texy | 26 +++++++++++++++++++++++++- utils/it/finder.texy | 2 ++ utils/pl/filesystem.texy | 26 +++++++++++++++++++++++++- utils/pl/finder.texy | 2 ++ utils/pt/filesystem.texy | 26 +++++++++++++++++++++++++- utils/pt/finder.texy | 2 ++ utils/ro/filesystem.texy | 26 +++++++++++++++++++++++++- utils/ro/finder.texy | 2 ++ utils/ru/filesystem.texy | 26 +++++++++++++++++++++++++- utils/ru/finder.texy | 2 ++ utils/sl/filesystem.texy | 26 +++++++++++++++++++++++++- utils/sl/finder.texy | 2 ++ utils/tr/filesystem.texy | 26 +++++++++++++++++++++++++- utils/tr/finder.texy | 2 ++ utils/uk/filesystem.texy | 26 +++++++++++++++++++++++++- utils/uk/finder.texy | 2 ++ 32 files changed, 432 insertions(+), 16 deletions(-) diff --git a/utils/bg/filesystem.texy b/utils/bg/filesystem.texy index 46b25a925e..e4950c69f1 100644 --- a/utils/bg/filesystem.texy +++ b/utils/bg/filesystem.texy @@ -2,7 +2,7 @@ **************************** .[perex] -[api:Nette\Utils\FileSystem] е статичен клас, който съдържа полезни функции за работа с файлова система. Едно от предимствата им пред нативните функции на PHP е, че те хвърлят изключения в случай на грешки. +[api:Nette\Utils\FileSystem] е клас, който съдържа полезни функции за работа с файлова система. Едно от предимствата им пред нативните функции на PHP е, че те хвърлят изключения в случай на грешки. Ако трябва да търсите файлове на диска, използвайте [Finder |finder]. @@ -176,3 +176,27 @@ platformSlashes(string $path): string .[method] ```php $path = FileSystem::platformSlashes($path); ``` + + +Статичен срещу нестатичен подход .[#toc-static-vs-non-static-approach] +====================================================================== + +За да замените лесно класа `FileSystem` с друг клас, например за целите на тестването, използвайте го нестатично: + +```php +class AnyClassUsingFileSystem +{ + public function __construct( + private FileSystem $fileSystem, + ) { + } + + + public function readConfig(): string + { + return $this->fileSystem->read(/* ... */); + } + + ... +} +``` diff --git a/utils/bg/finder.texy b/utils/bg/finder.texy index b7d2b8f193..267cd5a7ea 100644 --- a/utils/bg/finder.texy +++ b/utils/bg/finder.texy @@ -61,6 +61,8 @@ Finder::findDirectories('vendor') // всички директории Можете да използвате [заместващи символи |#wildcards] `*`, `**`, `?` and `[...]` в маската. Можете дори да посочите директории, например `src/*.php` ще търси всички PHP файлове в директорията `src`. +Симлинковете също се считат за директории или файлове. + Къде да търсим? .[#toc-where-to-search] --------------------------------------- diff --git a/utils/cs/filesystem.texy b/utils/cs/filesystem.texy index 169820d712..3ceacacb4e 100644 --- a/utils/cs/filesystem.texy +++ b/utils/cs/filesystem.texy @@ -2,7 +2,7 @@ Souborový systém **************** .[perex] -[api:Nette\Utils\FileSystem] je statická třída s užitečnými funkcemi pro práci se souborovým systémem. Jednou z výhod oproti nativním PHP funkcím je, že v případě chyby vyhazují výjimky. +[api:Nette\Utils\FileSystem] je třída s užitečnými funkcemi pro práci se souborovým systémem. Jednou z výhod oproti nativním PHP funkcím je, že v případě chyby vyhazují výjimky. Pokud potřebujete hledat soubory na disku, použijte [Finder|finder]. @@ -176,3 +176,27 @@ Převede lomítka na znaky specifické pro aktuální platformu, tj. `\` ve Wind ```php $path = FileSystem::platformSlashes($path); ``` + + +Statický vs nestatický přístup +============================== + +Abyste kupříkladu pro účely testování mohli třídu snadno nahradit jinou (mockem), používejte ji nestaticky: + +```php +class AnyClassUsingFileSystem +{ + public function __construct( + private FileSystem $fileSystem, + ) { + } + + + public function readConfig(): string + { + return $this->fileSystem->read(/* ... */); + } + + ... +} +``` diff --git a/utils/cs/finder.texy b/utils/cs/finder.texy index b7748df578..1a4bbe3327 100644 --- a/utils/cs/finder.texy +++ b/utils/cs/finder.texy @@ -61,6 +61,8 @@ Alternativou statických metod je vytvoření instance pomocí `new Finder` (tak V masce můžete používat [zástupné znaky|#Zástupné znaky] `*`, `**`, `?` a `[...]`. Dokonce můžete specifikovat i v adresáře, například `src/*.php` vyhledá všechny PHP soubory v adresáři `src`. +Symlinky jsou také považovány za adresáře nebo soubory. + Kde se má hledat? ----------------- diff --git a/utils/de/filesystem.texy b/utils/de/filesystem.texy index 73fb5d0b5c..94f3eaef39 100644 --- a/utils/de/filesystem.texy +++ b/utils/de/filesystem.texy @@ -2,7 +2,7 @@ Dateisystem-Funktionen ********************** .[perex] -[api:Nette\Utils\FileSystem] ist eine statische Klasse, die nützliche Funktionen für die Arbeit mit einem Dateisystem enthält. Ein Vorteil gegenüber nativen PHP-Funktionen ist, dass sie im Fehlerfall Ausnahmen auslösen. +[api:Nette\Utils\FileSystem] ist eine Klasse, die nützliche Funktionen für die Arbeit mit einem Dateisystem enthält. Ein Vorteil gegenüber nativen PHP-Funktionen ist, dass sie im Fehlerfall Ausnahmen auslösen. Wenn Sie nach Dateien auf dem Datenträger suchen müssen, verwenden Sie den [Finder |finder]. @@ -176,3 +176,27 @@ Konvertiert Schrägstriche in Zeichen, die für die aktuelle Plattform spezifisc ```php $path = FileSystem::platformSlashes($path); ``` + + +Statischer vs. nicht-statischer Ansatz .[#toc-static-vs-non-static-approach] +============================================================================ + +Um die Klasse `FileSystem` einfach durch eine andere Klasse zu ersetzen, z. B. zu Testzwecken, verwenden Sie sie nicht-statisch: + +```php +class AnyClassUsingFileSystem +{ + public function __construct( + private FileSystem $fileSystem, + ) { + } + + + public function readConfig(): string + { + return $this->fileSystem->read(/* ... */); + } + + ... +} +``` diff --git a/utils/de/finder.texy b/utils/de/finder.texy index 0964f17a52..5970de6800 100644 --- a/utils/de/finder.texy +++ b/utils/de/finder.texy @@ -61,6 +61,8 @@ Eine Alternative zu statischen Methoden besteht darin, mit `new Finder` eine Ins Sie können [Wildcards |#wildcards] `*`, `**` verwenden, `?` and `[...]` in der Maske verwenden. Sie können sogar Verzeichnisse angeben, z. B. `src/*.php` sucht nach allen PHP-Dateien im Verzeichnis `src`. +Symlinks werden auch als Verzeichnisse oder Dateien betrachtet. + Wo soll gesucht werden? .[#toc-where-to-search] ----------------------------------------------- diff --git a/utils/el/filesystem.texy b/utils/el/filesystem.texy index fa9d16d7cf..1a0317bbb3 100644 --- a/utils/el/filesystem.texy +++ b/utils/el/filesystem.texy @@ -2,7 +2,7 @@ ****************************** .[perex] -[api:Nette\Utils\FileSystem] είναι μια στατική κλάση, η οποία περιέχει χρήσιμες συναρτήσεις για την εργασία με ένα σύστημα αρχείων. Ένα πλεονέκτημα σε σχέση με τις εγγενείς συναρτήσεις της PHP είναι ότι πετάνε εξαιρέσεις σε περίπτωση σφαλμάτων. +[api:Nette\Utils\FileSystem] είναι μια κλάση, η οποία περιέχει χρήσιμες λειτουργίες για την εργασία με ένα σύστημα αρχείων. Ένα πλεονέκτημα σε σχέση με τις εγγενείς συναρτήσεις της PHP είναι ότι σε περίπτωση σφαλμάτων πετάνε εξαιρέσεις. Αν θέλετε να αναζητήσετε αρχεία στο δίσκο, χρησιμοποιήστε το [Finder |finder]. @@ -176,3 +176,27 @@ platformSlashes(string $path): string .[method] ```php $path = FileSystem::platformSlashes($path); ``` + + +Στατική έναντι μη στατικής προσέγγισης .[#toc-static-vs-non-static-approach] +============================================================================ + +Για να αντικαταστήσετε εύκολα την κλάση `FileSystem` με μια άλλη κλάση, για παράδειγμα για σκοπούς δοκιμών, χρησιμοποιήστε τη μη στατική: + +```php +class AnyClassUsingFileSystem +{ + public function __construct( + private FileSystem $fileSystem, + ) { + } + + + public function readConfig(): string + { + return $this->fileSystem->read(/* ... */); + } + + ... +} +``` diff --git a/utils/el/finder.texy b/utils/el/finder.texy index fc541178a9..8c554fbd45 100644 --- a/utils/el/finder.texy +++ b/utils/el/finder.texy @@ -61,6 +61,8 @@ Finder::findDirectories('vendor') // όλοι οι κατάλογοι Μπορείτε να χρησιμοποιήσετε [μπαλαντέρ |#wildcards] `*`, `**`, `?` and `[...]` στη μάσκα. Μπορείτε ακόμη και να καθορίσετε σε καταλόγους, για παράδειγμα, το `src/*.php` θα αναζητήσει όλα τα αρχεία PHP στον κατάλογο `src`. +Οι συμβολικοί σύνδεσμοι θεωρούνται επίσης κατάλογοι ή αρχεία. + Πού να ψάξετε; .[#toc-where-to-search] -------------------------------------- diff --git a/utils/en/filesystem.texy b/utils/en/filesystem.texy index 995e03310c..522039c28e 100644 --- a/utils/en/filesystem.texy +++ b/utils/en/filesystem.texy @@ -2,7 +2,7 @@ Filesystem Functions ******************** .[perex] -[api:Nette\Utils\FileSystem] is a static class, which contains useful functions for working with a filesystem. One advantage over native PHP functions is that they throw exceptions in case of errors. +[api:Nette\Utils\FileSystem] is a class, which contains useful functions for working with a filesystem. One advantage over native PHP functions is that they throw exceptions in case of errors. If you need to search for files on the disk, use the [Finder |finder]. @@ -176,3 +176,27 @@ Converts slashes to characters specific to the current platform, i.e. `\` on Win ```php $path = FileSystem::platformSlashes($path); ``` + + +Static vs Non-static Approach +============================= + +To easily replace the `FileSystem` class with another class for example for testing purposes, use it non-statically: + +```php +class AnyClassUsingFileSystem +{ + public function __construct( + private FileSystem $fileSystem, + ) { + } + + + public function readConfig(): string + { + return $this->fileSystem->read(/* ... */); + } + + ... +} +``` diff --git a/utils/en/finder.texy b/utils/en/finder.texy index f9117246db..d10d88243a 100644 --- a/utils/en/finder.texy +++ b/utils/en/finder.texy @@ -61,6 +61,8 @@ An alternative to static methods is to create an instance using `new Finder` (th You can use [#wildcards] `*`, `**`, `?` and `[...]` in the mask. You can even specify in directories, for example `src/*.php` will search for all PHP files in the `src` directory. +Symlinks are also considered directories or files. + Where to Search? ---------------- diff --git a/utils/es/filesystem.texy b/utils/es/filesystem.texy index c7827c8fb4..dc546ee9a5 100644 --- a/utils/es/filesystem.texy +++ b/utils/es/filesystem.texy @@ -2,7 +2,7 @@ Funciones del sistema de archivos ********************************* .[perex] -[api:Nette\Utils\FileSystem] es una clase estática, que contiene funciones útiles para trabajar con un sistema de archivos. Una ventaja sobre las funciones nativas de PHP es que lanzan excepciones en caso de errores. +[api:Nette\Utils\FileSystem] es una clase que contiene funciones útiles para trabajar con un sistema de archivos. Una ventaja sobre las funciones nativas de PHP es que lanzan excepciones en caso de errores. Si necesitas buscar archivos en el disco, utiliza el [Finder |finder]. @@ -176,3 +176,27 @@ Convierte las barras inclinadas en caracteres específicos de la plataforma actu ```php $path = FileSystem::platformSlashes($path); ``` + + +Enfoque estático frente a no estático .[#toc-static-vs-non-static-approach] +=========================================================================== + +Para reemplazar fácilmente la clase `FileSystem` por otra clase, por ejemplo para realizar pruebas, utilícela de forma no estática: + +```php +class AnyClassUsingFileSystem +{ + public function __construct( + private FileSystem $fileSystem, + ) { + } + + + public function readConfig(): string + { + return $this->fileSystem->read(/* ... */); + } + + ... +} +``` diff --git a/utils/es/finder.texy b/utils/es/finder.texy index 04afe3c631..88d9e64cdb 100644 --- a/utils/es/finder.texy +++ b/utils/es/finder.texy @@ -61,6 +61,8 @@ Una alternativa a los métodos estáticos es crear una instancia utilizando `new Puede utilizar [comodines |#wildcards] `*`, `**`, `?` and `[...]` en la máscara. Incluso puede especificar en directorios, por ejemplo `src/*.php` buscará todos los archivos PHP en el directorio `src`. +Los enlaces simbólicos también se consideran directorios o archivos. + ¿Dónde buscar? .[#toc-where-to-search] -------------------------------------- diff --git a/utils/fr/filesystem.texy b/utils/fr/filesystem.texy index 649b9ab4f5..9eebde9692 100644 --- a/utils/fr/filesystem.texy +++ b/utils/fr/filesystem.texy @@ -2,7 +2,7 @@ Fonctions du système de fichiers ******************************** .[perex] -[api:Nette\Utils\FileSystem] est une classe statique, qui contient des fonctions utiles pour travailler avec un système de fichiers. Un avantage par rapport aux fonctions natives de PHP est qu'elles lèvent des exceptions en cas d'erreurs. +[api:Nette\Utils\FileSystem] est une classe qui contient des fonctions utiles pour travailler avec un système de fichiers. Un avantage par rapport aux fonctions natives de PHP est qu'elles lèvent des exceptions en cas d'erreur. Si vous devez rechercher des fichiers sur le disque, utilisez le [Finder |finder]. @@ -176,3 +176,27 @@ Convertit les barres obliques en caractères spécifiques à la plate-forme actu ```php $path = FileSystem::platformSlashes($path); ``` + + +Approche statique ou non statique .[#toc-static-vs-non-static-approach] +======================================================================= + +Pour remplacer facilement la classe `FileSystem` par une autre classe, par exemple à des fins de test, utilisez-la de manière non statique : + +```php +class AnyClassUsingFileSystem +{ + public function __construct( + private FileSystem $fileSystem, + ) { + } + + + public function readConfig(): string + { + return $this->fileSystem->read(/* ... */); + } + + ... +} +``` diff --git a/utils/fr/finder.texy b/utils/fr/finder.texy index c846adf89c..c4b7682126 100644 --- a/utils/fr/finder.texy +++ b/utils/fr/finder.texy @@ -61,6 +61,8 @@ Une alternative aux méthodes statiques est de créer une instance à l'aide de Vous pouvez utiliser des [caractères génériques |#wildcards] `*`, `**`, `?` and `[...]` dans le masque. Vous pouvez même spécifier des répertoires, par exemple `src/*.php` recherchera tous les fichiers PHP dans le répertoire `src`. +Les liens symboliques sont également considérés comme des répertoires ou des fichiers. + Où chercher ? .[#toc-where-to-search] ------------------------------------- diff --git a/utils/hu/filesystem.texy b/utils/hu/filesystem.texy index 6299e34529..37eaf4d0e7 100644 --- a/utils/hu/filesystem.texy +++ b/utils/hu/filesystem.texy @@ -2,7 +2,7 @@ Fájlrendszer funkciók ********************* .[perex] -[api:Nette\Utils\FileSystem] egy statikus osztály, amely hasznos függvényeket tartalmaz a fájlrendszerrel való munkához. Egyik előnye a natív PHP függvényekkel szemben, hogy hiba esetén kivételeket dobnak. +[api:Nette\Utils\FileSystem] egy osztály, amely hasznos funkciókat tartalmaz a fájlrendszerrel való munkához. Egyik előnye a natív PHP függvényekkel szemben, hogy hiba esetén kivételeket dobnak. Ha fájlokat kell keresnie a lemezen, használja a [Finder |finder] programot. @@ -176,3 +176,27 @@ A slashes karaktereket az aktuális platformra jellemző karakterekre konvertál ```php $path = FileSystem::platformSlashes($path); ``` + + +Statikus vs. nem statikus megközelítés .[#toc-static-vs-non-static-approach] +============================================================================ + +A `FileSystem` osztályt könnyen lecserélhetjük egy másik osztályra, például tesztelési célokra, ha nem-statikusan használjuk: + +```php +class AnyClassUsingFileSystem +{ + public function __construct( + private FileSystem $fileSystem, + ) { + } + + + public function readConfig(): string + { + return $this->fileSystem->read(/* ... */); + } + + ... +} +``` diff --git a/utils/hu/finder.texy b/utils/hu/finder.texy index 81131ce5a4..10cd3f3b02 100644 --- a/utils/hu/finder.texy +++ b/utils/hu/finder.texy @@ -61,6 +61,8 @@ A statikus módszerek alternatívája, hogy létrehozunk egy példányt a `new F Használhat [vadkártyákat |#wildcards] `*`, `**`, `?` and `[...]` a maszkban. Megadhat könyvtárakat is, például a `src/*.php` a `src` könyvtárban található összes PHP-fájlt megkeresi. +A szimbolikus hivatkozások szintén könyvtáraknak vagy fájloknak minősülnek. + Hol keressünk? .[#toc-where-to-search] -------------------------------------- diff --git a/utils/it/filesystem.texy b/utils/it/filesystem.texy index 183198d5df..9b8a981282 100644 --- a/utils/it/filesystem.texy +++ b/utils/it/filesystem.texy @@ -2,7 +2,7 @@ Funzioni del filesystem *********************** .[perex] -[api:Nette\Utils\FileSystem] è una classe statica che contiene funzioni utili per lavorare con il filesystem. Un vantaggio rispetto alle funzioni native di PHP è che lanciano eccezioni in caso di errori. +[api:Nette\Utils\FileSystem] è una classe che contiene funzioni utili per lavorare con il filesystem. Un vantaggio rispetto alle funzioni native di PHP è che lanciano eccezioni in caso di errori. Per cercare i file sul disco, utilizzare il [Finder |finder]. @@ -176,3 +176,27 @@ Converte gli slash in caratteri specifici della piattaforma corrente, ad esempio ```php $path = FileSystem::platformSlashes($path); ``` + + +Approccio statico e non statico .[#toc-static-vs-non-static-approach] +===================================================================== + +Per sostituire facilmente la classe `FileSystem` con un'altra classe, ad esempio a scopo di test, utilizzarla in modo non statico: + +```php +class AnyClassUsingFileSystem +{ + public function __construct( + private FileSystem $fileSystem, + ) { + } + + + public function readConfig(): string + { + return $this->fileSystem->read(/* ... */); + } + + ... +} +``` diff --git a/utils/it/finder.texy b/utils/it/finder.texy index fd44122a2a..e365191e57 100644 --- a/utils/it/finder.texy +++ b/utils/it/finder.texy @@ -61,6 +61,8 @@ Un'alternativa ai metodi statici è creare un'istanza con `new Finder` (l'oggett Si possono usare [i caratteri jolly |#wildcards] `*`, `**`, `?` and `[...]` nella maschera. Si possono anche specificare le directory, ad esempio `src/*.php` cercherà tutti i file PHP nella directory `src`. +Anche i collegamenti simbolici sono considerati directory o file. + Dove cercare? .[#toc-where-to-search] ------------------------------------- diff --git a/utils/pl/filesystem.texy b/utils/pl/filesystem.texy index 5980e40c18..0ccc81bcff 100644 --- a/utils/pl/filesystem.texy +++ b/utils/pl/filesystem.texy @@ -2,7 +2,7 @@ Funkcje systemu plików ********************** .[perex] -[api:Nette\Utils\FileSystem] jest statyczną klasą, która zawiera przydatne funkcje do pracy z systemem plików. Jedną z zalet w stosunku do natywnych funkcji PHP jest to, że w przypadku błędów rzucają one wyjątki. +[api:Nette\Utils\FileSystem] to klasa, która zawiera przydatne funkcje do pracy z systemem plików. Jedną z zalet w porównaniu z natywnymi funkcjami PHP jest to, że rzucają wyjątki w przypadku błędów. Jeśli chcesz wyszukać pliki na dysku, użyj [Finder |finder]. @@ -176,3 +176,27 @@ Konwertuje ukośniki na znaki specyficzne dla bieżącej platformy, tj. `\` w sy ```php $path = FileSystem::platformSlashes($path); ``` + + +Podejście statyczne i niestatyczne .[#toc-static-vs-non-static-approach] +======================================================================== + +Aby łatwo zastąpić klasę `FileSystem` inną klasą, na przykład do celów testowych, należy użyć jej w sposób niestatyczny: + +```php +class AnyClassUsingFileSystem +{ + public function __construct( + private FileSystem $fileSystem, + ) { + } + + + public function readConfig(): string + { + return $this->fileSystem->read(/* ... */); + } + + ... +} +``` diff --git a/utils/pl/finder.texy b/utils/pl/finder.texy index 4b2d449b2c..65cb8ea709 100644 --- a/utils/pl/finder.texy +++ b/utils/pl/finder.texy @@ -61,6 +61,8 @@ Alternatywą dla metod statycznych jest utworzenie instancji za pomocą `new Fin W masce można używać [znaków wieloznacznych |#Excluding] `*`, `**`, `?` a `[...]`. Możesz nawet określić w katalogach, na przykład `src/*.php` będzie szukać wszystkich plików PHP w katalogu `src`. +Symlinki są również uważane za katalogi lub pliki. + Gdzie szukać? .[#toc-kde-se-ma-hledat] -------------------------------------- diff --git a/utils/pt/filesystem.texy b/utils/pt/filesystem.texy index c869b35f84..2b3c6ef368 100644 --- a/utils/pt/filesystem.texy +++ b/utils/pt/filesystem.texy @@ -2,7 +2,7 @@ Funções do sistema de arquivos ****************************** .[perex] -[api:Nette\Utils\FileSystem] é uma classe estática, que contém funções úteis para trabalhar com um sistema de arquivos. Uma vantagem sobre as funções PHP nativas é que elas lançam exceções em caso de erros. +[api:Nette\Utils\FileSystem] é uma classe que contém funções úteis para trabalhar com um sistema de arquivos. Uma vantagem sobre as funções nativas do PHP é que elas lançam exceções em caso de erros. Se você precisar procurar arquivos no disco, use o [Finder |finder]. @@ -176,3 +176,27 @@ Converte cortes em caracteres específicos da plataforma atual, ou seja, `\` no ```php $path = FileSystem::platformSlashes($path); ``` + + +Abordagem estática versus não estática .[#toc-static-vs-non-static-approach] +============================================================================ + +Para substituir facilmente a classe `FileSystem` por outra classe, por exemplo, para fins de teste, use-a de forma não estática: + +```php +class AnyClassUsingFileSystem +{ + public function __construct( + private FileSystem $fileSystem, + ) { + } + + + public function readConfig(): string + { + return $this->fileSystem->read(/* ... */); + } + + ... +} +``` diff --git a/utils/pt/finder.texy b/utils/pt/finder.texy index 94e1cd48b0..0c8a31d15d 100644 --- a/utils/pt/finder.texy +++ b/utils/pt/finder.texy @@ -61,6 +61,8 @@ Uma alternativa aos métodos estáticos é criar uma instância usando `new Find Você pode usar [wildcards |#wildcards] `*`, `**`, `?` and `[...]` na máscara. Você pode até mesmo especificar em diretórios, por exemplo `src/*.php` procurará por todos os arquivos PHP no diretório `src`. +Os links simbólicos também são considerados diretórios ou arquivos. + Onde pesquisar? .[#toc-where-to-search] --------------------------------------- diff --git a/utils/ro/filesystem.texy b/utils/ro/filesystem.texy index ac3971da59..029969d120 100644 --- a/utils/ro/filesystem.texy +++ b/utils/ro/filesystem.texy @@ -2,7 +2,7 @@ Funcțiile sistemului de fișiere ******************************* .[perex] -[api:Nette\Utils\FileSystem] este o clasă statică, care conține funcții utile pentru lucrul cu un sistem de fișiere. Un avantaj față de funcțiile native PHP este că acestea aruncă excepții în caz de erori. +[api:Nette\Utils\FileSystem] este o clasă care conține funcții utile pentru lucrul cu un sistem de fișiere. Un avantaj față de funcțiile native PHP este că acestea aruncă excepții în caz de erori. Dacă trebuie să căutați fișiere pe disc, utilizați [Finder |finder]. @@ -176,3 +176,27 @@ Convertește slash-urile în caractere specifice platformei curente, de exemplu ```php $path = FileSystem::platformSlashes($path); ``` + + +Abordare statică vs. non-statică .[#toc-static-vs-non-static-approach] +====================================================================== + +Pentru a înlocui cu ușurință clasa `FileSystem` cu o altă clasă, de exemplu în scopuri de testare, utilizați-o în mod non-static: + +```php +class AnyClassUsingFileSystem +{ + public function __construct( + private FileSystem $fileSystem, + ) { + } + + + public function readConfig(): string + { + return $this->fileSystem->read(/* ... */); + } + + ... +} +``` diff --git a/utils/ro/finder.texy b/utils/ro/finder.texy index a2a2fafd0e..46799f331b 100644 --- a/utils/ro/finder.texy +++ b/utils/ro/finder.texy @@ -61,6 +61,8 @@ O alternativă la metodele statice este de a crea o instanță folosind `new Fin Puteți utiliza [caractere wildcards |#wildcards] `*`, `**`, `?` and `[...]` în mască. Puteți specifica chiar și în directoare, de exemplu `src/*.php` va căuta toate fișierele PHP din directorul `src`. +Legăturile simbolice sunt considerate, de asemenea, directoare sau fișiere. + Unde să căutați? .[#toc-where-to-search] ---------------------------------------- diff --git a/utils/ru/filesystem.texy b/utils/ru/filesystem.texy index edbc258074..39c217a040 100644 --- a/utils/ru/filesystem.texy +++ b/utils/ru/filesystem.texy @@ -2,7 +2,7 @@ **************** .[perex] -[api:Nette\Utils\FileSystem] это статический класс, содержащий полезные функции для работы с файловой системой. Одно из преимуществ перед собственными функциями PHP заключается в том, что они бросают исключения в случае ошибок. +[api:Nette\Utils\FileSystem] это класс, содержащий полезные функции для работы с файловой системой. Преимущество перед собственными функциями PHP заключается в том, что в случае ошибок они выбрасывают исключения. Если необходимо найти файлы на диске, используйте [Finder |finder]. @@ -176,3 +176,27 @@ platformSlashes(string $path): string .[method] ```php $path = FileSystem::platformSlashes($path); ``` + + +Статический и нестатический подход .[#toc-static-vs-non-static-approach] +======================================================================== + +Чтобы легко заменить класс `FileSystem` на другой класс, например, для тестирования, используйте нестатический подход: + +```php +class AnyClassUsingFileSystem +{ + public function __construct( + private FileSystem $fileSystem, + ) { + } + + + public function readConfig(): string + { + return $this->fileSystem->read(/* ... */); + } + + ... +} +``` diff --git a/utils/ru/finder.texy b/utils/ru/finder.texy index f873f51610..e749cd0e14 100644 --- a/utils/ru/finder.texy +++ b/utils/ru/finder.texy @@ -61,6 +61,8 @@ Finder::findDirectories('vendor') // все каталоги Вы можете использовать [подстановочные знаки |#wildcards] `*`, `**`, `?` and `[...]` в маске. Можно даже указывать в каталогах, например, `src/*.php` будет искать все файлы PHP в каталоге `src`. +Симлинки также считаются каталогами или файлами. + Где искать? .[#toc-where-to-search] ----------------------------------- diff --git a/utils/sl/filesystem.texy b/utils/sl/filesystem.texy index 69212925c7..4f2aea2f35 100644 --- a/utils/sl/filesystem.texy +++ b/utils/sl/filesystem.texy @@ -2,7 +2,7 @@ Funkcije datotečnega sistema **************************** .[perex] -[api:Nette\Utils\FileSystem] je statični razred, ki vsebuje uporabne funkcije za delo z datotečnim sistemom. Ena od prednosti v primerjavi z izvornimi funkcijami PHP je, da v primeru napak mečejo izjeme. +[api:Nette\Utils\FileSystem] je razred, ki vsebuje uporabne funkcije za delo z datotečnim sistemom. Prednost pred izvornimi funkcijami PHP je, da v primeru napak mečejo izjeme. Če želite poiskati datoteke na disku, uporabite [Finder |finder]. @@ -176,3 +176,27 @@ Pretvarja poševnice v znake, značilne za trenutno platformo, tj. `\` v sistemu ```php $path = FileSystem::platformSlashes($path); ``` + + +Statični in nestatični pristop .[#toc-static-vs-non-static-approach] +==================================================================== + +Če želite razred `FileSystem` preprosto zamenjati z drugim razredom, na primer za namene testiranja, ga uporabite nestatično: + +```php +class AnyClassUsingFileSystem +{ + public function __construct( + private FileSystem $fileSystem, + ) { + } + + + public function readConfig(): string + { + return $this->fileSystem->read(/* ... */); + } + + ... +} +``` diff --git a/utils/sl/finder.texy b/utils/sl/finder.texy index c548de7150..93c2c0e7f7 100644 --- a/utils/sl/finder.texy +++ b/utils/sl/finder.texy @@ -61,6 +61,8 @@ Alternativa statičnim metodam je, da ustvarite primerek z uporabo `new Finder` Uporabite lahko [nadomestne znake |#wildcards] `*`, `**`, `?` and `[...]` v maski. Navedete lahko celo imenike, na primer `src/*.php` bo poiskal vse datoteke PHP v imeniku `src`. +Za imenike ali datoteke se štejejo tudi simelne povezave. + Kje iskati? .[#toc-where-to-search] ----------------------------------- diff --git a/utils/tr/filesystem.texy b/utils/tr/filesystem.texy index 96aa3f27ca..88aa5f6a37 100644 --- a/utils/tr/filesystem.texy +++ b/utils/tr/filesystem.texy @@ -2,7 +2,7 @@ Dosya Sistemi İşlevleri *********************** .[perex] -[api:Nette\Utils\FileSystem] bir dosya sistemi ile çalışmak için yararlı işlevler içeren duruk bir sınıftır. Yerel PHP işlevlerine göre bir avantajı, hata durumunda istisnalar atmasıdır. +[api:Nette\Utils\FileSystem] bir dosya sistemi ile çalışmak için yararlı işlevler içeren bir sınıftır. Yerel PHP işlevlerine göre bir avantajı, hata durumunda istisnalar atmasıdır. Diskte dosya aramanız gerekiyorsa [Finder |finder]'ı kullanın. @@ -176,3 +176,27 @@ Eğik çizgileri geçerli platforma özgü karakterlere dönüştürür, yani Wi ```php $path = FileSystem::platformSlashes($path); ``` + + +Statik ve Statik Olmayan Yaklaşım .[#toc-static-vs-non-static-approach] +======================================================================= + +Örneğin test amacıyla `FileSystem` sınıfını başka bir sınıfla kolayca değiştirmek için, bunu statik olmayan bir şekilde kullanın: + +```php +class AnyClassUsingFileSystem +{ + public function __construct( + private FileSystem $fileSystem, + ) { + } + + + public function readConfig(): string + { + return $this->fileSystem->read(/* ... */); + } + + ... +} +``` diff --git a/utils/tr/finder.texy b/utils/tr/finder.texy index cd5045c6fb..993fa5c76d 100644 --- a/utils/tr/finder.texy +++ b/utils/tr/finder.texy @@ -61,6 +61,8 @@ Statik yöntemlere bir alternatif de `new Finder` adresini kullanarak bir örnek [Joker karakter |#wildcards] leri `*`, `**` adresinde kullanabilirsiniz, `?` and `[...]` maske içinde. Dizinleri bile belirtebilirsiniz, örneğin `src/*.php`, `src` dizinindeki tüm PHP dosyalarını arayacaktır. +Simbağlar da dizin veya dosya olarak kabul edilir. + Nerede Arama Yapmalı? .[#toc-where-to-search] --------------------------------------------- diff --git a/utils/uk/filesystem.texy b/utils/uk/filesystem.texy index 0f5a3f31a2..36f7ea9579 100644 --- a/utils/uk/filesystem.texy +++ b/utils/uk/filesystem.texy @@ -2,7 +2,7 @@ ************************ .[perex] -[api:Nette\Utils\FileSystem] це статичний клас, який містить корисні функції для роботи з файловою системою. Однією з переваг над нативними функціями PHP є те, що вони генерують виключення у випадку помилок. +[api:Nette\Utils\FileSystem] це клас, який містить корисні функції для роботи з файловою системою. Однією з переваг перед нативними функціями PHP є те, що вони генерують виключення у випадку помилок. Якщо вам потрібно знайти файли на диску, скористайтеся [Finder |finder]. @@ -176,3 +176,27 @@ platformSlashes(string $path): string .[method] ```php $path = FileSystem::platformSlashes($path); ``` + + +Статичний vs нестатичний підхід .[#toc-static-vs-non-static-approach] +===================================================================== + +Щоб легко замінити клас `FileSystem` іншим класом, наприклад, для тестування, використовуйте його нестатично: + +```php +class AnyClassUsingFileSystem +{ + public function __construct( + private FileSystem $fileSystem, + ) { + } + + + public function readConfig(): string + { + return $this->fileSystem->read(/* ... */); + } + + ... +} +``` diff --git a/utils/uk/finder.texy b/utils/uk/finder.texy index 7ed58e04f4..33cdeefa2f 100644 --- a/utils/uk/finder.texy +++ b/utils/uk/finder.texy @@ -61,6 +61,8 @@ Finder::findDirectories('vendor') // все каталоги Ви можете використовувати [підстановні знаки |#wildcards] `*`, `**`, `?` and `[...]` у масці. Можна навіть вказувати в каталогах, наприклад, `src/*.php` буде шукати всі файли PHP в каталозі `src`. +Симпосилання також вважаються каталогами або файлами. + Де шукати? .[#toc-where-to-search] ---------------------------------- From 4fcabd84f614b845756093d4618d2bfee8f50743 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 19 Sep 2023 17:35:36 +0200 Subject: [PATCH 008/137] latte: info about Latte\Runtime\Html --- latte/bg/extending-latte.texy | 12 +++++++++++- latte/cs/extending-latte.texy | 12 +++++++++++- latte/de/extending-latte.texy | 12 +++++++++++- latte/el/extending-latte.texy | 12 +++++++++++- latte/en/extending-latte.texy | 12 +++++++++++- latte/es/extending-latte.texy | 12 +++++++++++- latte/fr/extending-latte.texy | 12 +++++++++++- latte/hu/extending-latte.texy | 12 +++++++++++- latte/it/extending-latte.texy | 12 +++++++++++- latte/ja/extending-latte.texy | 12 +++++++++++- latte/pl/extending-latte.texy | 12 +++++++++++- latte/pt/extending-latte.texy | 12 +++++++++++- latte/ro/extending-latte.texy | 12 +++++++++++- latte/ru/extending-latte.texy | 12 +++++++++++- latte/sl/extending-latte.texy | 12 +++++++++++- latte/tr/extending-latte.texy | 12 +++++++++++- latte/uk/extending-latte.texy | 12 +++++++++++- 17 files changed, 187 insertions(+), 17 deletions(-) diff --git a/latte/bg/extending-latte.texy b/latte/bg/extending-latte.texy index d156b9e5bb..12bbe4f051 100644 --- a/latte/bg/extending-latte.texy +++ b/latte/bg/extending-latte.texy @@ -68,6 +68,16 @@ $latte->addFilter('shortify', fn(string $s, int $len = 10) => mb_substr($s, 0, $ Разбира се, функцията, представляваща филтъра, може да приема произволен брой параметри, като се поддържат и променливи параметри. +Ако филтърът връща низ в HTML, можете да го маркирате така, че Latte да не го ескапира автоматично (и следователно двойно). По този начин се избягва необходимостта от задаване на `|noescape` в шаблона. +Най-лесният начин е да обвиете низа в обект `Latte\Runtime\Html`, а другият начин е [Контекстни филтри |#Contextual Filters]. + +```php +$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("$amount EUR")); +``` + +.[note] +В този случай филтърът трябва да осигури правилно извеждане на данните. + Филтри, които използват класа .[#toc-filters-using-the-class] ------------------------------------------------------------- @@ -150,7 +160,7 @@ $latte->addFilter('money', function (FilterInfo $info, float $amount): string { // променете типа на съдържанието на HTML $info->contentType = ContentType::Html; - return "$num Kč"; + return "$amount EUR"; }); ``` diff --git a/latte/cs/extending-latte.texy b/latte/cs/extending-latte.texy index ad40b23768..15442df8e8 100644 --- a/latte/cs/extending-latte.texy +++ b/latte/cs/extending-latte.texy @@ -68,6 +68,16 @@ Jak vidíte, funkce obdrží levou stranu filtru před pipe `|` jako první argu Funkce představující filtr může samozřejmě přijímat libovolný počet parametrů, podporovány jsou i variadic parametry. +Pokud filtr vrací řetězec v HTML, můžete jej označit tak, aby jej Latte automaticky (a tedy dvojitě) neescapovalo. Vyhnete se tak potřebě uvádět v šabloně `|noescape`. +Nejjednodušší cestou je řetězec zabalit do objektu `Latte\Runtime\Html`, druhou cestu představují [Kontextové filtry|#Kontextové filtry]. + +```php +$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("$amount Kč")); +``` + +.[note] +Filtr musí v takovém případě zajistit správné escapování dat. + Filtry pomocí třídy ------------------- @@ -150,7 +160,7 @@ $latte->addFilter('money', function (FilterInfo $info, float $amount): string { // změníme content-type na HTML $info->contentType = ContentType::Html; - return "$num Kč"; + return "$amount Kč"; }); ``` diff --git a/latte/de/extending-latte.texy b/latte/de/extending-latte.texy index ea40c60918..3c2e5a6872 100644 --- a/latte/de/extending-latte.texy +++ b/latte/de/extending-latte.texy @@ -68,6 +68,16 @@ Wie Sie sehen können, erhält die Funktion die linke Seite des Filters vor der Natürlich kann die Funktion, die den Filter darstellt, eine beliebige Anzahl von Parametern annehmen, und auch variable Parameter werden unterstützt. +Wenn der Filter eine Zeichenkette in HTML zurückgibt, können Sie diese so markieren, dass Latte sie nicht automatisch (und damit doppelt) umbricht. Dadurch wird vermieden, dass Sie `|noescape` in der Vorlage angeben müssen. +Am einfachsten ist es, die Zeichenkette in ein `Latte\Runtime\Html` Objekt zu verpacken, die andere Möglichkeit sind [kontextuelle Filter |#Contextual Filters]. + +```php +$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("$amount EUR")); +``` + +.[note] +In diesem Fall muss der Filter das korrekte Escaping der Daten sicherstellen. + Filter, die die Klasse .[#toc-filters-using-the-class] ------------------------------------------------------ @@ -150,7 +160,7 @@ $latte->addFilter('money', function (FilterInfo $info, float $amount): string { // Inhaltstyp in HTML ändern $info->contentType = ContentType::Html; - return "$num Kč"; + return "$amount EUR"; }); ``` diff --git a/latte/el/extending-latte.texy b/latte/el/extending-latte.texy index 8a663c4b09..e6170a3abe 100644 --- a/latte/el/extending-latte.texy +++ b/latte/el/extending-latte.texy @@ -68,6 +68,16 @@ $latte->addFilter('shortify', fn(string $s, int $len = 10) => mb_substr($s, 0, $ Φυσικά, η συνάρτηση που αναπαριστά το φίλτρο μπορεί να δεχτεί οποιονδήποτε αριθμό παραμέτρων, ενώ υποστηρίζονται και μεταβλητές παράμετροι. +Αν το φίλτρο επιστρέφει ένα αλφαριθμητικό σε HTML, μπορείτε να το επισημάνετε έτσι ώστε το Latte να μην το αποφεύγει αυτόματα (και επομένως διπλά). Με αυτόν τον τρόπο αποφεύγεται η ανάγκη προσδιορισμού του `|noescape` στο πρότυπο. +Ο ευκολότερος τρόπος είναι να τυλίξετε τη συμβολοσειρά σε ένα αντικείμενο `Latte\Runtime\Html`, ο άλλος τρόπος είναι τα [φίλτρα πλαισίου |#Contextual Filters]. + +```php +$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("$amount EUR")); +``` + +.[note] +Στην περίπτωση αυτή, το φίλτρο πρέπει να διασφαλίζει τη σωστή διαφυγή των δεδομένων. + Φίλτρα που χρησιμοποιούν την κλάση .[#toc-filters-using-the-class] ------------------------------------------------------------------ @@ -150,7 +160,7 @@ $latte->addFilter('money', function (FilterInfo $info, float $amount): string { // αλλάζουμε τον τύπο περιεχομένου σε HTML $info->contentType = ContentType::Html; - return "$num Kč"; + return "$amount EUR"; }); ``` diff --git a/latte/en/extending-latte.texy b/latte/en/extending-latte.texy index 0e4178955a..0e5726200d 100644 --- a/latte/en/extending-latte.texy +++ b/latte/en/extending-latte.texy @@ -68,6 +68,16 @@ As you can see, the function receives the left side of the filter before the pip Of course, the function representing the filter can accept any number of parameters, and variadic parameters are also supported. +If the filter returns a string in HTML, you can mark it so that Latte does not automatically (and therefore double) escaping it. This avoids the need to specify `|noescape` in the template. +The easiest way is to wrap the string in a `Latte\Runtime\Html` object, the other way is [Contextual Filters|#Contextual Filters]. + +```php +$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("$amount EUR")); +``` + +.[note] +In this case, the filter must ensure correct escaping of the data. + Filters Using the Class ----------------------- @@ -150,7 +160,7 @@ $latte->addFilter('money', function (FilterInfo $info, float $amount): string { // change content-type to HTML $info->contentType = ContentType::Html; - return "$num Kč"; + return "$amount EUR"; }); ``` diff --git a/latte/es/extending-latte.texy b/latte/es/extending-latte.texy index 9f475d670d..cb4897a733 100644 --- a/latte/es/extending-latte.texy +++ b/latte/es/extending-latte.texy @@ -68,6 +68,16 @@ Como puede ver, la función recibe la parte izquierda del filtro antes de la tub Por supuesto, la función que representa el filtro puede aceptar cualquier número de parámetros, y también se admiten parámetros variádicos. +Si el filtro devuelve una cadena en HTML, puede marcarla para que Latte no la escape automáticamente (y por tanto por partida doble). Esto evita la necesidad de especificar `|noescape` en la plantilla. +La forma más fácil es envolver la cadena en un objeto `Latte\Runtime\Html`, la otra forma es [Filtros contextuales |#Contextual Filters]. + +```php +$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("$amount EUR")); +``` + +.[note] +En este caso, el filtro debe garantizar el correcto escape de los datos. + Filtros que utilizan la clase .[#toc-filters-using-the-class] ------------------------------------------------------------- @@ -150,7 +160,7 @@ $latte->addFilter('money', function (FilterInfo $info, float $amount): string { // change content-type to HTML $info->contentType = ContentType::Html; - return "$num Kč"; + return "$amount EUR"; }); ``` diff --git a/latte/fr/extending-latte.texy b/latte/fr/extending-latte.texy index 598eb8c810..f56410c7cb 100644 --- a/latte/fr/extending-latte.texy +++ b/latte/fr/extending-latte.texy @@ -68,6 +68,16 @@ Comme vous pouvez le voir, la fonction reçoit le côté gauche du filtre avant Bien sûr, la fonction représentant le filtre peut accepter n'importe quel nombre de paramètres, et les paramètres variadiques sont également supportés. +Si le filtre renvoie une chaîne en HTML, vous pouvez la marquer pour que Latte ne l'échappe pas automatiquement (et donc doublement). Cela évite d'avoir à spécifier `|noescape` dans le modèle. +La méthode la plus simple consiste à envelopper la chaîne dans un objet `Latte\Runtime\Html`, l'autre méthode étant celle des [filtres contextuels |#Contextual Filters]. + +```php +$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("$amount EUR")); +``` + +.[note] +Dans ce cas, le filtre doit assurer l'échappement correct des données. + Filtres utilisant la classe .[#toc-filters-using-the-class] ----------------------------------------------------------- @@ -150,7 +160,7 @@ $latte->addFilter('money', function (FilterInfo $info, float $amount): string { // changez le type de contenu en HTML $info->contentType = ContentType::Html; - return "$num Kč"; + return "$amount EUR"; }); ``` diff --git a/latte/hu/extending-latte.texy b/latte/hu/extending-latte.texy index aa1b38451f..3a5c70cb0b 100644 --- a/latte/hu/extending-latte.texy +++ b/latte/hu/extending-latte.texy @@ -68,6 +68,16 @@ Mint látható, a függvény a következő argumentumként a szűrő bal oldalá Természetesen a szűrőt reprezentáló függvény tetszőleges számú paramétert fogadhat el, és a változó paraméterek is támogatottak. +Ha a szűrő egy karakterláncot ad vissza HTML-ben, akkor megjelölheted, hogy a Latte ne automatikusan (és ezért duplán) szedje ki. Így elkerülhető a `|noescape` megadása a sablonban. +A legegyszerűbb, ha a sztringet egy `Latte\Runtime\Html` objektumba csomagoljuk, a másik lehetőség a [Contextual Filters |#Contextual Filters]. + +```php +$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("$amount EUR")); +``` + +.[note] +Ebben az esetben a szűrőnek biztosítania kell az adatok helyes kikerülését. + Az osztályt használó szűrők .[#toc-filters-using-the-class] ----------------------------------------------------------- @@ -150,7 +160,7 @@ $latte->addFilter('money', function (FilterInfo $info, float $amount): string { // a tartalomtípust HTML-re módosítja $info->contentType = ContentType::Html; - return "$num Kč"; + return "$amount EUR"; }); ``` diff --git a/latte/it/extending-latte.texy b/latte/it/extending-latte.texy index 913314c0ad..a64f7c8f76 100644 --- a/latte/it/extending-latte.texy +++ b/latte/it/extending-latte.texy @@ -68,6 +68,16 @@ Come si può vedere, la funzione riceve il lato sinistro del filtro prima della Naturalmente, la funzione che rappresenta il filtro può accettare un numero qualsiasi di parametri e sono supportati anche i parametri variabili. +Se il filtro restituisce una stringa in HTML, è possibile contrassegnarla in modo che Latte non esegua automaticamente (e quindi doppiamente) l'escape. Questo evita la necessità di specificare `|noescape` nel template. +Il modo più semplice è avvolgere la stringa in un oggetto `Latte\Runtime\Html`, l'altro modo è [Filtri contestuali |#Contextual Filters]. + +```php +$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("$amount EUR")); +``` + +.[note] +In questo caso, il filtro deve garantire il corretto escape dei dati. + Filtri che utilizzano la classe .[#toc-filters-using-the-class] --------------------------------------------------------------- @@ -150,7 +160,7 @@ $latte->addFilter('money', function (FilterInfo $info, float $amount): string { // cambia il tipo di contenuto in HTML $info->contentType = ContentType::Html; - return "$num Kč"; + return "$amount EUR"; }); ``` diff --git a/latte/ja/extending-latte.texy b/latte/ja/extending-latte.texy index 89d74f20ab..ac08174855 100644 --- a/latte/ja/extending-latte.texy +++ b/latte/ja/extending-latte.texy @@ -68,6 +68,16 @@ $latte->addFilter('shortify', fn(string $s, int $len = 10) => mb_substr($s, 0, $ もちろん、フィルタを表す関数は任意の数のパラメータを受け取ることができ、可変長のパラメータもサポートされています。 +フィルターがHTMLの文字列を返す場合、ラテが自動的に(つまり二重に)エスケープしないようにマークすることができます。これにより、テンプレートで`|noescape` を指定する必要がなくなります。 +最も簡単な方法は、`Latte\Runtime\Html` オブジェクトで文字列をラップすることです。もう一つの方法は、[コンテキストフィルタ |#Contextual Filters]です。 + +```php +$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("$amount EUR")); +``` + +.[note] +この場合、フィルターはデータの正しいエスケープを保証しなければならない。 + クラスを使ったフィルタ .[#toc-filters-using-the-class] ------------------------------------------- @@ -150,7 +160,7 @@ $latte->addFilter('money', function (FilterInfo $info, float $amount): string { // change content-type to HTML $info->contentType = ContentType::Html; - return "$num Kč"; + return "$amount EUR"; }); ``` diff --git a/latte/pl/extending-latte.texy b/latte/pl/extending-latte.texy index 9c6fc477ff..76b093805f 100644 --- a/latte/pl/extending-latte.texy +++ b/latte/pl/extending-latte.texy @@ -68,6 +68,16 @@ Jak widać, funkcja otrzymuje lewą stronę filtra przed fajką `|` jako první Oczywiście funkcja reprezentująca filtr może przyjąć dowolną liczbę parametrów, obsługiwane są również parametry variadyczne. +Jeśli filtr zwraca ciąg znaków w HTML, można go oznaczyć, aby Latte nie wykonywało automatycznego (a więc podwójnego) escapingu. Pozwala to uniknąć konieczności określania `|noescape` w szablonie. +Najprostszym sposobem jest zawinięcie łańcucha w obiekt `Latte\Runtime\Html`, innym sposobem są [filtry kontekstowe |#Contextual Filters]. + +```php +$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("$amount EUR")); +``` + +.[note] +W takim przypadku filtr musi zapewnić prawidłowe uciekanie danych. + Filtry z wykorzystaniem klasy .[#toc-filters-using-the-class] ------------------------------------------------------------- @@ -150,7 +160,7 @@ $latte->addFilter('money', function (FilterInfo $info, float $amount): string { // změníme content-type na HTML $info->contentType = ContentType::Html; - return "$num Kč"; + return "$amount EUR"; }); ``` diff --git a/latte/pt/extending-latte.texy b/latte/pt/extending-latte.texy index a20cb5cfc3..5e4fd40609 100644 --- a/latte/pt/extending-latte.texy +++ b/latte/pt/extending-latte.texy @@ -68,6 +68,16 @@ Como você pode ver, a função recebe o lado esquerdo do filtro antes do tubo ` Naturalmente, a função que representa o filtro pode aceitar qualquer número de parâmetros, e parâmetros variáveis também são suportados. +Se o filtro retornar uma cadeia de caracteres em HTML, você poderá marcá-la para que o Latte não a escape automaticamente (e, portanto, duplamente). Isso evita a necessidade de especificar `|noescape` no modelo. +A maneira mais fácil é envolver a cadeia de caracteres em um objeto `Latte\Runtime\Html`. A outra maneira é usar o [Contextual Filters |#Contextual Filters]. + +```php +$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("$amount EUR")); +``` + +.[note] +Nesse caso, o filtro deve garantir o escape correto dos dados. + Filtros que utilizam a classe .[#toc-filters-using-the-class] ------------------------------------------------------------- @@ -150,7 +160,7 @@ $latte->addFilter('money', function (FilterInfo $info, float $amount): string { // mudar o tipo de conteúdo para HTML $info->contentType = ContentType::Html; - return "$num Kč"; + return "$amount EUR"; }); ``` diff --git a/latte/ro/extending-latte.texy b/latte/ro/extending-latte.texy index 2d456f3147..855d311eae 100644 --- a/latte/ro/extending-latte.texy +++ b/latte/ro/extending-latte.texy @@ -68,6 +68,16 @@ După cum puteți vedea, funcția primește partea stângă a filtrului înainte Bineînțeles, funcția care reprezintă filtrul poate accepta orice număr de parametri, fiind suportați și parametrii variadici. +În cazul în care filtrul returnează un șir de caractere în HTML, îl puteți marca astfel încât Latte să nu-l evadeze automat (și, prin urmare, dublu). Astfel se evită necesitatea de a specifica `|noescape` în șablon. +Cea mai simplă modalitate este să înfășurați șirul într-un obiect `Latte\Runtime\Html`, cealaltă modalitate este [Filtre contextuale |#Contextual Filters]. + +```php +$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("$amount EUR")); +``` + +.[note] +În acest caz, filtrul trebuie să asigure o scăpare corectă a datelor. + Filtre care utilizează clasa .[#toc-filters-using-the-class] ------------------------------------------------------------ @@ -150,7 +160,7 @@ $latte->addFilter('money', function (FilterInfo $info, float $amount): string { // schimbăm tipul de conținut în HTML $info->contentType = ContentType::Html; - return "$num Kč"; + return "$amount EUR"; }); ``` diff --git a/latte/ru/extending-latte.texy b/latte/ru/extending-latte.texy index cd592d0cdc..c032d8a9cb 100644 --- a/latte/ru/extending-latte.texy +++ b/latte/ru/extending-latte.texy @@ -68,6 +68,16 @@ $latte->addFilter('shortify', fn(string $s, int $len = 10) => mb_substr($s, 0, $ Конечно, функция, представляющая фильтр, может принимать любое количество параметров, также поддерживаются переменные параметры. +Если фильтр возвращает строку в HTML, то можно пометить ее так, чтобы Latte не делал автоматическую (и, соответственно, двойную) экранировку. Это избавляет от необходимости указывать `|noescape` в шаблоне. +Самый простой способ - обернуть строку в объект `Latte\Runtime\Html`, другой способ - [Контекстные фильтры |#Contextual Filters]. + +```php +$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("$amount EUR")); +``` + +.[note] +В этом случае фильтр должен обеспечить корректное экранирование данных. + Фильтры, использующие класс .[#toc-filters-using-the-class] ----------------------------------------------------------- @@ -150,7 +160,7 @@ $latte->addFilter('money', function (FilterInfo $info, float $amount): string { // change content-type to HTML $info->contentType = ContentType::Html; - return "$num Kč"; + return "$amount EUR"; }); ``` diff --git a/latte/sl/extending-latte.texy b/latte/sl/extending-latte.texy index 791fe3bcee..b9479b5c87 100644 --- a/latte/sl/extending-latte.texy +++ b/latte/sl/extending-latte.texy @@ -68,6 +68,16 @@ Kot lahko vidite, funkcija kot naslednje argumente prejme levo stran filtra pred Seveda lahko funkcija, ki predstavlja filter, sprejme poljubno število parametrov, podprti pa so tudi variabilni parametri. +Če filter vrne niz HTML, ga lahko označite, da ga Latte ne bo samodejno (in zato dvojno) eskapiral. S tem se izognete potrebi, da bi v predlogi določili `|noescape`. +Najlažji način je, da niz zapakirate v objekt `Latte\Runtime\Html`, drugi način pa so [kontekstualni filtri |#Contextual Filters]. + +```php +$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("$amount EUR")); +``` + +.[note] +V tem primeru mora filter zagotoviti pravilno izpisovanje podatkov. + Filtri z uporabo razreda .[#toc-filters-using-the-class] -------------------------------------------------------- @@ -150,7 +160,7 @@ $latte->addFilter('money', function (FilterInfo $info, float $amount): string { // spremenimo tip vsebine v HTML $info->contentType = ContentType::Html; - return "$num Kč"; + return "$amount EUR"; }); ``` diff --git a/latte/tr/extending-latte.texy b/latte/tr/extending-latte.texy index 51489c1c4a..cace18d2bb 100644 --- a/latte/tr/extending-latte.texy +++ b/latte/tr/extending-latte.texy @@ -68,6 +68,16 @@ Gördüğünüz gibi, fonksiyon `|` as the first argument and the arguments pass Elbette, filtreyi temsil eden fonksiyon herhangi bir sayıda parametre kabul edebilir ve değişken parametreler de desteklenir. +Filtre HTML'de bir dize döndürürse, Latte'nin otomatik olarak (ve bu nedenle çift) kaçış yapmaması için işaretleyebilirsiniz. Bu, şablonda `|noescape` belirtme ihtiyacını ortadan kaldırır. +En kolay yol dizeyi bir `Latte\Runtime\Html` nesnesine sarmaktır, diğer yol ise [Bağlamsal Filtrelerdir |#Contextual Filters]. + +```php +$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("$amount EUR")); +``` + +.[note] +Bu durumda, filtre verilerin doğru şekilde kaçmasını sağlamalıdır. + Sınıfı Kullanan Filtreler .[#toc-filters-using-the-class] --------------------------------------------------------- @@ -150,7 +160,7 @@ $latte->addFilter('money', function (FilterInfo $info, float $amount): string { // içerik türünü HTML olarak değiştir $info->contentType = ContentType::Html; - return "$num Kč"; + return "$amount EUR"; }); ``` diff --git a/latte/uk/extending-latte.texy b/latte/uk/extending-latte.texy index 0a2a8b29c3..531dd46cdb 100644 --- a/latte/uk/extending-latte.texy +++ b/latte/uk/extending-latte.texy @@ -68,6 +68,16 @@ $latte->addFilter('shortify', fn(string $s, int $len = 10) => mb_substr($s, 0, $ Звичайно, функція, що представляє фільтр, може приймати будь-яку кількість параметрів, також підтримуються змінні параметри. +Якщо фільтр повертає рядок у форматі HTML, ви можете позначити його, щоб Latte не використовував автоматичне (і, відповідно, подвійне) екранування. Це дозволяє уникнути необхідності вказувати `|noescape` у шаблоні. +Найпростіший спосіб - обернути рядок в об'єкт `Latte\Runtime\Html`, інший спосіб - [контекстні фільтри |#Contextual Filters]. + +```php +$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("$amount EUR")); +``` + +.[note] +У цьому випадку фільтр повинен забезпечити коректне екранування даних. + Фільтри, що використовують клас .[#toc-filters-using-the-class] --------------------------------------------------------------- @@ -150,7 +160,7 @@ $latte->addFilter('money', function (FilterInfo $info, float $amount): string { // змінюємо тип контенту на HTML $info->contentType = ContentType::Html; - return "$num Kč"; + return "$amount EUR"; }); ``` From bafbffb8460294a2026361d815c524e0e0b9bc5c Mon Sep 17 00:00:00 2001 From: David Grudl Date: Fri, 22 Sep 2023 10:44:40 +0200 Subject: [PATCH 009/137] Tracy: added mappings --- tracy/bg/open-files-in-ide.texy | 9 +++++++++ tracy/cs/open-files-in-ide.texy | 13 +++++++++++-- tracy/de/open-files-in-ide.texy | 9 +++++++++ tracy/el/open-files-in-ide.texy | 9 +++++++++ tracy/en/open-files-in-ide.texy | 13 +++++++++++-- tracy/es/open-files-in-ide.texy | 9 +++++++++ tracy/fr/open-files-in-ide.texy | 9 +++++++++ tracy/hu/open-files-in-ide.texy | 9 +++++++++ tracy/it/open-files-in-ide.texy | 9 +++++++++ tracy/pl/open-files-in-ide.texy | 9 +++++++++ tracy/pt/open-files-in-ide.texy | 9 +++++++++ tracy/ro/open-files-in-ide.texy | 9 +++++++++ tracy/ru/open-files-in-ide.texy | 9 +++++++++ tracy/sl/open-files-in-ide.texy | 9 +++++++++ tracy/tr/open-files-in-ide.texy | 9 +++++++++ tracy/uk/open-files-in-ide.texy | 9 +++++++++ 16 files changed, 148 insertions(+), 4 deletions(-) diff --git a/tracy/bg/open-files-in-ide.texy b/tracy/bg/open-files-in-ide.texy index 2dc107b45e..af0a54662c 100644 --- a/tracy/bg/open-files-in-ide.texy +++ b/tracy/bg/open-files-in-ide.texy @@ -41,6 +41,15 @@ var settings = { Това става, като се стартира скриптът `install.cmd`. ** Трябва да го стартирате като администратор.** Скриптът `open-editor.js` сега ще обслужва протокола `editor://`. +За да отваряте връзки, генерирани на други сървъри, например производствен сървър или Docker, добавете съпоставяне на отдалечен към локален URL адрес към `open-editor.js`: + +```js + mappings: { + // remote path: local path + '/var/www/nette.app': 'W:\\Nette.web\\_web', + } +``` + Linux .[#toc-linux] =================== diff --git a/tracy/cs/open-files-in-ide.texy b/tracy/cs/open-files-in-ide.texy index 2483f08ae5..0d7fa6a865 100644 --- a/tracy/cs/open-files-in-ide.texy +++ b/tracy/cs/open-files-in-ide.texy @@ -41,6 +41,15 @@ Pozor, ponechávejte dvojitá lomítka v cestách. To uděláte spuštěním soubor `install.cmd`. **Je potřeba ho spustit jako Správce.** Skript `open-editor.js` bude nyní obsluhovat protokol `editor://`. +Aby bylo možné otevírat odkazy vygenerované na jiných serverech, jako třeba na ostrém serveru nebo v Dockeru, doplňte do `open-editor.js` ještě mapování vzdálené URL na lokální: + +```js + mappings: { + // vzdálená cesta: lokální cesta + '/var/www/nette.app': 'W:\\Nette.web\\_web', + } +``` + Linux ===== @@ -119,8 +128,8 @@ Vytvoření souboru: - Ve Firefoxu může být potřeba protokol povolit [nastavením |http://kb.mozillazine.org/Register_protocol#Firefox_3.5_and_above] `network.protocol-handler.expose.editor` na `false` a `network.protocol-handler.expose-all` na `true` v about:config. - Pokud vám to hned nepůjde, nepanikařte a zkuste párkrát refreshnout stránku před klikem na onen odkaz. Rozjede se to! -- Zde je [link|https://www.winhelponline.com/blog/error-there-is-no-script-engine-for-file-extension-when-running-js-files/] na opravu případné chyby: - Input Error: There is no script engine for file extension ".js" Maybe you associated ".js" file to another app, not JScript engine. +- Zde je [link|https://www.winhelponline.com/blog/error-there-is-no-script-engine-for-file-extension-when-running-js-files/] + na opravu případné chyby: `Input Error: There is no script engine for file extension ".js"`, `Maybe you associated ".js" file to another app, not JScript engine.` respektive `pro příponu .js není k dispozici žádný skriptovací stroj`. V Google Chrome od verze 77 již neuvidíte zatržítko „Tento typ odkazů vždy otevírat v přidružené aplikaci“, když je editor spuštěný prostřednictvím odkazu. Řešení pro Windows: vytvořte soubor `fix.reg`: diff --git a/tracy/de/open-files-in-ide.texy b/tracy/de/open-files-in-ide.texy index cb31a42091..0f30fb6c2d 100644 --- a/tracy/de/open-files-in-ide.texy +++ b/tracy/de/open-files-in-ide.texy @@ -41,6 +41,15 @@ Seien Sie vorsichtig und behalten Sie die doppelten Schrägstriche in den Pfaden Dazu führen Sie `install.cmd` aus. **Sie müssen es als Administrator ausführen**. Das Skript `open-editor.js` bedient nun das Protokoll `editor://`. +Um Links zu öffnen, die auf anderen Servern generiert wurden, z. B. auf einem Produktionsserver oder Docker, fügen Sie eine Remote-zu-Local-URL-Zuordnung zu `open-editor.js` hinzu: + +```js + mappings: { + // remote path: local path + '/var/www/nette.app': 'W:\\Nette.web\\_web', + } +``` + Linux .[#toc-linux] =================== diff --git a/tracy/el/open-files-in-ide.texy b/tracy/el/open-files-in-ide.texy index 13621cdf1c..e8b94df8e0 100644 --- a/tracy/el/open-files-in-ide.texy +++ b/tracy/el/open-files-in-ide.texy @@ -41,6 +41,15 @@ var settings = { Αυτό γίνεται εκτελώντας το `install.cmd`. **Πρέπει να το εκτελέσετε ως διαχειριστής.** Το σενάριο `open-editor.js` θα εξυπηρετεί τώρα το πρωτόκολλο `editor://`. +Για να ανοίξετε συνδέσμους που δημιουργούνται σε άλλους διακομιστές, όπως ένας διακομιστής παραγωγής ή ο Docker, προσθέστε μια αντιστοίχιση απομακρυσμένης σε τοπική διεύθυνση URL στο `open-editor.js`: + +```js + mappings: { + // remote path: local path + '/var/www/nette.app': 'W:\\Nette.web\\_web', + } +``` + Linux .[#toc-linux] =================== diff --git a/tracy/en/open-files-in-ide.texy b/tracy/en/open-files-in-ide.texy index 0c55974726..6a9d269a10 100644 --- a/tracy/en/open-files-in-ide.texy +++ b/tracy/en/open-files-in-ide.texy @@ -41,6 +41,15 @@ Be careful and keep the double slashes in the paths. This is done by running `install.cmd`. **You need to run it as an Administrator.** The `open-editor.js` script will now serve the `editor://` protocol. +In order to open links generated on other servers, such as a production server or Docker, add a remote to local URL mapping to `open-editor.js`: + +```js + mappings: { + // remote path: local path + '/var/www/nette.app': 'W:\\Nette.web\\_web', + } +``` + Linux ===== @@ -119,8 +128,8 @@ Troubleshooting - In Firefox you may need to [allow |http://kb.mozillazine.org/Register_protocol#Firefox_3.5_and_above] custom protocol execution in about:config by setting `network.protocol-handler.expose.editor` to `false` and `network.protocol-handler.expose-all` to `true`. It should be allowed by default, however. - If it's not all working immediately, don't panic. Try to refresh the page, restart browser or computer. That should help. -- See [here|https://www.winhelponline.com/blog/error-there-is-no-script-engine-for-file-extension-when-running-js-files/] to fix: - Input Error: There is no script engine for file extension ".js" Maybe you associated ".js" file to another app, not JScript engine. +- Here is the [link |https://www.winhelponline.com/blog/error-there-is-no-script-engine-for-file-extension-when-running-js-files/] + to correct any errors: `Input Error: There is no script engine for file extension ".js"` or `Maybe you associated ".js" file to another app, not JScript engine.` Starting from Google Chrome version 77 you will no longer see the checkbox “Always open these types of links in the associated app” when editor is opened through a link. Workaround for Windows: create file `fix.reg`: diff --git a/tracy/es/open-files-in-ide.texy b/tracy/es/open-files-in-ide.texy index 787ff8a5db..506ea462d6 100644 --- a/tracy/es/open-files-in-ide.texy +++ b/tracy/es/open-files-in-ide.texy @@ -41,6 +41,15 @@ Ten cuidado y mantén las barras dobles en las rutas. Esto se hace ejecutando `install.cmd`. **Necesitas ejecutarlo como Administrador. El script `open-editor.js` ahora servirá al protocolo `editor://`. +Para abrir enlaces generados en otros servidores, como un servidor de producción o Docker, añada una asignación de URL remota a local a `open-editor.js`: + +```js + mappings: { + // remote path: local path + '/var/www/nette.app': 'W:\\Nette.web\\_web', + } +``` + Linux .[#toc-linux] =================== diff --git a/tracy/fr/open-files-in-ide.texy b/tracy/fr/open-files-in-ide.texy index 4adeae2223..e6f5f73384 100644 --- a/tracy/fr/open-files-in-ide.texy +++ b/tracy/fr/open-files-in-ide.texy @@ -41,6 +41,15 @@ Faites attention et gardez les doubles slashs dans les chemins. Ceci est fait en exécutant `install.cmd`. **Vous devez l'exécuter en tant qu'administrateur. Le script `open-editor.js` servira désormais le protocole `editor://`. +Afin d'ouvrir les liens générés sur d'autres serveurs, tels qu'un serveur de production ou Docker, ajoutez un mappage d'URL distant à local à `open-editor.js`: + +```js + mappings: { + // remote path: local path + '/var/www/nette.app': 'W:\\Nette.web\\_web', + } +``` + Linux .[#toc-linux] =================== diff --git a/tracy/hu/open-files-in-ide.texy b/tracy/hu/open-files-in-ide.texy index 5500772969..551428802a 100644 --- a/tracy/hu/open-files-in-ide.texy +++ b/tracy/hu/open-files-in-ide.texy @@ -41,6 +41,15 @@ Legyen óvatos, és tartsa meg a kettős kötőjeleket az elérési utakban. Ez a `install.cmd` futtatásával történik. **Adminisztrátorként kell futtatnia.** A `open-editor.js` szkript mostantól a `editor://` protokollt fogja kiszolgálni. +Ahhoz, hogy más szervereken, például egy termelési szerveren vagy Dockerben létrehozott hivatkozásokat nyisson meg, adjon hozzá egy távoli helyi URL-t leképezőt a `open-editor.js` címhez: + +```js + mappings: { + // remote path: local path + '/var/www/nette.app': 'W:\\Nette.web\\_web', + } +``` + Linux .[#toc-linux] =================== diff --git a/tracy/it/open-files-in-ide.texy b/tracy/it/open-files-in-ide.texy index 4250065585..4d2c2c77ae 100644 --- a/tracy/it/open-files-in-ide.texy +++ b/tracy/it/open-files-in-ide.texy @@ -41,6 +41,15 @@ Fate attenzione a mantenere le doppie barre nei percorsi. Questo si fa eseguendo `install.cmd`. **Lo script `open-editor.js` servirà ora il protocollo `editor://`. +Per aprire i link generati su altri server, come un server di produzione o Docker, aggiungere una mappatura dell'URL da remoto a locale a `open-editor.js`: + +```js + mappings: { + // remote path: local path + '/var/www/nette.app': 'W:\\Nette.web\\_web', + } +``` + Linux .[#toc-linux] =================== diff --git a/tracy/pl/open-files-in-ide.texy b/tracy/pl/open-files-in-ide.texy index c53061cae1..238b907b86 100644 --- a/tracy/pl/open-files-in-ide.texy +++ b/tracy/pl/open-files-in-ide.texy @@ -41,6 +41,15 @@ Uważaj, aby zostawić podwójne ukośniki w ścieżkach. Robisz to uruchamiając plik `install.cmd`. **Musisz uruchomić go jako Administrator.** Skrypt `open-editor.js` będzie teraz obsługiwał protokół `editor://`. +Aby otworzyć linki wygenerowane na innych serwerach, takich jak serwer produkcyjny lub Docker, należy dodać mapowanie zdalnego adresu URL na lokalny do `open-editor.js`: + +```js + mappings: { + // remote path: local path + '/var/www/nette.app': 'W:\\Nette.web\\_web', + } +``` + Linux .[#toc-linux] =================== diff --git a/tracy/pt/open-files-in-ide.texy b/tracy/pt/open-files-in-ide.texy index ad4fa053af..1e2a6b8f91 100644 --- a/tracy/pt/open-files-in-ide.texy +++ b/tracy/pt/open-files-in-ide.texy @@ -41,6 +41,15 @@ Tenha cuidado e mantenha os cortes duplos nos caminhos. Isto é feito através da `install.cmd`. ** Você precisa executá-lo como Administrador.** O script `open-editor.js` servirá agora ao protocolo `editor://`. +Para abrir links gerados em outros servidores, como um servidor de produção ou o Docker, adicione um mapeamento de URL remoto para local em `open-editor.js`: + +```js + mappings: { + // remote path: local path + '/var/www/nette.app': 'W:\\Nette.web\\_web', + } +``` + Linux .[#toc-linux] =================== diff --git a/tracy/ro/open-files-in-ide.texy b/tracy/ro/open-files-in-ide.texy index b59ff680af..b4613e5e07 100644 --- a/tracy/ro/open-files-in-ide.texy +++ b/tracy/ro/open-files-in-ide.texy @@ -41,6 +41,15 @@ Fiți atenți și păstrați barierele duble în căile de acces. Acest lucru se face prin rularea `install.cmd`. **Trebuie să îl rulați ca administrator.** Scriptul `open-editor.js` va servi acum protocolul `editor://`. +Pentru a deschide linkuri generate pe alte servere, cum ar fi un server de producție sau Docker, adăugați o corespondență URL de la distanță la local la `open-editor.js`: + +```js + mappings: { + // remote path: local path + '/var/www/nette.app': 'W:\\Nette.web\\_web', + } +``` + Linux .[#toc-linux] =================== diff --git a/tracy/ru/open-files-in-ide.texy b/tracy/ru/open-files-in-ide.texy index deb1328d5a..e4579a7dbf 100644 --- a/tracy/ru/open-files-in-ide.texy +++ b/tracy/ru/open-files-in-ide.texy @@ -41,6 +41,15 @@ var settings = { Это делается путем запуска скрипта `install.cmd`. **Вы должны запустить его от имени администратора.** Скрипт `open-editor.js` теперь будет обслуживать протокол `editor://`. +Для того чтобы открывать ссылки, созданные на других серверах, например, на рабочем сервере или в Docker, добавьте сопоставление удаленных и локальных URL-адресов на `open-editor.js`: + +```js + mappings: { + // remote path: local path + '/var/www/nette.app': 'W:\\Nette.web\\_web', + } +``` + Linux .[#toc-linux] =================== diff --git a/tracy/sl/open-files-in-ide.texy b/tracy/sl/open-files-in-ide.texy index f616ef9d31..ee0233abd4 100644 --- a/tracy/sl/open-files-in-ide.texy +++ b/tracy/sl/open-files-in-ide.texy @@ -41,6 +41,15 @@ Bodite previdni in ohranite dvojne poševnice v poteh. To storite tako, da zaženete `install.cmd`. **Zažeti ga morate kot skrbnik.** Skripta `open-editor.js` bo zdaj služila protokolu `editor://`. +Če želite odpreti povezave, ustvarjene v drugih strežnikih, na primer produkcijskem strežniku ali strežniku Docker, v spletno mesto `open-editor.js` dodajte preslikavo oddaljenega v lokalni naslov URL: + +```js + mappings: { + // remote path: local path + '/var/www/nette.app': 'W:\\Nette.web\\_web', + } +``` + Linux .[#toc-linux] =================== diff --git a/tracy/tr/open-files-in-ide.texy b/tracy/tr/open-files-in-ide.texy index b9b4900fb2..50fab80666 100644 --- a/tracy/tr/open-files-in-ide.texy +++ b/tracy/tr/open-files-in-ide.texy @@ -41,6 +41,15 @@ Dikkatli olun ve çift eğik çizgileri yollarda tutun. Bu işlem `install.cmd` çalıştırılarak yapılır. **Yönetici olarak çalıştırmanız gerekir.** `open-editor.js` betiği artık `editor://` protokolüne hizmet edecektir. +Üretim sunucusu veya Docker gibi diğer sunucularda oluşturulan bağlantıları açmak için `open-editor.js` adresine bir uzak-yerel URL eşlemesi ekleyin: + +```js + mappings: { + // remote path: local path + '/var/www/nette.app': 'W:\\Nette.web\\_web', + } +``` + Linux .[#toc-linux] =================== diff --git a/tracy/uk/open-files-in-ide.texy b/tracy/uk/open-files-in-ide.texy index b1272d7225..42681cc378 100644 --- a/tracy/uk/open-files-in-ide.texy +++ b/tracy/uk/open-files-in-ide.texy @@ -41,6 +41,15 @@ var settings = { Це робиться шляхом запуску скрипта `install.cmd`. **Ви повинні запустити його від імені адміністратора.** Скрипт `open-editor.js` тепер буде обслуговувати протокол `editor://`. +Щоб відкрити посилання, створені на інших серверах, таких як продакшн-сервер або Docker, додайте віддалене до локального зіставлення URL-адрес до `open-editor.js`: + +```js + mappings: { + // remote path: local path + '/var/www/nette.app': 'W:\\Nette.web\\_web', + } +``` + Linux .[#toc-linux] =================== From bd38bdeefa7b898c07627a3e92764426c6ee57a1 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 26 Sep 2023 20:26:46 +0200 Subject: [PATCH 010/137] robot-loader: info about standalone usage --- robot-loader/bg/@home.texy | 11 ++++++++++- robot-loader/cs/@home.texy | 11 ++++++++++- robot-loader/de/@home.texy | 11 ++++++++++- robot-loader/el/@home.texy | 11 ++++++++++- robot-loader/en/@home.texy | 11 ++++++++++- robot-loader/es/@home.texy | 11 ++++++++++- robot-loader/fr/@home.texy | 11 ++++++++++- robot-loader/hu/@home.texy | 11 ++++++++++- robot-loader/it/@home.texy | 11 ++++++++++- robot-loader/pl/@home.texy | 11 ++++++++++- robot-loader/pt/@home.texy | 11 ++++++++++- robot-loader/ro/@home.texy | 11 ++++++++++- robot-loader/ru/@home.texy | 11 ++++++++++- robot-loader/sl/@home.texy | 11 ++++++++++- robot-loader/tr/@home.texy | 11 ++++++++++- robot-loader/uk/@home.texy | 11 ++++++++++- 16 files changed, 160 insertions(+), 16 deletions(-) diff --git a/robot-loader/bg/@home.texy b/robot-loader/bg/@home.texy index 2fdf709047..333415531b 100644 --- a/robot-loader/bg/@home.texy +++ b/robot-loader/bg/@home.texy @@ -24,7 +24,16 @@ require_once 'Utils/Paginator.php'; Инсталиране на .[#toc-installation] ----------------------------------- -Изтеглете и инсталирайте пакета, като използвате [Composer|best-practices:composer]: +Можете да изтеглите RobotLoader като [един самостоятелен файл `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], който можете да включите в скрипта си с помощта на `require`, и веднага да разполагате с удобно автоматично зареждане за цялото си приложение: + +```php +require '/path/to/RobotLoader.php'; + +$loader = new Nette\Loaders\RobotLoader; +// ... +``` + +Ако изграждате приложение, което използва [Composer |best-practices:composer], можете да го инсталирате чрез него: ```shell composer require nette/robot-loader diff --git a/robot-loader/cs/@home.texy b/robot-loader/cs/@home.texy index 13acd5b3e3..2e5e544ee5 100644 --- a/robot-loader/cs/@home.texy +++ b/robot-loader/cs/@home.texy @@ -24,7 +24,16 @@ require_once 'Utils/Paginator.php'; Instalace --------- -Knihovnu stáhěte a nainstalujete pomocí nástroje [Composer|best-practices:composer]: +RobotLoader si můžete stáhnout jako [jeden samostatný soubor `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], který vložíte pomocí `require` do svého skriptu a hned máte k dispozici komfortní autoloading pro celou aplikaci. + +```php +require '/path/to/RobotLoader.php'; + +$loader = new Nette\Loaders\RobotLoader; +// ... +``` + +Pokud stavíte aplikaci využívající [Composer|best-practices:composer], můžete jej nainstalovat pomocí něj: ```shell composer require nette/robot-loader diff --git a/robot-loader/de/@home.texy b/robot-loader/de/@home.texy index 71dda5a3cb..2218f88bce 100644 --- a/robot-loader/de/@home.texy +++ b/robot-loader/de/@home.texy @@ -24,7 +24,16 @@ require_once 'Utils/Paginator.php'; Installation .[#toc-installation] --------------------------------- -Laden Sie das Paket herunter und installieren Sie es mit [Composer |best-practices:composer]: +Sie können RobotLoader als [einzelne Standalone-Datei `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php] herunterladen, die Sie mit `require` in Ihr Skript einbinden können, und haben sofort eine komfortable automatische Ladung für Ihre gesamte Anwendung: + +```php +require '/path/to/RobotLoader.php'; + +$loader = new Nette\Loaders\RobotLoader; +// ... +``` + +Wenn Sie eine Anwendung erstellen, die [Composer |best-practices:composer] verwendet, können Sie ihn über Composer installieren: ```shell composer require nette/robot-loader diff --git a/robot-loader/el/@home.texy b/robot-loader/el/@home.texy index 4f037f2c0e..d705af5afc 100644 --- a/robot-loader/el/@home.texy +++ b/robot-loader/el/@home.texy @@ -24,7 +24,16 @@ require_once 'Utils/Paginator.php'; Εγκατάσταση .[#toc-installation] -------------------------------- -Κατεβάστε και εγκαταστήστε το πακέτο χρησιμοποιώντας το [Composer |best-practices:composer]: +Μπορείτε να κατεβάσετε το RobotLoader ως ένα μεμονωμένο [αρχείο `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], το οποίο μπορείτε να συμπεριλάβετε στο σενάριό σας χρησιμοποιώντας το `require`, και να έχετε αμέσως βολική αυτόματη φόρτωση για ολόκληρη την εφαρμογή σας: + +```php +require '/path/to/RobotLoader.php'; + +$loader = new Nette\Loaders\RobotLoader; +// ... +``` + +Εάν κατασκευάζετε μια εφαρμογή που χρησιμοποιεί το [Composer |best-practices:composer], μπορείτε να το εγκαταστήσετε μέσω αυτού: ```shell composer require nette/robot-loader diff --git a/robot-loader/en/@home.texy b/robot-loader/en/@home.texy index 028013bf86..d8cb1f60fc 100644 --- a/robot-loader/en/@home.texy +++ b/robot-loader/en/@home.texy @@ -24,7 +24,16 @@ require_once 'Utils/Paginator.php'; Installation ------------ -Download and install the package using [Composer|best-practices:composer]: +You can download RobotLoader as a [single standalone file `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], which you can include in your script using `require`, and immediately have convenient autoloading for your entire application: + +```php +require '/path/to/RobotLoader.php'; + +$loader = new Nette\Loaders\RobotLoader; +// ... +``` + +If you are building an application that uses [Composer|best-practices:composer], you can install it through it: ```shell composer require nette/robot-loader diff --git a/robot-loader/es/@home.texy b/robot-loader/es/@home.texy index 365dd5c96f..24506e56b0 100644 --- a/robot-loader/es/@home.texy +++ b/robot-loader/es/@home.texy @@ -24,7 +24,16 @@ require_once 'Utils/Paginator.php'; Instalación .[#toc-installation] -------------------------------- -Descargue e instale el paquete utilizando [Composer |best-practices:composer]: +Puede descargar RobotLoader como un [único archivo independiente `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], que puede incluir en su script utilizando `require`, y disponer inmediatamente de una cómoda carga automática para toda su aplicación: + +```php +require '/path/to/RobotLoader.php'; + +$loader = new Nette\Loaders\RobotLoader; +// ... +``` + +Si estás construyendo una aplicación que utiliza [Composer |best-practices:composer], puedes instalarlo a través de él: ```shell composer require nette/robot-loader diff --git a/robot-loader/fr/@home.texy b/robot-loader/fr/@home.texy index 89109f8308..cceff67b9a 100644 --- a/robot-loader/fr/@home.texy +++ b/robot-loader/fr/@home.texy @@ -24,7 +24,16 @@ require_once 'Utils/Paginator.php'; Installation .[#toc-installation] --------------------------------- -Téléchargez et installez le paquet en utilisant [Composer |best-practices:composer]: +Vous pouvez télécharger RobotLoader sous la forme d'un [fichier autonome `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], que vous pouvez inclure dans votre script à l'aide de `require`, et disposer immédiatement d'un chargement automatique pratique pour l'ensemble de votre application : + +```php +require '/path/to/RobotLoader.php'; + +$loader = new Nette\Loaders\RobotLoader; +// ... +``` + +Si vous construisez une application qui utilise [Composer |best-practices:composer], vous pouvez l'installer par l'intermédiaire de ce dernier : ```shell composer require nette/robot-loader diff --git a/robot-loader/hu/@home.texy b/robot-loader/hu/@home.texy index c8538cea54..45165f62b5 100644 --- a/robot-loader/hu/@home.texy +++ b/robot-loader/hu/@home.texy @@ -24,7 +24,16 @@ require_once 'Utils/Paginator.php'; Telepítés .[#toc-installation] ------------------------------ -Töltse le és telepítse a csomagot a [Composer |best-practices:composer] segítségével: +A RobotLoader egyetlen önálló fájlként letölthető [`RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], amelyet a `require` segítségével beilleszthet a szkriptjébe, és máris kényelmes automatikus betöltés áll rendelkezésére az egész alkalmazás számára: + +```php +require '/path/to/RobotLoader.php'; + +$loader = new Nette\Loaders\RobotLoader; +// ... +``` + +Ha olyan alkalmazást készít, amely a [Composert |best-practices:composer] használja, akkor azon keresztül telepítheti: ```shell composer require nette/robot-loader diff --git a/robot-loader/it/@home.texy b/robot-loader/it/@home.texy index 58c8528646..f61f8f3d65 100644 --- a/robot-loader/it/@home.texy +++ b/robot-loader/it/@home.texy @@ -24,7 +24,16 @@ require_once 'Utils/Paginator.php'; Installazione .[#toc-installation] ---------------------------------- -Scaricare e installare il pacchetto utilizzando [Composer |best-practices:composer]: +È possibile scaricare RobotLoader come un [singolo file standalone `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], che può essere incluso nel proprio script utilizzando `require`, e disporre immediatamente di un comodo caricamento automatico per l'intera applicazione: + +```php +require '/path/to/RobotLoader.php'; + +$loader = new Nette\Loaders\RobotLoader; +// ... +``` + +Se state costruendo un'applicazione che utilizza [Composer |best-practices:composer], potete installarlo attraverso di esso: ```shell composer require nette/robot-loader diff --git a/robot-loader/pl/@home.texy b/robot-loader/pl/@home.texy index a6fcc7f729..d95d91ac81 100644 --- a/robot-loader/pl/@home.texy +++ b/robot-loader/pl/@home.texy @@ -24,7 +24,16 @@ require_once 'Utils/Paginator.php'; Instalacja .[#toc-installation] ------------------------------- -Pobierz i zainstaluj bibliotekę za pomocą [Composera |best-practices:composer]: +RobotLoader można pobrać jako [pojedynczy, samodzielny plik `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], który można dołączyć do skryptu za pomocą `require` i natychmiast uzyskać wygodny autoloading dla całej aplikacji: + +```php +require '/path/to/RobotLoader.php'; + +$loader = new Nette\Loaders\RobotLoader; +// ... +``` + +Jeśli tworzysz aplikację korzystającą z [Composera |best-practices:composer], możesz ją zainstalować za jego pośrednictwem: ```shell composer require nette/robot-loader diff --git a/robot-loader/pt/@home.texy b/robot-loader/pt/@home.texy index daf06c0cbb..7ce9c57336 100644 --- a/robot-loader/pt/@home.texy +++ b/robot-loader/pt/@home.texy @@ -24,7 +24,16 @@ require_once 'Utils/Paginator.php'; Instalação .[#toc-installation] ------------------------------- -Baixe e instale o pacote usando [o Composer |best-practices:composer]: +Você pode fazer o download do RobotLoader como um [único arquivo autônomo `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], que pode ser incluído no seu script usando `require`, e ter imediatamente um carregamento automático conveniente para todo o seu aplicativo: + +```php +require '/path/to/RobotLoader.php'; + +$loader = new Nette\Loaders\RobotLoader; +// ... +``` + +Se estiver criando um aplicativo que usa [o Composer |best-practices:composer], poderá instalá-lo por meio dele: ```shell composer require nette/robot-loader diff --git a/robot-loader/ro/@home.texy b/robot-loader/ro/@home.texy index 931005f59e..882200243f 100644 --- a/robot-loader/ro/@home.texy +++ b/robot-loader/ro/@home.texy @@ -24,7 +24,16 @@ require_once 'Utils/Paginator.php'; Instalare .[#toc-installation] ------------------------------ -Descărcați și instalați pachetul folosind [Composer |best-practices:composer]: +Puteți descărca RobotLoader ca un [singur fișier independent `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], pe care îl puteți include în scriptul dvs. folosind `require`, și puteți avea imediat o încărcare automată convenabilă pentru întreaga aplicație: + +```php +require '/path/to/RobotLoader.php'; + +$loader = new Nette\Loaders\RobotLoader; +// ... +``` + +Dacă construiți o aplicație care utilizează [Composer |best-practices:composer], îl puteți instala prin intermediul acestuia: ```shell composer require nette/robot-loader diff --git a/robot-loader/ru/@home.texy b/robot-loader/ru/@home.texy index 0e2efe5380..e050f34605 100644 --- a/robot-loader/ru/@home.texy +++ b/robot-loader/ru/@home.texy @@ -24,7 +24,16 @@ require_once 'Utils/Paginator.php'; Установка .[#toc-installation] ------------------------------ -Загрузите и установите пакет с помощью [Composer|best-practices:composer]: +Вы можете загрузить RobotLoader в виде [отдельного файла `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], который можно включить в свой скрипт с помощью `require`, и сразу же получить удобную автозагрузку для всего приложения: + +```php +require '/path/to/RobotLoader.php'; + +$loader = new Nette\Loaders\RobotLoader; +// ... +``` + +Если вы создаете приложение, использующее [Composer |best-practices:composer], вы можете установить его через него: ```shell composer require nette/robot-loader diff --git a/robot-loader/sl/@home.texy b/robot-loader/sl/@home.texy index 47d3bab6ec..9415d0f3c7 100644 --- a/robot-loader/sl/@home.texy +++ b/robot-loader/sl/@home.texy @@ -24,7 +24,16 @@ require_once 'Utils/Paginator.php'; Namestitev .[#toc-installation] ------------------------------- -Prenesite in namestite paket s [programom Composer |best-practices:composer]: +RobotLoader lahko prenesete kot [eno samostojno datoteko `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], ki jo lahko vključite v svojo skripto z uporabo `require` in takoj dobite priročno samodejno polnjenje za celotno aplikacijo: + +```php +require '/path/to/RobotLoader.php'; + +$loader = new Nette\Loaders\RobotLoader; +// ... +``` + +Če gradite aplikacijo, ki uporablja [program Composer |best-practices:composer], ga lahko namestite prek njega: ```shell composer require nette/robot-loader diff --git a/robot-loader/tr/@home.texy b/robot-loader/tr/@home.texy index 67fd5162ed..4fde195cb7 100644 --- a/robot-loader/tr/@home.texy +++ b/robot-loader/tr/@home.texy @@ -24,7 +24,16 @@ require_once 'Utils/Paginator.php'; Kurulum .[#toc-installation] ---------------------------- -[Composer'ı |best-practices:composer] kullanarak paketi indirin ve yükleyin: +RobotLoader'ı `require` kullanarak komut [dosyanıza |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php] ekleyebileceğiniz [tek |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php] bir [bağımsız dosya `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php] olarak indirebilir ve hemen tüm uygulamanız için uygun otomatik yüklemeye sahip olabilirsiniz: + +```php +require '/path/to/RobotLoader.php'; + +$loader = new Nette\Loaders\RobotLoader; +// ... +``` + + [Composer |best-practices:composer] kullanan bir uygulama geliştiriyorsanız, [Composer |best-practices:composer] aracılığıyla yükleyebilirsiniz: ```shell composer require nette/robot-loader diff --git a/robot-loader/uk/@home.texy b/robot-loader/uk/@home.texy index 1e07799bcc..da2070658f 100644 --- a/robot-loader/uk/@home.texy +++ b/robot-loader/uk/@home.texy @@ -24,7 +24,16 @@ require_once 'Utils/Paginator.php'; Встановлення .[#toc-installation] --------------------------------- -Завантажте та встановіть пакунок за допомогою [Composer|best-practices:composer]: +Ви можете завантажити RobotLoader як [окремий файл `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], який ви можете включити в свій скрипт за допомогою `require`, і одразу ж мати зручне автозавантаження для всього вашого додатку: + +```php +require '/path/to/RobotLoader.php'; + +$loader = new Nette\Loaders\RobotLoader; +// ... +``` + +Якщо ви створюєте додаток, який використовує [Composer |best-practices:composer], ви можете встановити його через нього: ```shell composer require nette/robot-loader From 95f937e27b733373490e0914990c8f79f9bb2a93 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 27 Sep 2023 11:42:21 +0200 Subject: [PATCH 011/137] typo --- www/bg/10-reasons-why-nette.texy | 4 ++-- www/fr/10-reasons-why-nette.texy | 2 +- www/pt/10-reasons-why-nette.texy | 2 +- www/tr/10-reasons-why-nette.texy | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/www/bg/10-reasons-why-nette.texy b/www/bg/10-reasons-why-nette.texy index 76fa90b28c..22806ab98c 100644 --- a/www/bg/10-reasons-why-nette.texy +++ b/www/bg/10-reasons-why-nette.texy @@ -16,8 +16,8 @@ Nette внася комфорт и ефективност в света на уеб разработчиците чрез иновативни инструменти и техники. Кои са основните характеристики, които правят Nette уникална и съществена част от инструментариума на разработчика? Нека да разгледаме! -#№1 Nette ви глези ------------------- +#1 Nette ви глези +----------------- Когато преди двадесет години започна да се оформя рамката Nette, тя се въртеше около една единствена цел: Как да създаваме уебсайтове възможно най-удобно? Как да направим живота на програмистите възможно най-лесен? Как да направим уеб разработката секси? diff --git a/www/fr/10-reasons-why-nette.texy b/www/fr/10-reasons-why-nette.texy index 428ae08fa7..43a6208026 100644 --- a/www/fr/10-reasons-why-nette.texy +++ b/www/fr/10-reasons-why-nette.texy @@ -52,7 +52,7 @@ Avec Nette, vous construisez des pages à partir de composants d'interface utili Cette caractéristique unique distingue Nette de tous les autres acteurs importants du marché. Elle vous permet de créer et de maintenir efficacement des applications web. Avec Nette, travailler avec l'interface utilisateur devient une expérience fluide et agréable. -Ensemble de forfaits flexibles #5 +#5 Ensemble de forfaits flexibles --------------------------------- Nette est un ensemble de [paquets autonomes |www:packages]. Ils comprennent l'[outil de débogage Tracy |tracy:], le [système de templates Latte de nouvelle génération |latte:], l'[excellent conteneur d'injection de dépendances |dependency-injection:], des [formulaires |forms:], et bien d'autres choses encore. Chaque paquet a une documentation détaillée lisible et réside dans un dépôt séparé sur GitHub. diff --git a/www/pt/10-reasons-why-nette.texy b/www/pt/10-reasons-why-nette.texy index d4f10518e6..75a704b013 100644 --- a/www/pt/10-reasons-why-nette.texy +++ b/www/pt/10-reasons-why-nette.texy @@ -52,7 +52,7 @@ Com Nette, você constrói páginas a partir de componentes UI reutilizáveis. Esta característica única distingue a Nette de todos os outros players significativos no mercado. Ela permite criar e manter aplicações web de forma eficiente. Com Nette, trabalhar com a UI se torna uma experiência suave e agradável. -Conjunto de Pacotes Flexíveis #5 +#5 Conjunto de Pacotes Flexíveis -------------------------------- Nette é um conjunto de [pacotes autônomos |www:packages]. Eles incluem a [ferramenta |tracy:] viciante [de depuração Tracy |tracy:], o [sistema de última geração de modelos Latte |latte:], o [excelente Recipiente de Injeção de Dependência |dependency-injection:], [formulários |forms:] e muito mais. Cada pacote tem uma documentação detalhada legível e reside em um repositório separado no GitHub. diff --git a/www/tr/10-reasons-why-nette.texy b/www/tr/10-reasons-why-nette.texy index 404d140fff..6cfb0fef8b 100644 --- a/www/tr/10-reasons-why-nette.texy +++ b/www/tr/10-reasons-why-nette.texy @@ -34,7 +34,7 @@ Nette örnek olarak liderlik eder. İyi alışkanlıklar öğreten ve kanıtlanm Nette topluluğu, şu anda başarılı ve önemli projelerin arkasında olan bir dizi şahsiyeti yetiştirmiştir. Binlerce programcı için Nette, profesyonel gelişim yolunda bir akıl hocası haline geldi. Siz de katılın ve Nette'in kodunuzun ve uygulamalarınızın kalitesini nasıl olumlu yönde etkileyeceğini keşfedin. -#Uygulamalarınızın 3 Numaralı Güvenilir Koruyucusu +#3 Uygulamalarınızın Numaralı Güvenilir Koruyucusu -------------------------------------------------- Nette uygulamalarınızı korur. Yıllar içinde, güvenliği son derece ciddiye alan bir araç olarak ün kazanmıştır. Güvenlik açıklarına karşı ustaca koruma sağlayarak, geliştiricilerin güvenlikten ödün vermeden çalışmalarını her zaman kolaylaştırır. From cde7d29f4a07e296ac5d0b5d136129471416e601 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 27 Sep 2023 21:23:05 +0200 Subject: [PATCH 012/137] neon: improved syntax description --- neon/bg/format.texy | 30 ++++++++++++++++++++++++++---- neon/cs/format.texy | 30 ++++++++++++++++++++++++++---- neon/de/format.texy | 30 ++++++++++++++++++++++++++---- neon/el/format.texy | 30 ++++++++++++++++++++++++++---- neon/en/format.texy | 30 ++++++++++++++++++++++++++---- neon/es/format.texy | 30 ++++++++++++++++++++++++++---- neon/fr/format.texy | 30 ++++++++++++++++++++++++++---- neon/hu/format.texy | 30 ++++++++++++++++++++++++++---- neon/it/format.texy | 30 ++++++++++++++++++++++++++---- neon/pl/format.texy | 30 ++++++++++++++++++++++++++---- neon/pt/format.texy | 30 ++++++++++++++++++++++++++---- neon/ro/format.texy | 30 ++++++++++++++++++++++++++---- neon/ru/format.texy | 30 ++++++++++++++++++++++++++---- neon/sl/format.texy | 30 ++++++++++++++++++++++++++---- neon/tr/format.texy | 30 ++++++++++++++++++++++++++---- neon/uk/format.texy | 30 ++++++++++++++++++++++++++---- 16 files changed, 416 insertions(+), 64 deletions(-) diff --git a/neon/bg/format.texy b/neon/bg/format.texy index 912e802462..03c6593461 100644 --- a/neon/bg/format.texy +++ b/neon/bg/format.texy @@ -119,11 +119,11 @@ country: USA ```neon pets: - - Cat - - Dog + - Cat + - Dog cars: - - Volvo - - Skoda + - Volvo + - Skoda ``` В PHP същата структура ще бъде записана по следния начин: @@ -161,6 +161,28 @@ item: [ ] ``` +В предишния случай написахме съпоставяне, чиито елементи бяха последователности. Сега нека опитаме да направим обратния опит и да създадем последователност, съдържаща мапинг: + +```neon +- + name: John + age: 35 +- + name: Peter + age: 28 +``` + +Не е необходимо точките да са на отделни редове; те могат да бъдат разположени и по този начин: + +```neon +- name: John + age: 35 +- name: Peter + age: 28 +``` + +От вас зависи дали ще подравните булетите в колона, като използвате интервали или табулация. + Тъй като PHP използва една и съща структура за съпоставки и последователности, т.е. масиви, двете могат да се комбинират. Този път отстъпите са същите: ```neon diff --git a/neon/cs/format.texy b/neon/cs/format.texy index 3535dbe153..7012e69d60 100644 --- a/neon/cs/format.texy +++ b/neon/cs/format.texy @@ -119,11 +119,11 @@ Hodnotami mapování a sekvencí mohou být jiné mapování a sekvence. Hlavní ```neon pets: - - Cat - - Dog + - Cat + - Dog cars: - - Volvo - - Skoda + - Volvo + - Skoda ``` V PHP by se stejná struktura zapsala jako: @@ -161,6 +161,28 @@ item: [ ] ``` +V předchozím případě jsme zapsali mapovaní, jehož prvky byly sekvence, teď to zkusíme obráceně a vytvoříme sekvenci obsahující mapování: + +```neon +- + name: John + age: 35 +- + name: Peter + age: 28 +``` + +Není nutné, aby odrážky byly na samostatných řádcích, lze je umístit i tímto způsobem: + +```neon +- name: John + age: 35 +- name: Peter + age: 28 +``` + +Je na vás, jestli klíče zarovnáte do sloupce pomocí mezer nebo použijete tabulátor. + Protože v PHP se používá pro mapování i sekvence stejná struktura, tedy pole, lze obojí sloučit. Odsazení je tentokrát stejné: ```neon diff --git a/neon/de/format.texy b/neon/de/format.texy index c3898cf997..f741101004 100644 --- a/neon/de/format.texy +++ b/neon/de/format.texy @@ -119,11 +119,11 @@ Werte von Mappings und Sequenzen können andere Mappings und Sequenzen sein. Der ```neon pets: - - Cat - - Dog + - Cat + - Dog cars: - - Volvo - - Skoda + - Volvo + - Skoda ``` In PHP würde die gleiche Struktur wie folgt geschrieben werden: @@ -161,6 +161,28 @@ item: [ ] ``` +Im vorherigen Fall haben wir eine Abbildung geschrieben, deren Elemente Sequenzen waren. Versuchen wir es nun andersherum und erstellen eine Sequenz, die Mappings enthält: + +```neon +- + name: John + age: 35 +- + name: Peter + age: 28 +``` + +Die Aufzählungspunkte müssen nicht unbedingt in separaten Zeilen stehen, sondern können auch auf diese Weise platziert werden: + +```neon +- name: John + age: 35 +- name: Peter + age: 28 +``` + +Es bleibt Ihnen überlassen, ob Sie die Tasten in einer Spalte mit Leerzeichen oder mit einem Tabulator ausrichten. + Da PHP die gleiche Struktur für Mapping und Sequenzen verwendet, nämlich Arrays, können beide zusammengeführt werden. Die Einrückung ist dieses Mal die gleiche: ```neon diff --git a/neon/el/format.texy b/neon/el/format.texy index bf28f3a1d0..4c80868abc 100644 --- a/neon/el/format.texy +++ b/neon/el/format.texy @@ -119,11 +119,11 @@ country: USA ```neon pets: - - Cat - - Dog + - Cat + - Dog cars: - - Volvo - - Skoda + - Volvo + - Skoda ``` Στην PHP, η ίδια δομή θα γραφόταν ως εξής: @@ -161,6 +161,28 @@ item: [ ] ``` +Στην προηγούμενη περίπτωση, γράψαμε μια απεικόνιση της οποίας τα στοιχεία ήταν ακολουθίες. Τώρα, ας δοκιμάσουμε το αντίστροφο και ας δημιουργήσουμε μια ακολουθία που περιέχει απεικονίσεις: + +```neon +- + name: John + age: 35 +- + name: Peter + age: 28 +``` + +Δεν είναι απαραίτητο τα κουκκίδες να βρίσκονται σε ξεχωριστές γραμμές- μπορούν επίσης να τοποθετηθούν με αυτόν τον τρόπο: + +```neon +- name: John + age: 35 +- name: Peter + age: 28 +``` + +Εξαρτάται από εσάς αν θα ευθυγραμμίσετε τα πλήκτρα σε μια στήλη χρησιμοποιώντας διαστήματα ή ένα tab. + Επειδή η PHP χρησιμοποιεί την ίδια δομή για την αντιστοίχιση και τις ακολουθίες, δηλαδή πίνακες, και οι δύο μπορούν να συγχωνευθούν. Η εσοχή είναι η ίδια αυτή τη φορά: ```neon diff --git a/neon/en/format.texy b/neon/en/format.texy index ec4a3d6a7d..45c9289b34 100644 --- a/neon/en/format.texy +++ b/neon/en/format.texy @@ -119,11 +119,11 @@ Values of mappings and sequences may be other mappings and sequences. The level ```neon pets: - - Cat - - Dog + - Cat + - Dog cars: - - Volvo - - Skoda + - Volvo + - Skoda ``` In PHP, the same structure would be written as: @@ -161,6 +161,28 @@ item: [ ] ``` +In the previous case, we wrote a mapping whose elements were sequences. Now, let's try it the other way around and create a sequence containing mappings: + +```neon +- + name: John + age: 35 +- + name: Peter + age: 28 +``` + +It's not necessary for the bullet points to be on separate lines; they can also be placed in this manner: + +```neon +- name: John + age: 35 +- name: Peter + age: 28 +``` + +It's up to you whether you align the keys in a column using spaces or a tab. + Because PHP uses the same structure for mapping and sequences, that is, arrays, both can be merged. The indentation is the same this time: ```neon diff --git a/neon/es/format.texy b/neon/es/format.texy index 3ba10dd7f1..cdc695c92a 100644 --- a/neon/es/format.texy +++ b/neon/es/format.texy @@ -119,11 +119,11 @@ Los valores de las correspondencias y secuencias pueden ser otras correspondenci ```neon pets: - - Cat - - Dog + - Cat + - Dog cars: - - Volvo - - Skoda + - Volvo + - Skoda ``` En PHP, la misma estructura se escribiría como: @@ -161,6 +161,28 @@ item: [ ] ``` +En el caso anterior, escribimos un mapeo cuyos elementos eran secuencias. Ahora, intentémoslo al revés y creemos una secuencia que contenga mapeos: + +```neon +- + name: John + age: 35 +- + name: Peter + age: 28 +``` + +No es necesario que las viñetas estén en líneas separadas; también pueden colocarse así: + +```neon +- name: John + age: 35 +- name: Peter + age: 28 +``` + +Depende de ti si alineas las viñetas en una columna utilizando espacios o un tabulador. + Debido a que PHP utiliza la misma estructura para mapeo y secuencias, es decir, arrays, ambos pueden ser fusionados. La indentación es la misma esta vez: ```neon diff --git a/neon/fr/format.texy b/neon/fr/format.texy index 4d1d55c829..c6ffac6484 100644 --- a/neon/fr/format.texy +++ b/neon/fr/format.texy @@ -119,11 +119,11 @@ Les valeurs des mappings et des séquences peuvent être d'autres mappings et s ```neon pets: - - Cat - - Dog + - Cat + - Dog cars: - - Volvo - - Skoda + - Volvo + - Skoda ``` En PHP, la même structure s'écrirait comme suit : @@ -161,6 +161,28 @@ item: [ ] ``` +Dans le cas précédent, nous avons écrit un mapping dont les éléments étaient des séquences. Essayons maintenant l'inverse et créons une séquence contenant des mappings : + +```neon +- + name: John + age: 35 +- + name: Peter + age: 28 +``` + +Il n'est pas nécessaire que les puces soient sur des lignes séparées ; elles peuvent également être placées de cette manière : + +```neon +- name: John + age: 35 +- name: Peter + age: 28 +``` + +Il vous appartient d'aligner les clés dans une colonne en utilisant des espaces ou une tabulation. + Parce que PHP utilise la même structure pour le mapping et les séquences, c'est-à-dire les tableaux, les deux peuvent être fusionnés. L'indentation est la même cette fois : ```neon diff --git a/neon/hu/format.texy b/neon/hu/format.texy index ee01eb5fea..a220212f7d 100644 --- a/neon/hu/format.texy +++ b/neon/hu/format.texy @@ -119,11 +119,11 @@ A leképezések és szekvenciák értékei lehetnek más leképezések és szekv ```neon pets: - - Cat - - Dog + - Cat + - Dog cars: - - Volvo - - Skoda + - Volvo + - Skoda ``` PHP-ben ugyanezt a struktúrát így írnánk le: @@ -161,6 +161,28 @@ item: [ ] ``` +Az előző esetben egy olyan leképezést írtunk, amelynek elemei szekvenciák voltak. Most próbáljuk meg fordítva, és hozzunk létre egy leképezéseket tartalmazó szekvenciát: + +```neon +- + name: John + age: 35 +- + name: Peter + age: 28 +``` + +Nem szükséges, hogy a felsoroláspontok külön sorokban legyenek; így is elhelyezhetjük őket: + +```neon +- name: John + age: 35 +- name: Peter + age: 28 +``` + +Öntől függ, hogy a kulcsokat szóközökkel vagy tabulátorral igazítja-e egy oszlopba. + Mivel a PHP ugyanazt a struktúrát használja a leképezéshez és a szekvenciákhoz, azaz a tömböket, mindkettő összevonható. A behúzás ezúttal is ugyanaz: ```neon diff --git a/neon/it/format.texy b/neon/it/format.texy index 20b2520538..7ccb465f5d 100644 --- a/neon/it/format.texy +++ b/neon/it/format.texy @@ -119,11 +119,11 @@ I valori delle mappature e delle sequenze possono essere altre mappature e seque ```neon pets: - - Cat - - Dog + - Cat + - Dog cars: - - Volvo - - Skoda + - Volvo + - Skoda ``` In PHP, la stessa struttura sarebbe scritta come: @@ -161,6 +161,28 @@ item: [ ] ``` +Nel caso precedente, abbiamo scritto una mappatura i cui elementi erano sequenze. Proviamo ora a fare il contrario e a creare una sequenza contenente delle mappature: + +```neon +- + name: John + age: 35 +- + name: Peter + age: 28 +``` + +Non è necessario che i punti elenco siano su righe separate; possono anche essere disposti in questo modo: + +```neon +- name: John + age: 35 +- name: Peter + age: 28 +``` + +Sta a voi decidere se allineare i tasti in una colonna usando spazi o tabulazioni. + Poiché PHP utilizza la stessa struttura per le mappature e le sequenze, cioè gli array, entrambi possono essere uniti. L'indentazione è la stessa questa volta: ```neon diff --git a/neon/pl/format.texy b/neon/pl/format.texy index dbb95707bd..1a0f8173b6 100644 --- a/neon/pl/format.texy +++ b/neon/pl/format.texy @@ -119,11 +119,11 @@ Wartości mapowania i sekwencji mogą być innymi mapowaniami i sekwencjami. Du ```neon pets: - - Cat - - Dog + - Cat + - Dog cars: - - Volvo - - Skoda + - Volvo + - Skoda ``` W PHP ta sama struktura zostałaby zapisana jako: @@ -161,6 +161,28 @@ item: [ ] ``` +W poprzednim przypadku napisaliśmy mapowanie, którego elementami były sekwencje. Teraz spróbujmy zrobić to na odwrót i stworzyć sekwencję zawierającą mapowania: + +```neon +- + name: John + age: 35 +- + name: Peter + age: 28 +``` + +Nie jest konieczne, aby wypunktowania znajdowały się w osobnych wierszach; można je również umieścić w ten sposób: + +```neon +- name: John + age: 35 +- name: Peter + age: 28 +``` + +Od Ciebie zależy, czy wyrównasz klawisze w kolumnie za pomocą spacji czy tabulatora. + Ponieważ PHP używa tej samej struktury dla mapowania i sekwencji, czyli tablic, można je połączyć. Tym razem wcięcie jest takie samo: ```neon diff --git a/neon/pt/format.texy b/neon/pt/format.texy index 62568cf71f..38a5cd832b 100644 --- a/neon/pt/format.texy +++ b/neon/pt/format.texy @@ -119,11 +119,11 @@ Os valores de mapeamentos e seqüências podem ser outros mapeamentos e seqüên ```neon pets: - - Cat - - Dog + - Cat + - Dog cars: - - Volvo - - Skoda + - Volvo + - Skoda ``` Em PHP, a mesma estrutura seria escrita como: @@ -161,6 +161,28 @@ item: [ ] ``` +No caso anterior, escrevemos um mapeamento cujos elementos eram sequências. Agora, vamos tentar o contrário e criar uma sequência contendo mapeamentos: + +```neon +- + name: John + age: 35 +- + name: Peter + age: 28 +``` + +Não é necessário que os marcadores estejam em linhas separadas; eles também podem ser colocados dessa maneira: + +```neon +- name: John + age: 35 +- name: Peter + age: 28 +``` + +Fica a seu critério alinhar as chaves em uma coluna usando espaços ou tabulação. + Porque PHP usa a mesma estrutura para mapeamento e seqüências, ou seja, arrays, ambos podem ser fundidos. A indentação é a mesma desta vez: ```neon diff --git a/neon/ro/format.texy b/neon/ro/format.texy index b04a4462a6..1bfdfea3d4 100644 --- a/neon/ro/format.texy +++ b/neon/ro/format.texy @@ -119,11 +119,11 @@ Valorile maparelor și secvențelor pot fi alte mape și secvențe. Nivelul de i ```neon pets: - - Cat - - Dog + - Cat + - Dog cars: - - Volvo - - Skoda + - Volvo + - Skoda ``` În PHP, aceeași structură ar fi scrisă astfel:: @@ -161,6 +161,28 @@ item: [ ] ``` +În cazul anterior, am scris o hartă ale cărei elemente erau secvențe. Acum, să încercăm invers și să creăm o secvență care să conțină mapare: + +```neon +- + name: John + age: 35 +- + name: Peter + age: 28 +``` + +Nu este necesar ca punctele să fie pe linii separate; ele pot fi plasate și în acest mod: + +```neon +- name: John + age: 35 +- name: Peter + age: 28 +``` + +Depinde de dvs. dacă aliniați cheile într-o coloană folosind spații sau o tabulație. + Deoarece PHP utilizează aceeași structură pentru cartografiere și secvențe, adică array-uri, ambele pot fi îmbinate. Indentarea este aceeași de această dată: ```neon diff --git a/neon/ru/format.texy b/neon/ru/format.texy index fd87a2c992..82e51b2c1d 100644 --- a/neon/ru/format.texy +++ b/neon/ru/format.texy @@ -119,11 +119,11 @@ country: USA ```neon pets: - - Cat - - Dog + - Cat + - Dog cars: - - Volvo - - Skoda + - Volvo + - Skoda ``` В PHP та же структура была бы записана как: @@ -161,6 +161,28 @@ item: [ ] ``` +В предыдущем случае мы написали отображение, элементами которого были последовательности. Теперь попробуем сделать все наоборот и создать последовательность, содержащую отображения: + +```neon +- + name: John + age: 35 +- + name: Peter + age: 28 +``` + +Не обязательно, чтобы пункты были расположены на отдельных строках, их можно расположить и таким образом: + +```neon +- name: John + age: 35 +- name: Peter + age: 28 +``` + +Выравнивать ли ключи в колонке с помощью пробелов или табуляции - решать вам. + Поскольку PHP использует одну и ту же структуру для отображения и последовательностей, то есть массивы, оба варианта могут быть объединены. На этот раз отступы одинаковы: ```neon diff --git a/neon/sl/format.texy b/neon/sl/format.texy index 554940cd92..0ed6f8f8c4 100644 --- a/neon/sl/format.texy +++ b/neon/sl/format.texy @@ -119,11 +119,11 @@ Vrednosti preslikav in zaporedij so lahko druge preslikave in zaporedja. Pomembn ```neon pets: - - Cat - - Dog + - Cat + - Dog cars: - - Volvo - - Skoda + - Volvo + - Skoda ``` V jeziku PHP bi bila ista struktura zapisana kot: @@ -161,6 +161,28 @@ item: [ ] ``` +V prejšnjem primeru smo zapisali preslikavo, katere elementi so bila zaporedja. Zdaj poskusimo obratno in ustvarimo zaporedje, ki vsebuje preslikave: + +```neon +- + name: John + age: 35 +- + name: Peter + age: 28 +``` + +Ni nujno, da so točke na ločenih vrsticah; lahko jih postavimo tudi na ta način: + +```neon +- name: John + age: 35 +- name: Peter + age: 28 +``` + +Od vas je odvisno, ali jih boste v stolpcu poravnali s presledki ali tabulatorjem. + Ker PHP uporablja enako strukturo za preslikave in zaporedja, tj. polja, je mogoče oboje združiti. Vstavljanje je tokrat enako: ```neon diff --git a/neon/tr/format.texy b/neon/tr/format.texy index 838533b0d5..d8a808509d 100644 --- a/neon/tr/format.texy +++ b/neon/tr/format.texy @@ -119,11 +119,11 @@ Eşlemelerin ve dizilerin değerleri başka eşlemeler ve diziler olabilir. Giri ```neon pets: - - Cat - - Dog + - Cat + - Dog cars: - - Volvo - - Skoda + - Volvo + - Skoda ``` PHP'de aynı yapı şu şekilde yazılacaktır: @@ -161,6 +161,28 @@ item: [ ] ``` +Önceki durumda, elemanları diziler olan bir eşleme yazmıştık. Şimdi de tam tersini deneyelim ve eşlemeleri içeren bir dizi oluşturalım: + +```neon +- + name: John + age: 35 +- + name: Peter + age: 28 +``` + +Madde işaretlerinin ayrı satırlarda olması gerekli değildir; bu şekilde de yerleştirilebilirler: + +```neon +- name: John + age: 35 +- name: Peter + age: 28 +``` + +Bir sütundaki tuşları boşluk veya sekme kullanarak hizalayıp hizalamayacağınız size bağlıdır. + PHP eşleme ve diziler için aynı yapıyı, yani dizileri kullandığından, her ikisi de birleştirilebilir. Girintileme bu sefer aynıdır: ```neon diff --git a/neon/uk/format.texy b/neon/uk/format.texy index 000d5c051a..046bd099a2 100644 --- a/neon/uk/format.texy +++ b/neon/uk/format.texy @@ -119,11 +119,11 @@ country: USA ```neon pets: - - Cat - - Dog + - Cat + - Dog cars: - - Volvo - - Skoda + - Volvo + - Skoda ``` У PHP та сама структура була б записана як: @@ -161,6 +161,28 @@ item: [ ] ``` +У попередньому випадку ми написали відображення, елементами якого були послідовності. Тепер давайте спробуємо зробити навпаки і створимо послідовність, що містить відображення: + +```neon +- + name: John + age: 35 +- + name: Peter + age: 28 +``` + +Не обов'язково, щоб маркери були на окремих рядках, їх можна розмістити і таким чином: + +```neon +- name: John + age: 35 +- name: Peter + age: 28 +``` + +Ви самі вирішуєте, як вирівнювати ключі в стовпчику - за допомогою пробілів чи табуляції. + Оскільки PHP використовує одну й ту саму структуру для відображення і послідовностей, тобто масиви, обидва варіанти можуть бути об'єднані. Цього разу відступи однакові: ```neon From 9646248580dc601faf119eeac910b87a42975140 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 27 Sep 2023 23:42:32 +0200 Subject: [PATCH 013/137] di: neon syntax improvements --- dependency-injection/bg/configuration.texy | 17 ++++++----------- .../bg/passing-dependencies.texy | 6 ++---- dependency-injection/bg/services.texy | 8 ++++---- dependency-injection/cs/configuration.texy | 17 ++++++----------- .../cs/passing-dependencies.texy | 6 ++---- dependency-injection/cs/services.texy | 8 ++++---- dependency-injection/de/configuration.texy | 17 ++++++----------- .../de/passing-dependencies.texy | 6 ++---- dependency-injection/de/services.texy | 8 ++++---- dependency-injection/el/configuration.texy | 17 ++++++----------- .../el/passing-dependencies.texy | 6 ++---- dependency-injection/el/services.texy | 8 ++++---- dependency-injection/en/configuration.texy | 17 ++++++----------- .../en/passing-dependencies.texy | 6 ++---- dependency-injection/en/services.texy | 8 ++++---- dependency-injection/es/configuration.texy | 17 ++++++----------- .../es/passing-dependencies.texy | 6 ++---- dependency-injection/es/services.texy | 8 ++++---- dependency-injection/fr/configuration.texy | 17 ++++++----------- .../fr/passing-dependencies.texy | 6 ++---- dependency-injection/fr/services.texy | 8 ++++---- dependency-injection/hu/configuration.texy | 17 ++++++----------- .../hu/passing-dependencies.texy | 6 ++---- dependency-injection/hu/services.texy | 8 ++++---- dependency-injection/it/configuration.texy | 17 ++++++----------- .../it/passing-dependencies.texy | 6 ++---- dependency-injection/it/services.texy | 8 ++++---- dependency-injection/ja/configuration.texy | 17 ++++++----------- .../ja/passing-dependencies.texy | 6 ++---- dependency-injection/ja/services.texy | 8 ++++---- dependency-injection/pl/configuration.texy | 17 ++++++----------- .../pl/passing-dependencies.texy | 6 ++---- dependency-injection/pl/services.texy | 8 ++++---- dependency-injection/pt/configuration.texy | 17 ++++++----------- .../pt/passing-dependencies.texy | 6 ++---- dependency-injection/pt/services.texy | 8 ++++---- dependency-injection/ro/configuration.texy | 17 ++++++----------- .../ro/passing-dependencies.texy | 6 ++---- dependency-injection/ro/services.texy | 8 ++++---- dependency-injection/ru/configuration.texy | 17 ++++++----------- .../ru/passing-dependencies.texy | 6 ++---- dependency-injection/ru/services.texy | 8 ++++---- dependency-injection/sl/configuration.texy | 17 ++++++----------- .../sl/passing-dependencies.texy | 6 ++---- dependency-injection/sl/services.texy | 8 ++++---- dependency-injection/tr/configuration.texy | 17 ++++++----------- .../tr/passing-dependencies.texy | 6 ++---- dependency-injection/tr/services.texy | 8 ++++---- dependency-injection/uk/configuration.texy | 17 ++++++----------- .../uk/passing-dependencies.texy | 6 ++---- dependency-injection/uk/services.texy | 8 ++++---- 51 files changed, 204 insertions(+), 323 deletions(-) diff --git a/dependency-injection/bg/configuration.texy b/dependency-injection/bg/configuration.texy index d90b41c6b4..583f748030 100644 --- a/dependency-injection/bg/configuration.texy +++ b/dependency-injection/bg/configuration.texy @@ -191,20 +191,15 @@ return [ ```neon търсене: - # избирате собствени имена на раздели - myForms: - in: %appDir%/Forms - - model: - in: %appDir%/Model + - in: %appDir%/Forms + - in: %appDir%/Model ``` Обикновено обаче не искаме да добавяме всички класове и интерфейси, затова можем да ги филтрираме: ```neon търсене: - myForms: - in: %appDir%/Forms + - in: %appDir%/Forms # филтриране по име на файл (string|string[]) files: @@ -220,7 +215,7 @@ return [ ```neon search: - myForms: + - in: %appDir% extends: - App\*Form implements: @@ -231,7 +226,7 @@ search: ```neon search: - myForms: + - in: %appDir% exclude: classes: ... extends: ... @@ -242,7 +237,7 @@ search: ```neon search: - myForms: + - in: %appDir% tags: ... ``` diff --git a/dependency-injection/bg/passing-dependencies.texy b/dependency-injection/bg/passing-dependencies.texy index 079f493c12..d4761752a3 100644 --- a/dependency-injection/bg/passing-dependencies.texy +++ b/dependency-injection/bg/passing-dependencies.texy @@ -168,8 +168,7 @@ class MyClass ```neon services: - - - create: MyClass + - create: MyClass setup: - setCache ``` @@ -196,8 +195,7 @@ $obj->cache = $cache; ```neon services: - - - create: MyClass + - create: MyClass setup: - $cache = @\Cache ``` diff --git a/dependency-injection/bg/services.texy b/dependency-injection/bg/services.texy index 44bb7797e9..ad35504555 100644 --- a/dependency-injection/bg/services.texy +++ b/dependency-injection/bg/services.texy @@ -235,8 +235,8 @@ services: ```neon services: - - create: Foo(@database) - setup: + - create: Foo(@database) + setup: - setCacheStorage(@cache.storage) ``` @@ -255,8 +255,8 @@ public function createService01(): Foo ```neon services: - - create: Foo(@Nette\Database\Connection) # или @\PDO - setup: + - create: Foo(@Nette\Database\Connection) + setup: - setCacheStorage(@cache.storage) ``` diff --git a/dependency-injection/cs/configuration.texy b/dependency-injection/cs/configuration.texy index a42f461c3c..92061e1451 100644 --- a/dependency-injection/cs/configuration.texy +++ b/dependency-injection/cs/configuration.texy @@ -191,20 +191,15 @@ Stačí uvést, ve kterých adresářích (a podadresářích) má třídy hleda ```neon search: - # názvy sekcí si volíte sami - formuláře: - in: %appDir%/Forms - - model: - in: %appDir%/Model + - in: %appDir%/Forms + - in: %appDir%/Model ``` Obvykle ovšem nechceme přidávat úplně všechny třídy a rozhraní, proto je můžeme filtrovat: ```neon search: - formuláře: - in: %appDir%/Forms + - in: %appDir%/Forms # filtrování podle názvu souboru (string|string[]) files: @@ -220,7 +215,7 @@ Nebo můžeme vybírat třídy, které dědí či implementují alespoň jednu z ```neon search: - formuláře: + - in: %appDir% extends: - App\*Form implements: @@ -231,7 +226,7 @@ Lze definovat i vylučující pravidla, tj. masky názvu třídy nebo dědičné ```neon search: - formuláře: + - in: %appDir% exclude: classes: ... extends: ... @@ -242,7 +237,7 @@ Všem službám lze nastavit tagy: ```neon search: - formuláře: + - in: %appDir% tags: ... ``` diff --git a/dependency-injection/cs/passing-dependencies.texy b/dependency-injection/cs/passing-dependencies.texy index 433f999eb0..bb32928a73 100644 --- a/dependency-injection/cs/passing-dependencies.texy +++ b/dependency-injection/cs/passing-dependencies.texy @@ -168,8 +168,7 @@ Volání setteru definujeme v konfiguraci DI kontejneru v [klíči setup |servic ```neon services: - - - create: MyClass + - create: MyClass setup: - setCache ``` @@ -196,8 +195,7 @@ Nastavení proměnné definujeme v konfiraci DI kontejneru v [sekci setup |servi ```neon services: - - - create: MyClass + - create: MyClass setup: - $cache = @\Cache ``` diff --git a/dependency-injection/cs/services.texy b/dependency-injection/cs/services.texy index 52e3a357ea..2bb322dff7 100644 --- a/dependency-injection/cs/services.texy +++ b/dependency-injection/cs/services.texy @@ -235,8 +235,8 @@ Na jednotlivé služby se odkazuje pomocí zavináče a názvu služby, takže n ```neon services: - - create: Foo(@database) - setup: + - create: Foo(@database) + setup: - setCacheStorage(@cache.storage) ``` @@ -255,8 +255,8 @@ I na anonymní služby se lze odkazovat přes zavináč, jen místo názvu uvede ```neon services: - - create: Foo(@Nette\Database\Connection) # nebo třeba @\PDO - setup: + - create: Foo(@Nette\Database\Connection) + setup: - setCacheStorage(@cache.storage) ``` diff --git a/dependency-injection/de/configuration.texy b/dependency-injection/de/configuration.texy index 897d0a2df3..e4baef85bb 100644 --- a/dependency-injection/de/configuration.texy +++ b/dependency-injection/de/configuration.texy @@ -191,20 +191,15 @@ Geben Sie einfach an, in welchen Verzeichnissen (und Unterverzeichnissen) nach d ```neon Suche: - # Sie wählen die Namen der Abschnitte selbst - myForms: - in: %appDir%/Forms - - model: - in: %appDir%/Model + - in: %appDir%/Forms + - in: %appDir%/Model ``` Normalerweise wollen wir jedoch nicht alle Klassen und Schnittstellen hinzufügen, so dass wir sie filtern können: ```neon search: - myForms: - in: %appDir%/Forms + - in: %appDir%/Forms # Filtern nach Dateinamen (string|string[]) files: @@ -220,7 +215,7 @@ Oder wir können Klassen auswählen, die mindestens eine der folgenden Klassen e ```neon search: - myForms: + - in: %appDir% extends: - App\*Form implements: @@ -231,7 +226,7 @@ Sie können auch negative Regeln definieren, z. B. Klassennamensmasken oder Vorf ```neon search: - myForms: + - in: %appDir% exclude: classes: ... extends: ... @@ -242,7 +237,7 @@ Für hinzugefügte Dienste können Tags gesetzt werden: ```neon search: - myForms: + - in: %appDir% tags: ... ``` diff --git a/dependency-injection/de/passing-dependencies.texy b/dependency-injection/de/passing-dependencies.texy index c5111a38be..5ed4db6b6e 100644 --- a/dependency-injection/de/passing-dependencies.texy +++ b/dependency-injection/de/passing-dependencies.texy @@ -168,8 +168,7 @@ Der Setter-Aufruf wird in der DI-Container-Konfiguration im [Abschnitt setup |se ```neon services: - - - create: MyClass + - create: MyClass setup: - setCache ``` @@ -196,8 +195,7 @@ Die Einstellung der Variablen wird in der Konfiguration des DI-Containers im [Ab ```neon services: - - - create: MyClass + - create: MyClass setup: - $cache = @\Cache ``` diff --git a/dependency-injection/de/services.texy b/dependency-injection/de/services.texy index f4659b138d..466afd7d30 100644 --- a/dependency-injection/de/services.texy +++ b/dependency-injection/de/services.texy @@ -235,8 +235,8 @@ Die einzelnen Dienste werden mit dem Zeichen `@` and name, so for example `@data ```neon services: - - create: Foo(@database) - setup: + - create: Foo(@database) + setup: - setCacheStorage(@cache.storage) ``` @@ -255,8 +255,8 @@ Auch anonyme Dienste können über einen Callback referenziert werden, man muss ```neon services: - - create: Foo(@Nette\Database\Connection) # oder @\PDO - setup: + - create: Foo(@Nette\Database\Connection) + setup: - setCacheStorage(@cache.storage) ``` diff --git a/dependency-injection/el/configuration.texy b/dependency-injection/el/configuration.texy index c56264af03..f08eb9b714 100644 --- a/dependency-injection/el/configuration.texy +++ b/dependency-injection/el/configuration.texy @@ -191,20 +191,15 @@ return [ ```neon search: - # επιλέγετε μόνοι σας τα ονόματα των τμημάτων - myForms: - in: %appDir%/Forms - - model: - in: %appDir%/Model + - in: %appDir%/Forms + - in: %appDir%/Model ``` Συνήθως, όμως, δεν θέλουμε να προσθέσουμε όλες τις κλάσεις και τις διεπαφές, οπότε μπορούμε να τις φιλτράρουμε: ```neon search: - myForms: - in: %appDir%/Forms + - in: %appDir%/Forms # φιλτράρισμα με βάση το όνομα αρχείου (string|string[]) files: @@ -220,7 +215,7 @@ search: ```neon search: - myForms: + - in: %appDir% extends: - App\*Form implements: @@ -231,7 +226,7 @@ search: ```neon search: - myForms: + - in: %appDir% exclude: classes: ... extends: ... @@ -242,7 +237,7 @@ search: ```neon search: - myForms: + - in: %appDir% tags: ... ``` diff --git a/dependency-injection/el/passing-dependencies.texy b/dependency-injection/el/passing-dependencies.texy index 01698c8e6a..7d9171faaa 100644 --- a/dependency-injection/el/passing-dependencies.texy +++ b/dependency-injection/el/passing-dependencies.texy @@ -168,8 +168,7 @@ class MyClass ```neon services: - - - create: MyClass + - create: MyClass setup: - setCache ``` @@ -196,8 +195,7 @@ $obj->cache = $cache; ```neon services: - - - create: MyClass + - create: MyClass setup: - $cache = @\Cache ``` diff --git a/dependency-injection/el/services.texy b/dependency-injection/el/services.texy index f264fd21f6..88990590c5 100644 --- a/dependency-injection/el/services.texy +++ b/dependency-injection/el/services.texy @@ -235,8 +235,8 @@ services: ```neon services: - - create: Foo(@database) - setup: + - create: Foo(@database) + setup: - setCacheStorage(@cache.storage) ``` @@ -255,8 +255,8 @@ public function createService01(): Foo ```neon services: - - create: Foo(@Nette\Database\Connection) # ή @\PDO - setup: + - create: Foo(@Nette\Database\Connection) + setup: - setCacheStorage(@cache.storage) ``` diff --git a/dependency-injection/en/configuration.texy b/dependency-injection/en/configuration.texy index a43f9a653c..9a4e4893cb 100644 --- a/dependency-injection/en/configuration.texy +++ b/dependency-injection/en/configuration.texy @@ -191,20 +191,15 @@ Just specify in which directories (and subdirectories) the classes should be sea ```neon search: - # you choose the section names yourself - myForms: - in: %appDir%/Forms - - model: - in: %appDir%/Model + - in: %appDir%/Forms + - in: %appDir%/Model ``` Usually, however, we don't want to add all the classes and interfaces, so we can filter them: ```neon search: - myForms: - in: %appDir%/Forms + - in: %appDir%/Forms # filtering by file name (string|string[]) files: @@ -220,7 +215,7 @@ Or we can select classes that inherit or implement at least one of the following ```neon search: - myForms: + - in: %appDir% extends: - App\*Form implements: @@ -231,7 +226,7 @@ You can also define negative rules, ie class name masks or ancestors and if they ```neon search: - myForms: + - in: %appDir% exclude: classes: ... extends: ... @@ -242,7 +237,7 @@ Tags can be set for added services: ```neon search: - myForms: + - in: %appDir% tags: ... ``` diff --git a/dependency-injection/en/passing-dependencies.texy b/dependency-injection/en/passing-dependencies.texy index 43912611d4..afb5dea3dc 100644 --- a/dependency-injection/en/passing-dependencies.texy +++ b/dependency-injection/en/passing-dependencies.texy @@ -168,8 +168,7 @@ The setter call is defined in the DI container configuration in [section setup | ```neon services: - - - create: MyClass + - create: MyClass setup: - setCache ``` @@ -196,8 +195,7 @@ The setting of the variable is defined in the DI container configuration in [sec ```neon services: - - - create: MyClass + - create: MyClass setup: - $cache = @\Cache ``` diff --git a/dependency-injection/en/services.texy b/dependency-injection/en/services.texy index b0ba6e9eaa..ce393350eb 100644 --- a/dependency-injection/en/services.texy +++ b/dependency-injection/en/services.texy @@ -235,8 +235,8 @@ Individual services are referenced using character `@` and name, so for example ```neon services: - - create: Foo(@database) - setup: + - create: Foo(@database) + setup: - setCacheStorage(@cache.storage) ``` @@ -255,8 +255,8 @@ Even anonymous services can be referenced using a callback, just specify their t ```neon services: - - create: Foo(@Nette\Database\Connection) # or @\PDO - setup: + - create: Foo(@Nette\Database\Connection) + setup: - setCacheStorage(@cache.storage) ``` diff --git a/dependency-injection/es/configuration.texy b/dependency-injection/es/configuration.texy index 5dcfe64475..a952ee9bc5 100644 --- a/dependency-injection/es/configuration.texy +++ b/dependency-injection/es/configuration.texy @@ -191,20 +191,15 @@ Basta con especificar en qué directorios (y subdirectorios) deben buscarse las ```neon search: - # usted mismo elige los nombres de las secciones - myForms: - in: %appDir%/Forms - - model: - in: %appDir%/Model + - in: %appDir%/Forms + - in: %appDir%/Model ``` Normalmente, sin embargo, no queremos añadir todas las clases e interfaces, así que podemos filtrarlas: ```neon search: - myForms: - in: %appDir%/Forms + - in: %appDir%/Forms # filtrado por nombre de archivo (string|string[]) files: @@ -220,7 +215,7 @@ O podemos seleccionar clases que hereden o implementen al menos una de las sigui ```neon search: - myForms: + - in: %appDir% extends: - App\*Form implements: @@ -231,7 +226,7 @@ También se pueden definir reglas negativas, es decir, máscaras de nombres de c ```neon search: - myForms: + - in: %appDir% exclude: classes: ... extends: ... @@ -242,7 +237,7 @@ Se pueden establecer etiquetas para los servicios añadidos: ```neon search: - myForms: + - in: %appDir% tags: ... ``` diff --git a/dependency-injection/es/passing-dependencies.texy b/dependency-injection/es/passing-dependencies.texy index 05588ddfdc..8c80722dc9 100644 --- a/dependency-injection/es/passing-dependencies.texy +++ b/dependency-injection/es/passing-dependencies.texy @@ -168,8 +168,7 @@ La llamada al setter se define en la configuración del contenedor DI en [secci ```neon services: - - - create: MyClass + - create: MyClass setup: - setCache ``` @@ -196,8 +195,7 @@ La configuración de la variable se define en la configuración del contenedor D ```neon services: - - - create: MyClass + - create: MyClass setup: - $cache = @\Cache ``` diff --git a/dependency-injection/es/services.texy b/dependency-injection/es/services.texy index 2f6af40b80..4c971094e4 100644 --- a/dependency-injection/es/services.texy +++ b/dependency-injection/es/services.texy @@ -235,8 +235,8 @@ Los servicios individuales se referencian utilizando el carácter `@` y el nombr ```neon services: - - create: Foo(@database) - setup: + - create: Foo(@database) + setup: - setCacheStorage(@cache.storage) ``` @@ -255,8 +255,8 @@ Incluso los servicios anónimos pueden ser referenciados usando una llamada de r ```neon services: - - create: Foo(@Nette\Database\Connection) # or @\PDO - setup: + - create: Foo(@Nette\Database\Connection) + setup: - setCacheStorage(@cache.storage) ``` diff --git a/dependency-injection/fr/configuration.texy b/dependency-injection/fr/configuration.texy index 0a423fb41b..af47fe7a52 100644 --- a/dependency-injection/fr/configuration.texy +++ b/dependency-injection/fr/configuration.texy @@ -191,20 +191,15 @@ Il suffit de préciser dans quels répertoires (et sous-répertoires) les classe ```neon recherche: - # vous choisissez vous-même les noms des sections - mesFormulaires: - in: %appDir%/Forms - - modèle: - in: %appDir%/Model + - in: %appDir%/Forms + - in: %appDir%/Model ``` En général, cependant, nous ne voulons pas ajouter toutes les classes et interfaces, nous pouvons donc les filtrer : ```neon recherche: - mesFormulaires: - in: %appDir%/Forms + - in: %appDir%/Forms # filtrer par nom de fichier (string|string[]) files: @@ -220,7 +215,7 @@ Ou nous pouvons sélectionner les classes qui héritent ou implémentent au moin ```neon search: - myForms: + - in: %appDir% extends: - App\*Form implements: @@ -231,7 +226,7 @@ Vous pouvez également définir des règles négatives, c'est-à-dire des masque ```neon search: - myForms: + - in: %appDir% exclude: classes: ... extends: ... @@ -242,7 +237,7 @@ Des étiquettes peuvent être définies pour les services ajoutés : ```neon search: - myForms: + - in: %appDir% tags: ... ``` diff --git a/dependency-injection/fr/passing-dependencies.texy b/dependency-injection/fr/passing-dependencies.texy index 67f2ea3138..72726f495d 100644 --- a/dependency-injection/fr/passing-dependencies.texy +++ b/dependency-injection/fr/passing-dependencies.texy @@ -168,8 +168,7 @@ L'appel au setter est défini dans la configuration du conteneur DI dans la [sec ```neon services: - - - create: MyClass + - create: MyClass setup: - setCache ``` @@ -196,8 +195,7 @@ Le paramétrage de la variable est défini dans la configuration du conteneur DI ```neon services: - - - create: MyClass + - create: MyClass setup: - $cache = @\Cache ``` diff --git a/dependency-injection/fr/services.texy b/dependency-injection/fr/services.texy index 95f152a65b..d4bd5296c3 100644 --- a/dependency-injection/fr/services.texy +++ b/dependency-injection/fr/services.texy @@ -235,8 +235,8 @@ Les services individuels sont référencés à l'aide du caractère `@` and name ```neon services: - - create: Foo(@database) - setup: + - create: Foo(@database) + setup: - setCacheStorage(@cache.storage) ``` @@ -255,8 +255,8 @@ Même les services anonymes peuvent être référencés à l'aide d'un callback, ```neon services: - - create: Foo(@Nette\Database\Connection) # ou @\PDO - setup: + - create: Foo(@Nette\Database\Connection) + setup: - setCacheStorage(@cache.storage) ``` diff --git a/dependency-injection/hu/configuration.texy b/dependency-injection/hu/configuration.texy index 1563ee5bf8..63f920f291 100644 --- a/dependency-injection/hu/configuration.texy +++ b/dependency-injection/hu/configuration.texy @@ -191,20 +191,15 @@ Csak adjuk meg, hogy mely könyvtárakban (és alkönyvtárakban) kell keresni a ```neon search: - # te magad választod ki a szekciók nevét - myForms: - in: %appDir%/Forms - - model: - in: %appDir%/Model + - in: %appDir%/Forms + - in: %appDir%/Model ``` Általában azonban nem akarjuk az összes osztályt és interfészt felvenni, így szűrhetjük őket: ```neon search: - myForms: - in: %appDir%/Forms + - in: %appDir%/Forms # szűrés fájlnév alapján (string|string[]) files: @@ -220,7 +215,7 @@ Vagy kiválaszthatjuk azokat az osztályokat, amelyek a következő osztályok k ```neon search: - myForms: + - in: %appDir% extends: - App\*Form implements: @@ -231,7 +226,7 @@ Meghatározhatunk negatív szabályokat is, azaz osztálynév maszkokat vagy ős ```neon search: - myForms: + - in: %appDir% exclude: classes: ... extends: ... @@ -242,7 +237,7 @@ A hozzáadott szolgáltatásokhoz címkéket lehet beállítani: ```neon search: - myForms: + - in: %appDir% tags: ... ``` diff --git a/dependency-injection/hu/passing-dependencies.texy b/dependency-injection/hu/passing-dependencies.texy index a426543d32..924341e21f 100644 --- a/dependency-injection/hu/passing-dependencies.texy +++ b/dependency-injection/hu/passing-dependencies.texy @@ -168,8 +168,7 @@ A setter hívás a DI konténer konfigurációjában a [setup szakaszban |servic ```neon services: - - - create: MyClass + - create: MyClass setup: - setCache ``` @@ -196,8 +195,7 @@ A változó beállítását a DI konténer konfigurációjában, a [setup szakas ```neon services: - - - create: MyClass + - create: MyClass setup: - $cache = @\Cache ``` diff --git a/dependency-injection/hu/services.texy b/dependency-injection/hu/services.texy index d1630dc19a..db1874d9fd 100644 --- a/dependency-injection/hu/services.texy +++ b/dependency-injection/hu/services.texy @@ -235,8 +235,8 @@ Az egyes szolgáltatásokra a `@` and name, so for example `@database` karaktere ```neon services: - - create: Foo(@database) - setup: + - create: Foo(@database) + setup: - setCacheStorage(@cache.storage) ``` @@ -255,8 +255,8 @@ A névtelen szolgáltatásokra is lehet hivatkozni visszahívással, csak a típ ```neon services: - - create: Foo(@Nette\Database\Connection) # or @\PDO - setup: + - create: Foo(@Nette\Database\Connection) + setup: - setCacheStorage(@cache.storage) ``` diff --git a/dependency-injection/it/configuration.texy b/dependency-injection/it/configuration.texy index 58a933c479..a4d17c7f7d 100644 --- a/dependency-injection/it/configuration.texy +++ b/dependency-injection/it/configuration.texy @@ -191,20 +191,15 @@ Basta specificare in quali directory (e sottodirectory) devono essere cercate le ```neon search: - # scegliete voi stessi i nomi delle sezioni - myForms: - in: %appDir%/Forms - - model: - in: %appDir%/Model + - in: %appDir%/Forms + - in: %appDir%/Model ``` Di solito, però, non vogliamo aggiungere tutte le classi e le interfacce, quindi possiamo filtrarle: ```neon search: - myForms: - in: %appDir%/Forms + - in: %appDir%/Forms # filtrare per nome di file (string|string[]) files: @@ -220,7 +215,7 @@ Oppure possiamo selezionare le classi che ereditano o implementano almeno una de ```neon search: - myForms: + - in: %appDir% extends: - App\*Form implements: @@ -231,7 +226,7 @@ Si possono anche definire regole negative, cioè maschere di nomi di classi o an ```neon search: - myForms: + - in: %appDir% exclude: classes: ... extends: ... @@ -242,7 +237,7 @@ I tag possono essere impostati per i servizi aggiunti: ```neon search: - myForms: + - in: %appDir% tags: ... ``` diff --git a/dependency-injection/it/passing-dependencies.texy b/dependency-injection/it/passing-dependencies.texy index bfd95ad60a..47f03a6686 100644 --- a/dependency-injection/it/passing-dependencies.texy +++ b/dependency-injection/it/passing-dependencies.texy @@ -168,8 +168,7 @@ La chiamata al setter è definita nella configurazione del contenitore DI, nella ```neon services: - - - create: MyClass + - create: MyClass setup: - setCache ``` @@ -196,8 +195,7 @@ L'impostazione della variabile è definita nella configurazione del contenitore ```neon services: - - - create: MyClass + - create: MyClass setup: - $cache = @\Cache ``` diff --git a/dependency-injection/it/services.texy b/dependency-injection/it/services.texy index d3b690fe82..4f16ef0548 100644 --- a/dependency-injection/it/services.texy +++ b/dependency-injection/it/services.texy @@ -235,8 +235,8 @@ I singoli servizi sono referenziati utilizzando il carattere `@` and name, so fo ```neon services: - - create: Foo(@database) - setup: + - create: Foo(@database) + setup: - setCacheStorage(@cache.storage) ``` @@ -255,8 +255,8 @@ Anche i servizi anonimi possono essere referenziati usando un callback, basta sp ```neon services: - - create: Foo(@Nette\Database\Connection) # or @\PDO - setup: + - create: Foo(@Nette\Database\Connection) + setup: - setCacheStorage(@cache.storage) ``` diff --git a/dependency-injection/ja/configuration.texy b/dependency-injection/ja/configuration.texy index 6da88d5eec..7bb044010c 100644 --- a/dependency-injection/ja/configuration.texy +++ b/dependency-injection/ja/configuration.texy @@ -191,20 +191,15 @@ DIコンテナにサービスを自動追加することで、非常に快適に ```neon search: - # you choose the section names yourself - myForms: - in: %appDir%/Forms - - model: - in: %appDir%/Model + - in: %appDir%/Forms + - in: %appDir%/Model ``` しかし、通常は、すべてのクラスとインターフェイスを追加したくないので、フィルタリングすることができます。 ```neon search: - myForms: - in: %appDir%/Forms + - in: %appDir%/Forms # filtering by file name (string|string[]) files: @@ -220,7 +215,7 @@ search: ```neon search: - myForms: + - in: %appDir% extends: - App\*Form implements: @@ -231,7 +226,7 @@ search: ```neon search: - myForms: + - in: %appDir% exclude: classes: ... extends: ... @@ -242,7 +237,7 @@ search: ```neon search: - myForms: + - in: %appDir% tags: ... ``` diff --git a/dependency-injection/ja/passing-dependencies.texy b/dependency-injection/ja/passing-dependencies.texy index 22d913aed6..df513946b2 100644 --- a/dependency-injection/ja/passing-dependencies.texy +++ b/dependency-injection/ja/passing-dependencies.texy @@ -168,8 +168,7 @@ setter の呼び出しは、DI コンテナの設定[セクション setup |serv ```neon services: - - - create: MyClass + - create: MyClass setup: - setCache ``` @@ -196,8 +195,7 @@ $obj->cache = $cache; ```neon services: - - - create: MyClass + - create: MyClass setup: - $cache = @\Cache ``` diff --git a/dependency-injection/ja/services.texy b/dependency-injection/ja/services.texy index f4b2054bee..5ea5de0182 100644 --- a/dependency-injection/ja/services.texy +++ b/dependency-injection/ja/services.texy @@ -235,8 +235,8 @@ services: ```neon services: - - create: Foo(@database) - setup: + - create: Foo(@database) + setup: - setCacheStorage(@cache.storage) ``` @@ -255,8 +255,8 @@ public function createService01(): Foo ```neon services: - - create: Foo(@Nette\Database\Connection) # or @\PDO - setup: + - create: Foo(@Nette\Database\Connection) + setup: - setCacheStorage(@cache.storage) ``` diff --git a/dependency-injection/pl/configuration.texy b/dependency-injection/pl/configuration.texy index 111cbc9e1e..e497fcd3b5 100644 --- a/dependency-injection/pl/configuration.texy +++ b/dependency-injection/pl/configuration.texy @@ -191,20 +191,15 @@ Wystarczy określić, w których katalogach (i podkatalogach) szukać klas: ```neon search: - # wybierasz nazwy sekcji - formy: - in: %appDir%/Forms - - model: - in: %appDir%/Model + - in: %appDir%/Forms + - in: %appDir%/Model ``` Zazwyczaj nie chcemy dodawać wszystkich klas i interfejsów, więc możemy je filtrować: ```neon search: - Formy: - in: %appDir%/Forms + - in: %appDir%/Forms # filter by filename (string|string[]) files: @@ -220,7 +215,7 @@ Możemy też wybrać klasy, które dziedziczą lub implementują przynajmniej je ```neon search: - formuláře: + - in: %appDir% extends: - App\*Form implements: @@ -231,7 +226,7 @@ Można również zdefiniować reguły wykluczenia, czyli maski nazw klas lub dzi ```neon search: - formuláře: + - in: %appDir% exclude: classes: ... extends: ... @@ -242,7 +237,7 @@ Wszystkie usługi mogą być oznakowane: ```neon search: - formuláře: + - in: %appDir% tags: ... ``` diff --git a/dependency-injection/pl/passing-dependencies.texy b/dependency-injection/pl/passing-dependencies.texy index d4e4656bd3..db5b61194a 100644 --- a/dependency-injection/pl/passing-dependencies.texy +++ b/dependency-injection/pl/passing-dependencies.texy @@ -168,8 +168,7 @@ Wywołanie setera jest zdefiniowane w konfiguracji kontenera DI w [sekcji |servi ```neon services: - - - create: MyClass + - create: MyClass setup: - setCache ``` @@ -196,8 +195,7 @@ Ustawienia zmiennej definiujemy w konfiguracji kontenera DI w [sekcji setup |ser ```neon services: - - - create: MyClass + - create: MyClass setup: - $cache = @\Cache ``` diff --git a/dependency-injection/pl/services.texy b/dependency-injection/pl/services.texy index d40aece53e..f38f1f389a 100644 --- a/dependency-injection/pl/services.texy +++ b/dependency-injection/pl/services.texy @@ -235,8 +235,8 @@ Do usług odwołujemy się za pomocą nazwy usługi i nazwy serwisu, więc na pr ```neon services: - - create: Foo(@database) - setup: + - create: Foo(@database) + setup: - setCacheStorage(@cache.storage) ``` @@ -255,8 +255,8 @@ Nawet anonimowe usługi mogą być przywoływane poprzez alias, wystarczy podać ```neon services: - - create: Foo(@Nette\Database\Connection) # nebo třeba @PDO. - setup: + - create: Foo(@Nette\Database\Connection) + setup: - setCacheStorage(@cache.storage) ``` diff --git a/dependency-injection/pt/configuration.texy b/dependency-injection/pt/configuration.texy index e81ca1b571..2c21c894db 100644 --- a/dependency-injection/pt/configuration.texy +++ b/dependency-injection/pt/configuration.texy @@ -191,20 +191,15 @@ Basta especificar em quais diretórios (e subdiretórios) as classes devem ser p ```neon search: - # você mesmo escolhe os nomes das seções - myForms: - em: %appDir%/Forms - - model: - em: %appDir%/Modelo + - in: %appDir%/Forms + - in: %appDir%/Model ``` Normalmente, porém, não queremos acrescentar todas as classes e interfaces, para que possamos filtrá-las: ```neon search: - myForms: - in: %appDir%/Forms + - in: %appDir%/Forms # filtragem por nome de arquivo (string|string[]) files: @@ -220,7 +215,7 @@ Ou podemos selecionar classes que herdam ou implementam pelo menos uma das segui ```neon search: - myForms: + - in: %appDir% extends: - App\*Form implements: @@ -231,7 +226,7 @@ Você também pode definir regras negativas, ou seja, máscaras de nome de class ```neon search: - myForms: + - in: %appDir% exclude: classes: ... extends: ... @@ -242,7 +237,7 @@ As etiquetas podem ser definidas para serviços adicionais: ```neon search: - myForms: + - in: %appDir% tags: ... ``` diff --git a/dependency-injection/pt/passing-dependencies.texy b/dependency-injection/pt/passing-dependencies.texy index a6b4434e8d..b1655bd3dc 100644 --- a/dependency-injection/pt/passing-dependencies.texy +++ b/dependency-injection/pt/passing-dependencies.texy @@ -168,8 +168,7 @@ A chamada do setter é definida na configuração do recipiente DI na [configura ```neon services: - - - create: MyClass + - create: MyClass setup: - setCache ``` @@ -196,8 +195,7 @@ A configuração da variável é definida na configuração do recipiente DI na ```neon services: - - - create: MyClass + - create: MyClass setup: - $cache = @\Cache ``` diff --git a/dependency-injection/pt/services.texy b/dependency-injection/pt/services.texy index d8f55bada1..654948c932 100644 --- a/dependency-injection/pt/services.texy +++ b/dependency-injection/pt/services.texy @@ -235,8 +235,8 @@ Os serviços individuais são referenciados usando o personagem `@` and name, so ```neon services: - - create: Foo(@database) - setup: + - create: Foo(@database) + setup: - setCacheStorage(@cache.storage) ``` @@ -255,8 +255,8 @@ Mesmo serviços anônimos podem ser referenciados usando uma chamada de retorno, ```neon services: - - create: Foo(@Nette\Database\Connection) # or @\PDO - setup: + - create: Foo(@Nette\Database\Connection) + setup: - setCacheStorage(@cache.storage) ``` diff --git a/dependency-injection/ro/configuration.texy b/dependency-injection/ro/configuration.texy index 3c0a3e410c..870d2ff9ba 100644 --- a/dependency-injection/ro/configuration.texy +++ b/dependency-injection/ro/configuration.texy @@ -191,20 +191,15 @@ Trebuie doar să specificați în ce directoare (și subdirectoare) trebuie cău ```neon search: - # alegeți singuri denumirile secțiunilor - myForms: - in: %appDir%/Forms - - model: - in: %appDir%/Model + - in: %appDir%/Forms + - in: %appDir%/Model ``` De obicei, însă, nu dorim să adăugăm toate clasele și interfețele, așa că le putem filtra: ```neon search: - myForms: - in: %appDir%/Forms + - in: %appDir%/Forms # filtrarea după numele fișierului (string|string[]) files: @@ -220,7 +215,7 @@ Sau putem selecta clasele care moștenesc sau implementează cel puțin una dint ```neon search: - myForms: + - in: %appDir% extends: - App\*Form implements: @@ -231,7 +226,7 @@ De asemenea, se pot defini reguli negative, adică măști de nume de clasă sau ```neon search: - myForms: + - in: %appDir% exclude: classes: ... extends: ... @@ -242,7 +237,7 @@ Se pot stabili etichete pentru serviciile adăugate: ```neon search: - myForms: + - in: %appDir% tags: ... ``` diff --git a/dependency-injection/ro/passing-dependencies.texy b/dependency-injection/ro/passing-dependencies.texy index 2437edaeb2..9c3d341285 100644 --- a/dependency-injection/ro/passing-dependencies.texy +++ b/dependency-injection/ro/passing-dependencies.texy @@ -168,8 +168,7 @@ Apelarea setterului este definită în configurația containerului DI în [secț ```neon services: - - - create: MyClass + - create: MyClass setup: - setCache ``` @@ -196,8 +195,7 @@ Setarea variabilei este definită în configurația containerului DI în [secți ```neon services: - - - create: MyClass + - create: MyClass setup: - $cache = @\Cache ``` diff --git a/dependency-injection/ro/services.texy b/dependency-injection/ro/services.texy index 162f918633..5651246252 100644 --- a/dependency-injection/ro/services.texy +++ b/dependency-injection/ro/services.texy @@ -235,8 +235,8 @@ Serviciile individuale sunt referite folosind caracterul `@` and name, so for ex ```neon services: - - create: Foo(@database) - setup: + - create: Foo(@database) + setup: - setCacheStorage(@cache.storage) ``` @@ -255,8 +255,8 @@ Chiar și serviciile anonime pot fi referite folosind un callback, trebuie doar ```neon services: - - create: Foo(@Nette\Database\Connection) # sau @\PDO - setup: + - create: Foo(@Nette\Database\Connection) + setup: - setCacheStorage(@cache.storage) ``` diff --git a/dependency-injection/ru/configuration.texy b/dependency-injection/ru/configuration.texy index a288072f02..3d552530aa 100644 --- a/dependency-injection/ru/configuration.texy +++ b/dependency-injection/ru/configuration.texy @@ -191,20 +191,15 @@ return [ ```neon search: - # вы сами выбираете названия секций - myForms: - in: %appDir%/Forms - - model: - in: %appDir%/Model + - in: %appDir%/Forms + - in: %appDir%/Model ``` Обычно, однако, мы не хотим добавлять все классы и интерфейсы, поэтому мы можем отфильтровать их: ```neon search: - myForms: - in: %appDir%/Forms + - in: %appDir%/Forms # фильтрация по имени файла (string|string[]) files: @@ -220,7 +215,7 @@ search: ```neon search: - myForms: + - in: %appDir% extends: - App\*Form implements: @@ -231,7 +226,7 @@ search: ```neon search: - myForms: + - in: %appDir% exclude: classes: ... extends: ... @@ -242,7 +237,7 @@ search: ```neon search: - myForms: + - in: %appDir% tags: ... ``` diff --git a/dependency-injection/ru/passing-dependencies.texy b/dependency-injection/ru/passing-dependencies.texy index 31202bcf86..ed13246974 100644 --- a/dependency-injection/ru/passing-dependencies.texy +++ b/dependency-injection/ru/passing-dependencies.texy @@ -168,8 +168,7 @@ The setter call is defined in the DI container configuration in [section setup | ```neon services: - - - create: MyClass + - create: MyClass setup: - setCache ``` @@ -196,8 +195,7 @@ $obj->cache = $cache; ```neon services: - - - create: MyClass + - create: MyClass setup: - $cache = @\Cache ``` diff --git a/dependency-injection/ru/services.texy b/dependency-injection/ru/services.texy index 3af9d1f2e7..5566611a0f 100644 --- a/dependency-injection/ru/services.texy +++ b/dependency-injection/ru/services.texy @@ -235,8 +235,8 @@ services: ```neon services: - - create: Foo(@database) - setup: + - create: Foo(@database) + setup: - setCacheStorage(@cache.storage) ``` @@ -255,8 +255,8 @@ public function createService01(): Foo ```neon services: - - create: Foo(@Nette\Database\Connection) # или @\PDO - setup: + - create: Foo(@Nette\Database\Connection) + setup: - setCacheStorage(@cache.storage) ``` diff --git a/dependency-injection/sl/configuration.texy b/dependency-injection/sl/configuration.texy index 66f22356d4..4ccc57cc4f 100644 --- a/dependency-injection/sl/configuration.texy +++ b/dependency-injection/sl/configuration.texy @@ -191,20 +191,15 @@ Samo določite, v katerih imenikih (in podimenikih) naj se razredi iščejo: ```neon search: - # imena razdelkov izberete sami. - myForms: - in: %appDir%/Forms - - model: - in: %appDir%/Model + - in: %appDir%/Forms + - in: %appDir%/Model ``` Običajno ne želimo dodati vseh razredov in vmesnikov, zato jih lahko filtriramo: ```neon search: - myForms: - in: %appDir%/Forms + - in: %appDir%/Forms # filtriranje po imenu datoteke (niz|recept[]) files: @@ -220,7 +215,7 @@ Lahko pa izberemo razrede, ki dedujejo ali implementirajo vsaj enega od naslednj ```neon search: - myForms: + - in: %appDir% extends: - App\*Form implements: @@ -231,7 +226,7 @@ Določite lahko tudi negativna pravila, tj. maske imen razredov ali prednikov, i ```neon search: - myForms: + - in: %appDir% exclude: classes: ... extends: ... @@ -242,7 +237,7 @@ Za dodane storitve lahko nastavite oznake: ```neon search: - myForms: + - in: %appDir% tags: ... ``` diff --git a/dependency-injection/sl/passing-dependencies.texy b/dependency-injection/sl/passing-dependencies.texy index 451f940105..88d40d5663 100644 --- a/dependency-injection/sl/passing-dependencies.texy +++ b/dependency-injection/sl/passing-dependencies.texy @@ -168,8 +168,7 @@ Klic setterja je opredeljen v konfiguraciji vsebnika DI v [razdelku setup |servi ```neon services: - - - create: MyClass + - create: MyClass setup: - setCache ``` @@ -196,8 +195,7 @@ Nastavitev spremenljivke je opredeljena v konfiguraciji vsebnika DI v [razdelku ```neon services: - - - create: MyClass + - create: MyClass setup: - $cache = @\Cache ``` diff --git a/dependency-injection/sl/services.texy b/dependency-injection/sl/services.texy index 854a61e05a..fa55afbb89 100644 --- a/dependency-injection/sl/services.texy +++ b/dependency-injection/sl/services.texy @@ -235,8 +235,8 @@ Na posamezne storitve se sklicujemo z uporabo znakov `@` and name, so for exampl ```neon services: - - create: Foo(@database) - setup: + - create: Foo(@database) + setup: - setCacheStorage(@cache.storage) ``` @@ -255,8 +255,8 @@ Tudi na anonimne storitve se lahko sklicujete s povratnim klicem, le namesto ime ```neon services: - - create: Foo(@Nette\Database\Connection) # ali @\PDO - setup: + - create: Foo(@Nette\Database\Connection) + setup: - setCacheStorage(@cache.storage) ``` diff --git a/dependency-injection/tr/configuration.texy b/dependency-injection/tr/configuration.texy index 322cb2075a..0c5f7e7728 100644 --- a/dependency-injection/tr/configuration.texy +++ b/dependency-injection/tr/configuration.texy @@ -191,20 +191,15 @@ Sınıfların hangi dizinlerde (ve alt dizinlerde) aranması gerektiğini belirt ```neon search: - # bölüm adlarını kendiniz seçersiniz - myForms: - in: %appDir%/Forms - - model: - in: %appDir%/Model + - in: %appDir%/Forms + - in: %appDir%/Model ``` Ancak genellikle, tüm sınıfları ve arayüzleri eklemek istemeyiz, bu yüzden onları filtreleyebiliriz: ```neon search: - myForms: - in: %appDir%/Forms + - in: %appDir%/Forms # dosya adına göre filtreleme (string|string[]) files: @@ -220,7 +215,7 @@ Ya da aşağıdaki sınıflardan en az birini miras alan veya uygulayan sınıfl ```neon search: - myForms: + - in: %appDir% extends: - App\*Form implements: @@ -231,7 +226,7 @@ Ayrıca negatif kurallar da tanımlayabilirsiniz, yani sınıf adı maskeleri ve ```neon search: - myForms: + - in: %appDir% exclude: classes: ... extends: ... @@ -242,7 +237,7 @@ Eklenen hizmetler için etiketler belirlenebilir: ```neon search: - myForms: + - in: %appDir% tags: ... ``` diff --git a/dependency-injection/tr/passing-dependencies.texy b/dependency-injection/tr/passing-dependencies.texy index 6cb6795534..d77ec173aa 100644 --- a/dependency-injection/tr/passing-dependencies.texy +++ b/dependency-injection/tr/passing-dependencies.texy @@ -168,8 +168,7 @@ Setter çağrısı, [kurulum bölümündeki |services#Setup] DI konteyner yapıl ```neon services: - - - create: MyClass + - create: MyClass setup: - setCache ``` @@ -196,8 +195,7 @@ Değişkenin ayarı, [kurulum bölümündeki |services#Setup] DI konteyner yapı ```neon services: - - - create: MyClass + - create: MyClass setup: - $cache = @\Cache ``` diff --git a/dependency-injection/tr/services.texy b/dependency-injection/tr/services.texy index a4b3fb86c4..13eabfd4c8 100644 --- a/dependency-injection/tr/services.texy +++ b/dependency-injection/tr/services.texy @@ -235,8 +235,8 @@ Bireysel hizmetlere `@` and name, so for example `@database` karakteri kullanıl ```neon services: - - create: Foo(@database) - setup: + - create: Foo(@database) + setup: - setCacheStorage(@cache.storage) ``` @@ -255,8 +255,8 @@ Anonim hizmetlere bile bir geri arama kullanılarak başvurulabilir, sadece adla ```neon services: - - create: Foo(@Nette\Database\Connection) # or @\PDO - setup: + - create: Foo(@Nette\Database\Connection) + setup: - setCacheStorage(@cache.storage) ``` diff --git a/dependency-injection/uk/configuration.texy b/dependency-injection/uk/configuration.texy index da99a35c9d..f88af94d58 100644 --- a/dependency-injection/uk/configuration.texy +++ b/dependency-injection/uk/configuration.texy @@ -191,20 +191,15 @@ return [ ```neon search: - # ви самі вибираєте назви секцій - myForms: - in: %appDir%/Forms - - model: - in: %appDir%/Model + - in: %appDir%/Forms + - in: %appDir%/Model ``` Зазвичай, однак, ми не хочемо додавати всі класи та інтерфейси, тому ми можемо відфільтрувати їх: ```neon search: - myForms: - in: %appDir%/Forms + - in: %appDir%/Forms # фільтрація за ім'ям файлу (string|string[]) files: @@ -220,7 +215,7 @@ search: ```neon search: - myForms: + - in: %appDir% extends: - App\*Form implements: @@ -231,7 +226,7 @@ search: ```neon search: - myForms: + - in: %appDir% exclude: classes: ... extends: ... @@ -242,7 +237,7 @@ search: ```neon search: - myForms: + - in: %appDir% tags: ... ``` diff --git a/dependency-injection/uk/passing-dependencies.texy b/dependency-injection/uk/passing-dependencies.texy index 5badf00eb0..5200e69e95 100644 --- a/dependency-injection/uk/passing-dependencies.texy +++ b/dependency-injection/uk/passing-dependencies.texy @@ -168,8 +168,7 @@ class MyClass ```neon services: - - - create: MyClass + - create: MyClass setup: - setCache ``` @@ -196,8 +195,7 @@ $obj->cache = $cache; ```neon services: - - - create: MyClass + - create: MyClass setup: - $cache = @\Cache ``` diff --git a/dependency-injection/uk/services.texy b/dependency-injection/uk/services.texy index 10bb015505..85879327de 100644 --- a/dependency-injection/uk/services.texy +++ b/dependency-injection/uk/services.texy @@ -235,8 +235,8 @@ services: ```neon services: - - create: Foo(@database) - setup: + - create: Foo(@database) + setup: - setCacheStorage(@cache.storage) ``` @@ -255,8 +255,8 @@ public function createService01(): Foo ```neon services: - - create: Foo(@Nette\Database\Connection) # или @\PDO - setup: + - create: Foo(@Nette\Database\Connection) + setup: - setCacheStorage(@cache.storage) ``` From 85b137c34320f6a468dcadfb6a8b4ec01fc884d3 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 2 Oct 2023 19:25:35 +0200 Subject: [PATCH 014/137] turning cache off --- caching/bg/@home.texy | 13 +++++++++++++ caching/cs/@home.texy | 13 +++++++++++++ caching/de/@home.texy | 13 +++++++++++++ caching/el/@home.texy | 13 +++++++++++++ caching/en/@home.texy | 13 +++++++++++++ caching/es/@home.texy | 13 +++++++++++++ caching/fr/@home.texy | 13 +++++++++++++ caching/hu/@home.texy | 13 +++++++++++++ caching/it/@home.texy | 13 +++++++++++++ caching/pl/@home.texy | 13 +++++++++++++ caching/pt/@home.texy | 13 +++++++++++++ caching/ro/@home.texy | 13 +++++++++++++ caching/ru/@home.texy | 13 +++++++++++++ caching/sl/@home.texy | 13 +++++++++++++ caching/tr/@home.texy | 13 +++++++++++++ caching/uk/@home.texy | 13 +++++++++++++ nette/bg/troubleshooting.texy | 7 +++++++ nette/cs/troubleshooting.texy | 7 +++++++ nette/de/troubleshooting.texy | 7 +++++++ nette/el/troubleshooting.texy | 7 +++++++ nette/en/troubleshooting.texy | 7 +++++++ nette/es/troubleshooting.texy | 7 +++++++ nette/fr/troubleshooting.texy | 7 +++++++ nette/hu/troubleshooting.texy | 7 +++++++ nette/it/troubleshooting.texy | 7 +++++++ nette/pl/troubleshooting.texy | 7 +++++++ nette/pt/troubleshooting.texy | 7 +++++++ nette/ro/troubleshooting.texy | 7 +++++++ nette/ru/troubleshooting.texy | 7 +++++++ nette/sl/troubleshooting.texy | 7 +++++++ nette/tr/troubleshooting.texy | 7 +++++++ nette/uk/troubleshooting.texy | 7 +++++++ 32 files changed, 320 insertions(+) diff --git a/caching/bg/@home.texy b/caching/bg/@home.texy index 20a4992b5a..93c445505d 100644 --- a/caching/bg/@home.texy +++ b/caching/bg/@home.texy @@ -455,4 +455,17 @@ services: | `cache.storage` | [api:Nette\Caching\Storage] | хранилище +Изключване на кеша .[#toc-turning-off-cache] +============================================ + +Един от начините да изключите кеширането в приложението е да зададете съхранение на [DevNullStorage |#DevNullStorage]: + +```neon +services: + cache.storage: Nette\Caching\Storages\DevNullStorage +``` + +Тази настройка не влияе на кеширането на шаблоните в Latte или контейнера DI, тъй като тези библиотеки не използват услугите на nette/caching и управляват кеша си самостоятелно. Освен това [не е необходимо |nette:troubleshooting#how-to-disable-cache-during-development] техният кеш да [бъде изключен |nette:troubleshooting#how-to-disable-cache-during-development] в режим на разработка. + + {{leftbar: nette:@menu-topics}} diff --git a/caching/cs/@home.texy b/caching/cs/@home.texy index 8ccf9abb56..ecd736b714 100644 --- a/caching/cs/@home.texy +++ b/caching/cs/@home.texy @@ -455,4 +455,17 @@ Tyto služby se přidávají do DI kontejneru: | `cache.storage` | [api:Nette\Caching\Storage] | úložiště +Vypnutí cache +============= + +Jednou z možností, jak vypnout cache v aplikaci, je nastavit jako úložiště [DevNullStorage|#DevNullStorage]: + +```neon +services: + cache.storage: Nette\Caching\Storages\DevNullStorage +``` + +Toto nastavení nemá vliv na kešování šablon v Latte nebo DI kontejeru, protože tyto knihovny nevyužívají služeb nette/caching a spravují si cache samostatně. Jejich cache ostatně [není potřeba |nette:troubleshooting#jak-vypnout-cache-behem-vyvoje] ve vývojářském režimu vypínat. + + {{leftbar: nette:@menu-topics}} diff --git a/caching/de/@home.texy b/caching/de/@home.texy index b69531fee2..38f93f0350 100644 --- a/caching/de/@home.texy +++ b/caching/de/@home.texy @@ -455,4 +455,17 @@ Diese Dienste werden dem DI-Container hinzugefügt: | `cache.storage` | [api:Nette\Caching\Storage] | repository +Cache ausschalten .[#toc-turning-off-cache] +=========================================== + +Eine Möglichkeit, die Zwischenspeicherung in der Anwendung zu deaktivieren, besteht darin, den Speicher auf [DevNullStorage |#DevNullStorage] zu setzen: + +```neon +services: + cache.storage: Nette\Caching\Storages\DevNullStorage +``` + +Diese Einstellung wirkt sich nicht auf die Zwischenspeicherung von Vorlagen in Latte oder dem DI-Container aus, da diese Bibliotheken nicht die Dienste von nette/caching nutzen und ihren Cache unabhängig verwalten. Außerdem [muss |nette:troubleshooting#how-to-disable-cache-during-development] ihr Cache im Entwicklungsmodus [nicht abgeschaltet werden |nette:troubleshooting#how-to-disable-cache-during-development]. + + {{leftbar: nette:@menu-topics}} diff --git a/caching/el/@home.texy b/caching/el/@home.texy index 309a4273d8..66a2af2665 100644 --- a/caching/el/@home.texy +++ b/caching/el/@home.texy @@ -455,4 +455,17 @@ services: | `cache.storage` | [api:Nette\Caching\Storage] | repository +Απενεργοποίηση της κρυφής μνήμης .[#toc-turning-off-cache] +========================================================== + +Ένας από τους τρόπους για να απενεργοποιήσετε την προσωρινή αποθήκευση στην εφαρμογή είναι να ορίσετε τον αποθηκευτικό χώρο σε [DevNullStorage |#DevNullStorage]: + +```neon +services: + cache.storage: Nette\Caching\Storages\DevNullStorage +``` + +Αυτή η ρύθμιση δεν επηρεάζει την προσωρινή αποθήκευση των προτύπων στο Latte ή στο DI container, καθώς αυτές οι βιβλιοθήκες δεν χρησιμοποιούν τις υπηρεσίες της nette/caching και διαχειρίζονται την προσωρινή τους μνήμη ανεξάρτητα. Επιπλέον, η κρυφή μνήμη τους [δεν χρειάζεται να απ |nette:troubleshooting#how-to-disable-cache-during-development] ενεργοποιηθεί στη λειτουργία ανάπτυξης. + + {{leftbar: nette:@menu-topics}} diff --git a/caching/en/@home.texy b/caching/en/@home.texy index b8cb141247..dc6d500191 100644 --- a/caching/en/@home.texy +++ b/caching/en/@home.texy @@ -455,4 +455,17 @@ These services are added to the DI container: | `cache.storage` | [api:Nette\Caching\Storage] | repository +Turning Off Cache +================= + +One of the ways to turn off caching in the application is to set the storage to [DevNullStorage|#DevNullStorage]: + +```neon +services: + cache.storage: Nette\Caching\Storages\DevNullStorage +``` + +This setting does not affect the caching of templates in Latte or the DI container, as these libraries do not use the services of nette/caching and manage their cache independently. Moreover, their cache [does not need to be turned off |nette:troubleshooting#how-to-disable-cache-during-development] in development mode. + + {{leftbar: nette:@menu-topics}} diff --git a/caching/es/@home.texy b/caching/es/@home.texy index 531dadfdec..160688da21 100644 --- a/caching/es/@home.texy +++ b/caching/es/@home.texy @@ -455,4 +455,17 @@ Estos servicios se añaden al contenedor DI: | `cache.storage` | [api:Nette\Caching\Storage] | Repositorio +Cómo desactivar la caché .[#toc-turning-off-cache] +================================================== + +Una de las formas de desactivar el almacenamiento en caché en la aplicación es establecer el almacenamiento a [DevNullStorage |#DevNullStorage]: + +```neon +services: + cache.storage: Nette\Caching\Storages\DevNullStorage +``` + +Esta configuración no afecta al almacenamiento en caché de las plantillas en Latte o el contenedor DI, ya que estas bibliotecas no utilizan los servicios de nette/caching y gestionan su caché de forma independiente. Además, [no es necesario desactivar |nette:troubleshooting#how-to-disable-cache-during-development] su caché en el modo de desarrollo. + + {{leftbar: nette:@menu-topics}} diff --git a/caching/fr/@home.texy b/caching/fr/@home.texy index 0a470bcc93..4de232b30a 100644 --- a/caching/fr/@home.texy +++ b/caching/fr/@home.texy @@ -455,4 +455,17 @@ Ces services sont ajoutés au conteneur DI : | `cache.storage` | [api:Nette\Caching\Storage] | repository +Désactiver le cache .[#toc-turning-off-cache] +============================================= + +L'une des façons de désactiver la mise en cache dans l'application est de définir le stockage sur [DevNullStorage |#DevNullStorage]: + +```neon +services: + cache.storage: Nette\Caching\Storages\DevNullStorage +``` + +Ce paramètre n'affecte pas la mise en cache des modèles dans Latte ou le conteneur DI, car ces bibliothèques n'utilisent pas les services de nette/caching et gèrent leur cache de manière indépendante. De plus, leur cache n ['a pas besoin d'être désactivé |nette:troubleshooting#how-to-disable-cache-during-development] en mode développement. + + {{leftbar: nette:@menu-topics}} diff --git a/caching/hu/@home.texy b/caching/hu/@home.texy index 35a2b69b1a..68980aa562 100644 --- a/caching/hu/@home.texy +++ b/caching/hu/@home.texy @@ -455,4 +455,17 @@ Ezek a szolgáltatások hozzáadódnak a DI konténerhez: | `cache.storage` | [api:Nette\Caching\Storage] | repository +Cache kikapcsolása .[#toc-turning-off-cache] +============================================ + +A gyorsítótár kikapcsolásának egyik módja az alkalmazásban a tároló [DevNullStorage |#DevNullStorage] értékre állítása: + +```neon +services: + cache.storage: Nette\Caching\Storages\DevNullStorage +``` + +Ez a beállítás nem befolyásolja a Latte vagy a DI konténer sablonjainak gyorsítótárazását, mivel ezek a könyvtárak nem használják a nette/caching szolgáltatásait, és önállóan kezelik a gyorsítótárukat. Ráadásul a gyorsítótárukat [nem kell kikapcsolni |nette:troubleshooting#how-to-disable-cache-during-development] fejlesztési módban. + + {{leftbar: nette:@menu-topics}} diff --git a/caching/it/@home.texy b/caching/it/@home.texy index a2ffac4a4e..932701617a 100644 --- a/caching/it/@home.texy +++ b/caching/it/@home.texy @@ -455,4 +455,17 @@ Questi servizi vengono aggiunti al contenitore DI: | `cache.storage` | [api:Nette\Caching\Storage] | repository +Disattivare la cache .[#toc-turning-off-cache] +============================================== + +Uno dei modi per disattivare la cache nell'applicazione è impostare lo storage su [DevNullStorage |#DevNullStorage]: + +```neon +services: + cache.storage: Nette\Caching\Storages\DevNullStorage +``` + +Questa impostazione non influisce sulla cache dei modelli in Latte o nel contenitore DI, poiché queste librerie non utilizzano i servizi di nette/caching e gestiscono la loro cache in modo indipendente. Inoltre, la loro cache [non deve essere disattivata |nette:troubleshooting#how-to-disable-cache-during-development] in modalità di sviluppo. + + {{leftbar: nette:@menu-topics}} diff --git a/caching/pl/@home.texy b/caching/pl/@home.texy index dcce5e86e5..57d9d02bb4 100644 --- a/caching/pl/@home.texy +++ b/caching/pl/@home.texy @@ -455,4 +455,17 @@ Usługi te są dodawane do kontenera DI: | `cache.storage` | [api:Nette\Caching\Storage] | repozytorium +Wyłączanie pamięci podręcznej .[#toc-turning-off-cache] +======================================================= + +Jednym ze sposobów wyłączenia buforowania w aplikacji jest ustawienie pamięci masowej na [DevNullStorage |#DevNullStorage]: + +```neon +services: + cache.storage: Nette\Caching\Storages\DevNullStorage +``` + +Ustawienie to nie wpływa na buforowanie szablonów w Latte lub kontenerze DI, ponieważ biblioteki te nie korzystają z usług nette/caching i zarządzają swoją pamięcią podręczną niezależnie. Co więcej, ich pamięć podręczna nie musi być [wyłączona |nette:troubleshooting#how-to-disable-cache-during-development] w trybie deweloperskim. + + {{leftbar: nette:@menu-topics}} diff --git a/caching/pt/@home.texy b/caching/pt/@home.texy index 7e1585db49..c8f0dff93b 100644 --- a/caching/pt/@home.texy +++ b/caching/pt/@home.texy @@ -455,4 +455,17 @@ Esses serviços são adicionados ao contêiner DI: | `cache.storage` | [api:Nette\Caching\Storage] | repositório +Desativação do cache .[#toc-turning-off-cache] +============================================== + +Uma das maneiras de desativar o cache no aplicativo é definir o armazenamento como [DevNullStorage |#DevNullStorage]: + +```neon +services: + cache.storage: Nette\Caching\Storages\DevNullStorage +``` + +Essa configuração não afeta o armazenamento em cache dos modelos no Latte ou no contêiner DI, pois essas bibliotecas não usam os serviços do nette/caching e gerenciam seu cache de forma independente. Além disso, seu cache [não precisa ser desativ |nette:troubleshooting#how-to-disable-cache-during-development] ado no modo de desenvolvimento. + + {{leftbar: nette:@menu-topics}} diff --git a/caching/ro/@home.texy b/caching/ro/@home.texy index 179a0e2532..b821482ad2 100644 --- a/caching/ro/@home.texy +++ b/caching/ro/@home.texy @@ -455,4 +455,17 @@ Nume | Tip | Descriere `cache.storage` | [api:Nette\Caching\Storage] | | repository +Dezactivarea memoriei cache .[#toc-turning-off-cache] +===================================================== + +Una dintre modalitățile de dezactivare a memoriei cache în aplicație este să setați stocarea la [DevNullStorage |#DevNullStorage]: + +```neon +services: + cache.storage: Nette\Caching\Storages\DevNullStorage +``` + +Această setare nu afectează memoria cache a șabloanelor din Latte sau din containerul DI, deoarece aceste biblioteci nu utilizează serviciile nette/caching și își gestionează memoria cache în mod independent. În plus, memoria cache a acestora [nu trebuie dezactivată |nette:troubleshooting#how-to-disable-cache-during-development] în modul de dezvoltare. + + {{leftbar: nette:@menu-topics}} diff --git a/caching/ru/@home.texy b/caching/ru/@home.texy index 79f33dd961..f663f68372 100644 --- a/caching/ru/@home.texy +++ b/caching/ru/@home.texy @@ -455,4 +455,17 @@ services: | `cache.storage` | [api:Nette\Caching\Storage] | репозиторий +Отключение кэша .[#toc-turning-off-cache] +========================================= + +Одним из способов отключения кэширования в приложении является установка для хранилища значения [DevNullStorage |#DevNullStorage]: + +```neon +services: + cache.storage: Nette\Caching\Storages\DevNullStorage +``` + +Данная настройка не влияет на кэширование шаблонов в Latte или контейнере DI, так как эти библиотеки не используют сервисы nette/caching и управляют своим кэшем самостоятельно. Более того, их кэш [не нужно отключать |nette:troubleshooting#how-to-disable-cache-during-development] в режиме разработки. + + {{leftbar: nette:@menu-topics}} diff --git a/caching/sl/@home.texy b/caching/sl/@home.texy index 494f73a22a..aa8f457cc5 100644 --- a/caching/sl/@home.texy +++ b/caching/sl/@home.texy @@ -455,4 +455,17 @@ Te storitve so dodane vsebniku DI: | `cache.storage` | [api:Nette\Caching\Storage] | repozitorij +Izklop predpomnilnika .[#toc-turning-off-cache] +=============================================== + +Eden od načinov za izklop predpomnilnika v aplikaciji je nastavitev shrambe na [DevNullStorage |#DevNullStorage]: + +```neon +services: + cache.storage: Nette\Caching\Storages\DevNullStorage +``` + +Ta nastavitev ne vpliva na predpomnjenje predlog v Latte ali vsebniku DI, saj ti knjižnici ne uporabljata storitev nette/caching in upravljata svoj predpomnilnik neodvisno. Poleg tega njihovega predpomnilnika v razvojnem načinu [ni treba izklopiti |nette:troubleshooting#how-to-disable-cache-during-development]. + + {{leftbar: nette:@menu-topics}} diff --git a/caching/tr/@home.texy b/caching/tr/@home.texy index 8ef3ab0725..8367b34b0b 100644 --- a/caching/tr/@home.texy +++ b/caching/tr/@home.texy @@ -455,4 +455,17 @@ Bu hizmetler DI konteynerine eklenir: | `cache.storage` | [api:Nette\Caching\Storage] | depo +Önbelleği Kapatma .[#toc-turning-off-cache] +=========================================== + +Uygulamada önbelleğe almayı kapatmanın yollarından biri depolamayı [DevNullStorage |#DevNullStorage] olarak ayarlamaktır: + +```neon +services: + cache.storage: Nette\Caching\Storages\DevNullStorage +``` + +Bu ayar, Latte veya DI konteynerindeki şablonların önbelleğe alınmasını etkilemez, çünkü bu kütüphaneler nette/caching hizmetlerini kullanmaz ve önbelleklerini bağımsız olarak yönetir. Ayrıca, geliştirme modunda önbelleklerinin [kapatılmasına gerek yoktur |nette:troubleshooting#how-to-disable-cache-during-development]. + + {{leftbar: nette:@menu-topics}} diff --git a/caching/uk/@home.texy b/caching/uk/@home.texy index 6e32f166ce..a1f94ea61a 100644 --- a/caching/uk/@home.texy +++ b/caching/uk/@home.texy @@ -455,4 +455,17 @@ services: | `cache.storage` | [api:Nette\Caching\Storage] | репозиторій +Вимкнення кешу .[#toc-turning-off-cache] +======================================== + +Один із способів вимкнути кешування в додатку - встановити для сховища значення [DevNullStorage |#DevNullStorage]: + +```neon +services: + cache.storage: Nette\Caching\Storages\DevNullStorage +``` + +Це налаштування не впливає на кешування шаблонів у Latte або контейнері DI, оскільки ці бібліотеки не використовують сервіси nette/caching і керують своїм кешем самостійно. Крім того, їх кеш [не потрібно |nette:troubleshooting#how-to-disable-cache-during-development] вимикати в режимі розробки. + + {{leftbar: nette:@menu-topics}} diff --git a/nette/bg/troubleshooting.texy b/nette/bg/troubleshooting.texy index 6b42d2660b..3025fb225e 100644 --- a/nette/bg/troubleshooting.texy +++ b/nette/bg/troubleshooting.texy @@ -32,6 +32,13 @@ Tracy ще ви информира защо не може да регистри Когато всички страници (с изключение на началната страница) връщат грешка 404, това изглежда като проблем с конфигурацията на сървъра за [красиви URL адреси |#How to Configure a Server for Nice URLs?]. +Как да деактивирам кеша по време на разработка? .[#toc-how-to-disable-cache-during-development] +----------------------------------------------------------------------------------------------- +Nette е умен и не е необходимо да деактивирате кеширането в него. По време на разработката той автоматично актуализира кеша, когато има промяна в шаблона или конфигурацията на DI контейнера. Освен това режимът за разработка се активира чрез автоматично откриване, така че обикновено не е необходимо да конфигурирате нищо [или само IP адреса |application:bootstrap#development-vs-production-mode]. + +При отстраняване на грешки в маршрутизатора препоръчваме да се деактивира кешът на браузъра, където например може да се съхраняват пренасочвания: отворете Developer Tools (Ctrl+Shift+I или Cmd+Option+I) и в панела Network (Мрежа) поставете отметка в квадратчето за деактивиране на кеша. + + Грешка `#[\ReturnTypeWillChange] attribute should be used` .[#toc-error-returntypewillchange-attribute-should-be-used] ---------------------------------------------------------------------------------------------------------------------- Тази грешка се появява, ако сте обновили PHP до версия 8.1, но използвате Nette, която не е съвместима с нея. Решението е да се обнови Nette до по-нова версия с помощта на `composer update`. Nette поддържа PHP 8.1 от версия 3.0. Ако използвате по-стара версия (можете да разберете това, като погледнете `composer.json`), [обновете Nette |migrations:en] или останете с PHP 8.0. diff --git a/nette/cs/troubleshooting.texy b/nette/cs/troubleshooting.texy index 6f17c414a7..e18ad30c9e 100644 --- a/nette/cs/troubleshooting.texy +++ b/nette/cs/troubleshooting.texy @@ -32,6 +32,13 @@ Chyba 404, nefunguje routování Když všechny stránky (kromě homepage) vrací chybu 404, vypadá to na problém s konfigurací serveru pro [hezká URL |#Jak nastavit server pro hezká URL?]. +Jak vypnout cache během vývoje? +------------------------------- +Nette je chytré a nemusíte v něm vypínat kešování. Při vývoji totiž automaticky aktualizuje cache při každé změně šablony nebo konfigurace DI kontejneru. Vývojový režimu se navíc zapíná autodetekcí, takže obvykle není potřeba konfigurovat nic, [nebo jen IP adresu |application:bootstrap#vyvojarsky-vs-produkcni-rezim]. + +Při ladění routeru doporučujeme vypnout cache v prohlížeči, ve které mohou být uložené například přesměrování: otevřete si Developer Tools (Ctrl+Shift+I nebo Cmd+Option+I) a v panelu Network (Síť) zaškrtněne vypnutí cache. + + Chyba `#[\ReturnTypeWillChange] attribute should be used` --------------------------------------------------------- Tato chyba se objeví, pokud jste aktualizovali PHP na verzi 8.1, ale používáte Nette, která s ní není kompatibilní. Řešením je tedy aktualizovat Nette na novější verzi pomocí `composer update`. Nette podporuje PHP 8.1 od verze 3.0. Pokud používáte verzi starší (zjistíte pohledem do `composer.json`), [upgradujte Nette |migrations:] nebo zůstaňte u PHP 8.0. diff --git a/nette/de/troubleshooting.texy b/nette/de/troubleshooting.texy index 3f6bad0a91..d711a893b0 100644 --- a/nette/de/troubleshooting.texy +++ b/nette/de/troubleshooting.texy @@ -32,6 +32,13 @@ Fehler 404, Routing funktioniert nicht .[#toc-error-404-routing-not-working] Wenn alle Seiten (außer der Homepage) einen 404-Fehler zurückgeben, sieht es nach einem Serverkonfigurationsproblem für [hübsche URLs |#How to Configure a Server for Nice URLs?] aus. +Wie kann man den Cache während der Entwicklung deaktivieren? .[#toc-how-to-disable-cache-during-development] +------------------------------------------------------------------------------------------------------------ +Nette ist intelligent, und Sie müssen das Caching nicht deaktivieren. Während der Entwicklung wird der Cache automatisch aktualisiert, sobald eine Änderung in der Vorlage oder der DI-Container-Konfiguration vorgenommen wird. Außerdem wird der Entwicklungsmodus durch automatische Erkennung aktiviert, so dass normalerweise nichts konfiguriert werden muss, [auch nicht die IP-Adresse |application:bootstrap#development-vs-production-mode]. + +Bei der Fehlersuche im Router empfiehlt es sich, den Browser-Cache zu deaktivieren, in dem z. B. Umleitungen gespeichert sein könnten: Öffnen Sie die Entwicklertools (Strg+Umschalt+I oder Cmd+Option+I) und aktivieren Sie im Bereich Netzwerk das Kontrollkästchen zur Deaktivierung des Cache. + + Fehler `#[\ReturnTypeWillChange] attribute should be used` .[#toc-error-returntypewillchange-attribute-should-be-used] ---------------------------------------------------------------------------------------------------------------------- Dieser Fehler tritt auf, wenn Sie PHP auf Version 8.1 aktualisiert haben, aber Nette verwenden, das damit nicht kompatibel ist. Die Lösung besteht also darin, Nette mit `composer update` auf eine neuere Version zu aktualisieren. Nette unterstützt PHP 8.1 seit Version 3.0. Wenn Sie eine ältere Version verwenden (Sie können dies unter `composer.json` herausfinden), [aktualisieren Sie Nette |migrations:en] oder bleiben Sie bei PHP 8.0. diff --git a/nette/el/troubleshooting.texy b/nette/el/troubleshooting.texy index 1601a2e3fa..18f731fbb4 100644 --- a/nette/el/troubleshooting.texy +++ b/nette/el/troubleshooting.texy @@ -32,6 +32,13 @@ $configurator->enableTracy($appDir . '/log'); Όταν όλες οι σελίδες (εκτός από την αρχική σελίδα) επιστρέφουν ένα σφάλμα 404, φαίνεται ότι υπάρχει πρόβλημα διαμόρφωσης του διακομιστή για τις [όμορφες διευθύνσεις URL |#How to Configure a Server for Nice URLs?]. +Πώς να απενεργοποιήσετε την προσωρινή μνήμη cache κατά τη διάρκεια της ανάπτυξης; .[#toc-how-to-disable-cache-during-development] +--------------------------------------------------------------------------------------------------------------------------------- +Το Nette είναι έξυπνο και δεν χρειάζεται να απενεργοποιήσετε την προσωρινή αποθήκευση σε αυτό. Κατά τη διάρκεια της ανάπτυξης, ενημερώνει αυτόματα την κρυφή μνήμη κάθε φορά που υπάρχει μια αλλαγή στο πρότυπο ή στη διαμόρφωση του DI container. Επιπλέον, η λειτουργία ανάπτυξης ενεργοποιείται με αυτόματη ανίχνευση, οπότε συνήθως δεν χρειάζεται να ρυθμίσετε τίποτα [ή μόνο τη διεύθυνση IP |application:bootstrap#development-vs-production-mode]. + +Κατά την αποσφαλμάτωση του δρομολογητή, συνιστούμε την απενεργοποίηση της προσωρινής μνήμης του προγράμματος περιήγησης, όπου, για παράδειγμα, ενδέχεται να αποθηκεύονται οι ανακατευθύνσεις: ανοίξτε τα Εργαλεία ανάπτυξης (Ctrl+Shift+I ή Cmd+Option+I) και στον πίνακα Δίκτυο, τσεκάρετε το πλαίσιο για την απενεργοποίηση της προσωρινής μνήμης. + + Σφάλμα `#[\ReturnTypeWillChange] attribute should be used` .[#toc-error-returntypewillchange-attribute-should-be-used] ---------------------------------------------------------------------------------------------------------------------- Αυτό το σφάλμα εμφανίζεται αν έχετε αναβαθμίσει την PHP στην έκδοση 8.1 αλλά χρησιμοποιείτε τη Nette, η οποία δεν είναι συμβατή με αυτήν. Έτσι, η λύση είναι να ενημερώσετε τη Nette σε μια νεότερη έκδοση χρησιμοποιώντας το `composer update`. Η Nette υποστηρίζει την PHP 8.1 από την έκδοση 3.0. Αν χρησιμοποιείτε παλαιότερη έκδοση (μπορείτε να το διαπιστώσετε αναζητώντας στο `composer.json`), [αναβαθμίστε το Nette |migrations:en] ή μείνετε με την PHP 8.0. diff --git a/nette/en/troubleshooting.texy b/nette/en/troubleshooting.texy index da18381275..b9b44992fa 100644 --- a/nette/en/troubleshooting.texy +++ b/nette/en/troubleshooting.texy @@ -32,6 +32,13 @@ Error 404, Routing Not Working When all pages (except the homepage) return a 404 error, it looks like a server configuration problem for [pretty URLs |#How to Configure a Server for Nice URLs?]. +How to Disable Cache During Development? +---------------------------------------- +Nette is smart, and you don't need to disable caching in it. During development, it automatically updates the cache whenever there's a change in the template or the DI container configuration. Moreover, the development mode is activated by auto-detection, so there's usually no need to configure anything, [or just the IP address |application:bootstrap#development-vs-production-mode]. + +When debugging the router, we recommend disabling the browser cache, where, for example, redirects might be stored: open Developer Tools (Ctrl+Shift+I or Cmd+Option+I) and in the Network panel, check the box to disable the cache. + + Error `#[\ReturnTypeWillChange] attribute should be used` --------------------------------------------------------- This error occurs if you have upgraded PHP to version 8.1 but are using Nette, which is not compatible with it. So the solution is to update Nette to a newer version using `composer update`. Nette has supported PHP 8.1 since version 3.0. If you are using an older version (you can find out by looking in `composer.json`), [upgrade Nette |migrations:] or stay with PHP 8.0. diff --git a/nette/es/troubleshooting.texy b/nette/es/troubleshooting.texy index d0f9af49ff..59b26e6139 100644 --- a/nette/es/troubleshooting.texy +++ b/nette/es/troubleshooting.texy @@ -32,6 +32,13 @@ Error 404, enrutamiento no funciona .[#toc-error-404-routing-not-working] Cuando todas las páginas (excepto la página de inicio) devuelven un error 404, parece un problema de configuración del servidor para [URLs bonitas |#How to Configure a Server for Nice URLs?]. +¿Cómo desactivar la caché durante el desarrollo? .[#toc-how-to-disable-cache-during-development] +------------------------------------------------------------------------------------------------ +Nette es inteligente, y no necesitas desactivar la caché en él. Durante el desarrollo, actualiza automáticamente la caché cada vez que hay un cambio en la plantilla o en la configuración del contenedor DI. Además, el modo de desarrollo se activa por auto-detección, por lo que normalmente no hay necesidad de configurar nada, [o sólo la dirección IP |application:bootstrap#development-vs-production-mode]. + +A la hora de depurar el router, recomendamos desactivar la caché del navegador, donde, por ejemplo, podrían almacenarse las redirecciones: abre Herramientas de desarrollo (Ctrl+Mayús+I o Cmd+Opción+I) y, en el panel Red, marca la casilla para desactivar la caché. + + Error `#[\ReturnTypeWillChange] attribute should be used` .[#toc-error-returntypewillchange-attribute-should-be-used] --------------------------------------------------------------------------------------------------------------------- Este error se produce si ha actualizado PHP a la versión 8.1 pero está utilizando Nette, que no es compatible con ella. Entonces la solución es actualizar Nette a una versión más reciente usando `composer update`. Nette es compatible con PHP 8.1 desde la versión 3.0. Si está usando una versión anterior (puede averiguarlo buscando en `composer.json`), [actualice |migrations:en] Nette o quédese con PHP 8.0. diff --git a/nette/fr/troubleshooting.texy b/nette/fr/troubleshooting.texy index fad903b6f2..5e466938c7 100644 --- a/nette/fr/troubleshooting.texy +++ b/nette/fr/troubleshooting.texy @@ -32,6 +32,13 @@ Erreur 404, le routage ne fonctionne pas .[#toc-error-404-routing-not-working] Lorsque toutes les pages (sauf la page d'accueil) renvoient une erreur 404, il semble qu'il y ait un problème de configuration du serveur pour les [jolies URL |#How to Configure a Server for Nice URLs?]. +Comment désactiver le cache pendant le développement ? .[#toc-how-to-disable-cache-during-development] +------------------------------------------------------------------------------------------------------ +Nette est intelligent et il n'est pas nécessaire de désactiver la mise en cache. Pendant le développement, il met automatiquement à jour le cache chaque fois qu'il y a un changement dans le modèle ou la configuration du conteneur DI. De plus, le mode développement est activé par auto-détection, il n'y a donc généralement pas besoin de configurer quoi que ce soit, [ou juste l'adresse IP |application:bootstrap#development-vs-production-mode]. + +Lorsque vous déboguez le routeur, nous vous recommandons de désactiver le cache du navigateur, où, par exemple, les redirections peuvent être stockées : ouvrez Developer Tools (Ctrl+Shift+I ou Cmd+Option+I) et dans le panneau Network, cochez la case pour désactiver le cache. + + Erreur `#[\ReturnTypeWillChange] attribute should be used` .[#toc-error-returntypewillchange-attribute-should-be-used] ---------------------------------------------------------------------------------------------------------------------- Cette erreur se produit si vous avez mis à niveau PHP vers la version 8.1 mais que vous utilisez Nette, qui n'est pas compatible avec cette version. La solution est donc de mettre à jour Nette vers une version plus récente en utilisant `composer update`. Nette supporte PHP 8.1 depuis la version 3.0. Si vous utilisez une version plus ancienne (vous pouvez le savoir en consultant `composer.json`), [mettez à jour Nette |migrations:en] ou restez avec PHP 8.0. diff --git a/nette/hu/troubleshooting.texy b/nette/hu/troubleshooting.texy index 4b9b567e85..1c2df17f16 100644 --- a/nette/hu/troubleshooting.texy +++ b/nette/hu/troubleshooting.texy @@ -32,6 +32,13 @@ Az 500-as hiba egyik leggyakoribb oka az elavult gyorsítótár. Míg a Nette ok Amikor minden oldal (a kezdőlap kivételével) 404-es hibát ad vissza, úgy tűnik, hogy a szerver konfigurációs problémája van a [szép URL-eknél |#How to Configure a Server for Nice URLs?]. +Hogyan lehet letiltani a gyorsítótárat a fejlesztés során? .[#toc-how-to-disable-cache-during-development] +---------------------------------------------------------------------------------------------------------- +A Nette okos, és nem kell kikapcsolni benne a gyorsítótárazást. A fejlesztés során automatikusan frissíti a gyorsítótárat, ha változás történik a sablonban vagy a DI konténer konfigurációjában. Ráadásul a fejlesztési mód automatikus felismeréssel aktiválódik, így általában nem kell semmit, [vagy csak az IP-címet |application:bootstrap#development-vs-production-mode] konfigurálni. + +A router hibakeresése során javasoljuk a böngésző gyorsítótárának letiltását, ahol például az átirányítások tárolódhatnak: nyissa meg a Developer Tools-t (Ctrl+Shift+I vagy Cmd+Option+I), és a Hálózat panelen jelölje be a gyorsítótár letiltására szolgáló négyzetet. + + Hiba `#[\ReturnTypeWillChange] attribute should be used` .[#toc-error-returntypewillchange-attribute-should-be-used] -------------------------------------------------------------------------------------------------------------------- Ez a hiba akkor jelentkezik, ha a PHP-t a 8.1-es verzióra frissítette, de a Nette-et használja, amely nem kompatibilis vele. A megoldás tehát a Nette újabb verzióra való frissítése a `composer update` segítségével. A Nette a 3.0-s verzió óta támogatja a PHP 8.1-es verzióját. Ha régebbi verziót használ (ezt a `composer.json` oldalon találja meg), [frissítse a Nette-et |migrations:en], vagy maradjon a PHP 8.0-nál. diff --git a/nette/it/troubleshooting.texy b/nette/it/troubleshooting.texy index 38016d0bfb..da0869ae5c 100644 --- a/nette/it/troubleshooting.texy +++ b/nette/it/troubleshooting.texy @@ -32,6 +32,13 @@ Errore 404, il routing non funziona .[#toc-error-404-routing-not-working] Quando tutte le pagine (tranne la homepage) restituiscono un errore 404, sembra che ci sia un problema di configurazione del server per gli [URL più belli |#How to Configure a Server for Nice URLs?]. +Come disattivare la cache durante lo sviluppo? .[#toc-how-to-disable-cache-during-development] +---------------------------------------------------------------------------------------------- +Nette è intelligente e non è necessario disabilitare la cache. Durante lo sviluppo, aggiorna automaticamente la cache ogni volta che c'è un cambiamento nel template o nella configurazione del contenitore DI. Inoltre, la modalità di sviluppo è attivata dal rilevamento automatico, quindi di solito non è necessario configurare nulla, [o solo l'indirizzo IP |application:bootstrap#development-vs-production-mode]. + +Quando si esegue il debug del router, si consiglia di disabilitare la cache del browser, dove, ad esempio, potrebbero essere memorizzati i reindirizzamenti: aprire gli Strumenti per gli sviluppatori (Ctrl+Maiusc+I o Cmd+Option+I) e, nel pannello Rete, selezionare la casella per disabilitare la cache. + + Errore `#[\ReturnTypeWillChange] attribute should be used` .[#toc-error-returntypewillchange-attribute-should-be-used] ---------------------------------------------------------------------------------------------------------------------- Questo errore si verifica se si è aggiornato PHP alla versione 8.1 ma si sta utilizzando Nette, che non è compatibile con essa. La soluzione è aggiornare Nette a una versione più recente utilizzando `composer update`. Nette supporta PHP 8.1 dalla versione 3.0. Se si sta utilizzando una versione più vecchia (lo si può scoprire consultando `composer.json`), [aggiornare Nette |migrations:en] o rimanere con PHP 8.0. diff --git a/nette/pl/troubleshooting.texy b/nette/pl/troubleshooting.texy index f51c01be14..6a5a9aab0d 100644 --- a/nette/pl/troubleshooting.texy +++ b/nette/pl/troubleshooting.texy @@ -32,6 +32,13 @@ Błąd 404, routing nie działa .[#toc-error-404-routing-not-working] Kiedy wszystkie strony (oprócz strony głównej) zwracają błąd 404, wygląda to na problem z konfiguracją serwera dla [ładnych adresów URL |#How to Configure a Server for Nice URLs?]. +Jak wyłączyć pamięć podręczną podczas programowania? .[#toc-how-to-disable-cache-during-development] +---------------------------------------------------------------------------------------------------- +Nette jest inteligentny i nie trzeba w nim wyłączać buforowania. Podczas programowania automatycznie aktualizuje pamięć podręczną za każdym razem, gdy nastąpi zmiana w szablonie lub konfiguracji kontenera DI. Co więcej, tryb deweloperski jest aktywowany przez automatyczne wykrywanie, więc zwykle nie ma potrzeby konfigurowania czegokolwiek [lub tylko adresu IP |application:bootstrap#development-vs-production-mode]. + +Podczas debugowania routera zalecamy wyłączenie pamięci podręcznej przeglądarki, w której mogą być przechowywane na przykład przekierowania: otwórz Narzędzia deweloperskie (Ctrl+Shift+I lub Cmd+Option+I) i w panelu Sieć zaznacz pole, aby wyłączyć pamięć podręczną. + + Błąd `#[\ReturnTypeWillChange] attribute should be used` .[#toc-error-returntypewillchange-attribute-should-be-used] -------------------------------------------------------------------------------------------------------------------- Ten błąd pojawia się, jeśli zaktualizowałeś PHP do wersji 8.1, ale używasz Nette, która nie jest z nim kompatybilna. Rozwiązaniem jest więc aktualizacja Nette do nowszej wersji za pomocą `composer update`. Nette wspiera PHP 8.1 od wersji 3.0. Jeśli używasz starszej wersji (możesz to sprawdzić zaglądając na stronę `composer.json`), [zaktualizuj Nette |migrations:en] lub pozostań przy PHP 8.0. diff --git a/nette/pt/troubleshooting.texy b/nette/pt/troubleshooting.texy index 37f15320ca..bd64f473e0 100644 --- a/nette/pt/troubleshooting.texy +++ b/nette/pt/troubleshooting.texy @@ -32,6 +32,13 @@ Erro 404, roteamento não funciona .[#toc-error-404-routing-not-working] Quando todas as páginas (exceto a página inicial) retornam um erro 404, parece um problema de configuração do servidor para [URLs bonitas |#How to Configure a Server for Nice URLs?]. +Como desativar o cache durante o desenvolvimento? .[#toc-how-to-disable-cache-during-development] +------------------------------------------------------------------------------------------------- +O Nette é inteligente, e você não precisa desativar o cache nele. Durante o desenvolvimento, ele atualiza automaticamente o cache sempre que há uma alteração no modelo ou na configuração do contêiner DI. Além disso, o modo de desenvolvimento é ativado por detecção automática, portanto, normalmente não há necessidade de configurar nada, [ou apenas o endereço IP |application:bootstrap#development-vs-production-mode]. + +Ao depurar o roteador, recomendamos desativar o cache do navegador, onde, por exemplo, os redirecionamentos podem ser armazenados: abra o Developer Tools (Ctrl+Shift+I ou Cmd+Option+I) e, no painel Network, marque a caixa para desativar o cache. + + Erro `#[\ReturnTypeWillChange] attribute should be used` .[#toc-error-returntypewillchange-attribute-should-be-used] -------------------------------------------------------------------------------------------------------------------- Este erro ocorre se você tiver atualizado o PHP para a versão 8.1, mas estiver usando Nette, que não é compatível com ele. Portanto, a solução é atualizar o Nette para uma versão mais recente usando `composer update`. Nette suporta o PHP 8.1 desde a versão 3.0. Se você estiver usando uma versão mais antiga (você pode descobrir procurando em `composer.json`), [atualize Nette |migrations:en] ou fique com o PHP 8.0. diff --git a/nette/ro/troubleshooting.texy b/nette/ro/troubleshooting.texy index 254c6434ec..dfe631e766 100644 --- a/nette/ro/troubleshooting.texy +++ b/nette/ro/troubleshooting.texy @@ -32,6 +32,13 @@ Eroare 404, rutarea nu funcționează .[#toc-error-404-routing-not-working] Atunci când toate paginile (cu excepția paginii de start) returnează o eroare 404, se pare că este vorba de o problemă de configurare a serverului pentru [URL-urile frumoase |#How to Configure a Server for Nice URLs?]. +Cum se dezactivează memoria cache în timpul dezvoltării? .[#toc-how-to-disable-cache-during-development] +-------------------------------------------------------------------------------------------------------- +Nette este inteligent și nu este nevoie să dezactivați memoria cache în el. În timpul dezvoltării, acesta actualizează automat memoria cache ori de câte ori există o modificare în șablon sau în configurația containerului DI. Mai mult, modul de dezvoltare este activat prin autodetecție, așa că, de obicei, nu este nevoie să configurați nimic, [sau doar adresa IP |application:bootstrap#development-vs-production-mode]. + +Atunci când depanați routerul, vă recomandăm să dezactivați memoria cache a browserului, unde, de exemplu, ar putea fi stocate redirecționările: deschideți Developer Tools (Ctrl+Shift+I sau Cmd+Option+I) și în panoul Network (Rețea), bifați caseta pentru dezactivarea memoriei cache. + + Eroare `#[\ReturnTypeWillChange] attribute should be used` .[#toc-error-returntypewillchange-attribute-should-be-used] ---------------------------------------------------------------------------------------------------------------------- Această eroare apare în cazul în care ați actualizat PHP la versiunea 8.1, dar utilizați Nette, care nu este compatibil cu aceasta. Așadar, soluția este să actualizați Nette la o versiune mai nouă folosind `composer update`. Nette suportă PHP 8.1 încă de la versiunea 3.0. Dacă folosiți o versiune mai veche (puteți afla căutând în `composer.json`), [actualizați Nette |migrations:en] sau rămâneți cu PHP 8.0. diff --git a/nette/ru/troubleshooting.texy b/nette/ru/troubleshooting.texy index 4717eed854..7f9776b64a 100644 --- a/nette/ru/troubleshooting.texy +++ b/nette/ru/troubleshooting.texy @@ -32,6 +32,13 @@ Tracy сообщит, почему он не может вести журнал. Когда все страницы (кроме домашней) выдают ошибку 404, это похоже на проблему конфигурации сервера для [красивых URL |#How to Configure a Server for Nice URLs?]. +Как отключить кэш во время разработки? .[#toc-how-to-disable-cache-during-development] +-------------------------------------------------------------------------------------- +Nette - умный продукт, и отключать кэширование в нем не нужно. Во время разработки он автоматически обновляет кэш при каждом изменении шаблона или конфигурации DI-контейнера. Более того, режим разработки включается по автоопределению, поэтому обычно не требуется ничего настраивать, [или только IP-адрес |application:bootstrap#development-vs-production-mode]. + +При отладке маршрутизатора рекомендуется отключить кэш браузера, в котором, например, могут храниться редиректы: откройте Developer Tools (Ctrl+Shift+I или Cmd+Option+I) и в панели Network установите флажок на отключение кэша. + + Ошибка `#[\ReturnTypeWillChange] attribute should be used` .[#toc-error-returntypewillchange-attribute-should-be-used] ---------------------------------------------------------------------------------------------------------------------- Эта ошибка возникает, если вы обновили PHP до версии 8.1, но используете Nette, который не совместим с ней. Поэтому решением является обновление Nette до более новой версии с помощью `composer update`. Nette поддерживает PHP 8.1 с версии 3.0. Если вы используете более старую версию (вы можете узнать это, посмотрев в `composer.json`), [обновите Nette |migrations:en] или оставайтесь с PHP 8.0. diff --git a/nette/sl/troubleshooting.texy b/nette/sl/troubleshooting.texy index 846f03b532..67dfe0c7e0 100644 --- a/nette/sl/troubleshooting.texy +++ b/nette/sl/troubleshooting.texy @@ -32,6 +32,13 @@ Napaka 404, usmerjanje ne deluje .[#toc-error-404-routing-not-working] Če vse strani (razen domače strani) vrnejo napako 404, je videti, da gre za težavo s konfiguracijo strežnika za [lepe naslove URL |#How to Configure a Server for Nice URLs?]. +Kako onemogočiti predpomnilnik med razvojem? .[#toc-how-to-disable-cache-during-development] +-------------------------------------------------------------------------------------------- +Nette je pameten in v njem vam ni treba onemogočiti predpomnjenja. Med razvojem samodejno posodablja predpomnilnik, kadar koli se spremeni predlogo ali konfiguracija vsebnika DI. Poleg tega se razvojni način aktivira s samodejnim zaznavanjem, zato običajno ni treba nastavljati ničesar [ali le naslova IP |application:bootstrap#development-vs-production-mode]. + +Pri odpravljanju napak v usmerjevalniku priporočamo, da onemogočite predpomnilnik brskalnika, v katerem so na primer lahko shranjene preusmeritve: odprite Razvojna orodja (Ctrl+Shift+I ali Cmd+Option+I) in na plošči Omrežje označite polje za onemogočanje predpomnilnika. + + Napaka `#[\ReturnTypeWillChange] attribute should be used` .[#toc-error-returntypewillchange-attribute-should-be-used] ---------------------------------------------------------------------------------------------------------------------- Ta napaka se pojavi, če ste PHP nadgradili na različico 8.1, vendar uporabljate Nette, ki z njo ni združljiv. Rešitev je, da Nette posodobite na novejšo različico z uporabo `composer update`. Nette podpira PHP 8.1 od različice 3.0. Če uporabljate starejšo različico (to lahko ugotovite z vpogledom v `composer.json`), [nadgradite Nette |migrations:en] ali pa ostanite pri PHP 8.0. diff --git a/nette/tr/troubleshooting.texy b/nette/tr/troubleshooting.texy index 1bfffdea1c..9695448067 100644 --- a/nette/tr/troubleshooting.texy +++ b/nette/tr/troubleshooting.texy @@ -32,6 +32,13 @@ Hata 404, yönlendirme çalışmıyor .[#toc-error-404-routing-not-working] Tüm sayfalar (ana sayfa hariç) 404 hatası döndürdüğünde, [güzel URL' |#How to Configure a Server for Nice URLs?]ler için bir sunucu yapılandırma sorunu gibi görünür. +Geliştirme Sırasında Önbellek Nasıl Devre Dışı Bırakılır? .[#toc-how-to-disable-cache-during-development] +--------------------------------------------------------------------------------------------------------- +Nette akıllıdır ve içinde önbelleği devre dışı bırakmanıza gerek yoktur. Geliştirme sırasında, şablonda veya DI konteyner yapılandırmasında bir değişiklik olduğunda önbelleği otomatik olarak günceller. Dahası, geliştirme modu otomatik algılama ile etkinleştirilir, bu nedenle genellikle herhangi bir şeyi [veya yalnızca IP adresini |application:bootstrap#development-vs-production-mode] yapılandırmaya gerek yoktur. + +Yönlendiricide hata ayıklarken, örneğin yönlendirmelerin depolanabileceği tarayıcı önbelleğini devre dışı bırakmanızı öneririz: Geliştirici Araçları'nı açın (Ctrl+Shift+I veya Cmd+Option+I) ve Ağ panelinde önbelleği devre dışı bırakmak için kutuyu işaretleyin. + + Hata `#[\ReturnTypeWillChange] attribute should be used` .[#toc-error-returntypewillchange-attribute-should-be-used] -------------------------------------------------------------------------------------------------------------------- Bu hata, PHP'yi 8.1 sürümüne yükselttiyseniz ancak onunla uyumlu olmayan Nette kullanıyorsanız ortaya çıkar. Çözüm, `composer update` adresini kullanarak Nette'yi daha yeni bir sürüme güncellemektir. Nette, PHP 8.1'i 3.0 sürümünden beri desteklemektedir. Daha eski bir sürüm kullanıyorsanız ( `composer.json` adresine bakarak öğrenebilirsiniz), Nette'yi [yükseltin |migrations:en] veya PHP 8.0 ile kalın. diff --git a/nette/uk/troubleshooting.texy b/nette/uk/troubleshooting.texy index 0819381017..0eee4e5e76 100644 --- a/nette/uk/troubleshooting.texy +++ b/nette/uk/troubleshooting.texy @@ -32,6 +32,13 @@ Tracy повідомить вам, чому вона не може вести ж Коли всі сторінки (крім головної) повертають помилку 404, це схоже на проблему конфігурації сервера для [красивих URL-адрес |#How to Configure a Server for Nice URLs?]. +Як відключити кеш під час розробки? .[#toc-how-to-disable-cache-during-development] +----------------------------------------------------------------------------------- +Nette розумний, і вам не потрібно відключати кешування в ньому. Під час розробки він автоматично оновлює кеш щоразу, коли змінюється шаблон або конфігурація контейнера DI. Більше того, режим розробки активується за допомогою автоматичного визначення, тому зазвичай не потрібно нічого налаштовувати, окрім [IP-адреси |application:bootstrap#development-vs-production-mode]. + +Під час налагодження роутера ми рекомендуємо вимкнути кеш браузера, де можуть зберігатися, наприклад, редиректи: відкрийте Інструменти розробника (Ctrl+Shift+I або Cmd+Option+I) і в панелі "Мережа" поставте галочку, щоб вимкнути кеш. + + Помилка `#[\ReturnTypeWillChange] attribute should be used` .[#toc-error-returntypewillchange-attribute-should-be-used] ----------------------------------------------------------------------------------------------------------------------- Ця помилка виникає, якщо ви оновили PHP до версії 8.1, але використовуєте Nette, який не сумісний з нею. Тому рішенням є оновлення Nette до новішої версії за допомогою `composer update`. Nette підтримує PHP 8.1 з версії 3.0. Якщо ви використовуєте старішу версію (ви можете дізнатися це, подивившись у `composer.json`), [оновіть Nette |migrations:en] або залишайтеся з PHP 8.0. From b34a7ca20929fbd4729f641d6ea68ca48ef9aee8 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 5 Oct 2023 04:18:01 +0200 Subject: [PATCH 015/137] typo [closes #1022] --- application/bg/ajax.texy | 4 ++-- application/cs/ajax.texy | 4 ++-- application/de/ajax.texy | 4 ++-- application/el/ajax.texy | 4 ++-- application/en/ajax.texy | 4 ++-- application/es/ajax.texy | 4 ++-- application/fr/ajax.texy | 4 ++-- application/hu/ajax.texy | 4 ++-- application/it/ajax.texy | 4 ++-- application/pl/ajax.texy | 4 ++-- application/pt/ajax.texy | 4 ++-- application/ro/ajax.texy | 4 ++-- application/ru/ajax.texy | 4 ++-- application/sl/ajax.texy | 4 ++-- application/tr/ajax.texy | 4 ++-- application/uk/ajax.texy | 4 ++-- 16 files changed, 32 insertions(+), 32 deletions(-) diff --git a/application/bg/ajax.texy b/application/bg/ajax.texy index 1bcf75bc98..dfb8f9f929 100644 --- a/application/bg/ajax.texy +++ b/application/bg/ajax.texy @@ -156,7 +156,7 @@ $this->isControlInvalid('footer'); // -> true ```latte ``` @@ -241,7 +241,7 @@ $this->redrawControl('item'); {snippet wholeList} {/snippet} diff --git a/application/cs/ajax.texy b/application/cs/ajax.texy index e4d30f762a..18e53a91a5 100644 --- a/application/cs/ajax.texy +++ b/application/cs/ajax.texy @@ -156,7 +156,7 @@ Nette také umožňuje používání snippetů, jejichž název se vytvoří až ```latte
    {foreach $list as $id => $item} -
  • {$item} update
  • +
  • {$item} update
  • {/foreach}
``` @@ -241,7 +241,7 @@ V takovém případě je nejjednodušší celý ten seznam obalit ještě jední {snippet wholeList}
    {foreach $list as $id => $item} -
  • {$item} update
  • +
  • {$item} update
  • {/foreach}
{/snippet} diff --git a/application/de/ajax.texy b/application/de/ajax.texy index 63922c5732..12a3014a57 100644 --- a/application/de/ajax.texy +++ b/application/de/ajax.texy @@ -156,7 +156,7 @@ In Nette können Sie auch Snippets mit einem dynamischen Namen definieren, der a ```latte
    {foreach $list as $id => $item} -
  • {$item} update
  • +
  • {$item} update
  • {/foreach}
``` @@ -241,7 +241,7 @@ In diesem Fall besteht die einfachste Möglichkeit darin, die gesamte Liste in e {snippet wholeList}
    {foreach $list as $id => $item} -
  • {$item} update
  • +
  • {$item} update
  • {/foreach}
{/snippet} diff --git a/application/el/ajax.texy b/application/el/ajax.texy index 8ca0741a48..08df9e3fc2 100644 --- a/application/el/ajax.texy +++ b/application/el/ajax.texy @@ -156,7 +156,7 @@ $this->isControlInvalid('footer'); // -> true ```latte
    {foreach $list as $id => $item} -
  • {$item} update
  • +
  • {$item} update
  • {/foreach}
``` @@ -241,7 +241,7 @@ $this->redrawControl('item'); {snippet wholeList}
    {foreach $list as $id => $item} -
  • {$item} update
  • +
  • {$item} update
  • {/foreach}
{/snippet} diff --git a/application/en/ajax.texy b/application/en/ajax.texy index f43ff28c2f..6077456b78 100644 --- a/application/en/ajax.texy +++ b/application/en/ajax.texy @@ -156,7 +156,7 @@ In Nette you can also define snippets with a dynamic name based on a runtime par ```latte
    {foreach $list as $id => $item} -
  • {$item} update
  • +
  • {$item} update
  • {/foreach}
``` @@ -241,7 +241,7 @@ In this case, the simplest way is to wrap the whole list in one more snippet and {snippet wholeList}
    {foreach $list as $id => $item} -
  • {$item} update
  • +
  • {$item} update
  • {/foreach}
{/snippet} diff --git a/application/es/ajax.texy b/application/es/ajax.texy index 0ba8886dd4..db292160c4 100644 --- a/application/es/ajax.texy +++ b/application/es/ajax.texy @@ -156,7 +156,7 @@ En Nette también puede definir fragmentos con un nombre dinámico basado en un ```latte
    {foreach $list as $id => $item} -
  • {$item} update
  • +
  • {$item} update
  • {/foreach}
``` @@ -241,7 +241,7 @@ En este caso, la forma más sencilla es envolver toda la lista en un fragmento m {snippet wholeList}
    {foreach $list as $id => $item} -
  • {$item} update
  • +
  • {$item} update
  • {/foreach}
{/snippet} diff --git a/application/fr/ajax.texy b/application/fr/ajax.texy index 55c07c6dc6..7e05c20cdc 100644 --- a/application/fr/ajax.texy +++ b/application/fr/ajax.texy @@ -156,7 +156,7 @@ Dans Nette, vous pouvez également définir des snippets avec un nom dynamique b ```latte
    {foreach $list as $id => $item} -
  • {$item} update
  • +
  • {$item} update
  • {/foreach}
``` @@ -241,7 +241,7 @@ Dans ce cas, le moyen le plus simple est d'envelopper toute la liste dans un aut {snippet wholeList}
    {foreach $list as $id => $item} -
  • {$item} update
  • +
  • {$item} update
  • {/foreach}
{/snippet} diff --git a/application/hu/ajax.texy b/application/hu/ajax.texy index fb0a6e08b8..e086df6f19 100644 --- a/application/hu/ajax.texy +++ b/application/hu/ajax.texy @@ -156,7 +156,7 @@ A Nette-ben egy futásidejű paraméter alapján dinamikus névvel ellátott sni ```latte
    {foreach $list as $id => $item} -
  • {$item} update
  • +
  • {$item} update
  • {/foreach}
``` @@ -241,7 +241,7 @@ Ebben az esetben a legegyszerűbb megoldás, ha az egész listát még egy snipp {snippet wholeList}
    {foreach $list as $id => $item} -
  • {$item} update
  • +
  • {$item} update
  • {/foreach}
{/snippet} diff --git a/application/it/ajax.texy b/application/it/ajax.texy index 61d7bcd9ca..e6fd52b425 100644 --- a/application/it/ajax.texy +++ b/application/it/ajax.texy @@ -156,7 +156,7 @@ In Nette è possibile definire snippet con un nome dinamico basato su un paramet ```latte
    {foreach $list as $id => $item} -
  • {$item} update
  • +
  • {$item} update
  • {/foreach}
``` @@ -241,7 +241,7 @@ In questo caso, il modo più semplice è avvolgere l'intero elenco in un altro f {snippet wholeList}
    {foreach $list as $id => $item} -
  • {$item} update
  • +
  • {$item} update
  • {/foreach}
{/snippet} diff --git a/application/pl/ajax.texy b/application/pl/ajax.texy index 4b42eac748..6dbade07b9 100644 --- a/application/pl/ajax.texy +++ b/application/pl/ajax.texy @@ -156,7 +156,7 @@ Nette pozwala również na stosowanie snippetów, których nazwa jest tworzona w ```latte
    {foreach $list as $id => $item} -
  • {$item} update
  • +
  • {$item} update
  • {/foreach}
``` @@ -241,7 +241,7 @@ W takim przypadku najłatwiej jest owinąć całą listę jeszcze jednym snippet {snippet wholeList}
    {foreach $list as $id => $item} -
  • {$item} update
  • +
  • {$item} update
  • {/foreach}
{/snippet} diff --git a/application/pt/ajax.texy b/application/pt/ajax.texy index 2ef450e4d6..63906ac5e1 100644 --- a/application/pt/ajax.texy +++ b/application/pt/ajax.texy @@ -156,7 +156,7 @@ Em Nette você também pode definir trechos com um nome dinâmico baseado em um ```latte
    {foreach $list as $id => $item} -
  • {$item} update
  • +
  • {$item} update
  • {/foreach}
``` @@ -241,7 +241,7 @@ Neste caso, a maneira mais simples é envolver toda a lista em mais um trecho e {snippet wholeList}
    {foreach $list as $id => $item} -
  • {$item} update
  • +
  • {$item} update
  • {/foreach}
{/snippet} diff --git a/application/ro/ajax.texy b/application/ro/ajax.texy index 145ab87fdd..ce4963a704 100644 --- a/application/ro/ajax.texy +++ b/application/ro/ajax.texy @@ -156,7 +156,7 @@ Snippets dinamice .[#toc-dynamic-snippets] ```latte
    {foreach $list as $id => $item} -
  • {$item} update
  • +
  • {$item} update
  • {/foreach}
``` @@ -241,7 +241,7 @@ Dacă adăugați un nou element în listă și invalidați `itemsContainer`, cer {snippet wholeList}
    {foreach $list as $id => $item} -
  • {$item} update
  • +
  • {$item} update
  • {/foreach}
{/snippet} diff --git a/application/ru/ajax.texy b/application/ru/ajax.texy index 6009fc864c..8815f25f16 100644 --- a/application/ru/ajax.texy +++ b/application/ru/ajax.texy @@ -156,7 +156,7 @@ $this->isControlInvalid('footer'); // -> true ```latte ``` @@ -241,7 +241,7 @@ $this->redrawControl('item'); {snippet wholeList} {/snippet} diff --git a/application/sl/ajax.texy b/application/sl/ajax.texy index 1d982a2057..6e285a54ed 100644 --- a/application/sl/ajax.texy +++ b/application/sl/ajax.texy @@ -156,7 +156,7 @@ V programu Nette lahko na podlagi parametra v času izvajanja določite tudi din ```latte
    {foreach $list as $id => $item} -
  • {$item} update
  • +
  • {$item} update
  • {/foreach}
``` @@ -241,7 +241,7 @@ V tem primeru je najpreprostejši način, da celoten seznam zavijete v še en iz {snippet wholeList}
    {foreach $list as $id => $item} -
  • {$item} update
  • +
  • {$item} update
  • {/foreach}
{/snippet} diff --git a/application/tr/ajax.texy b/application/tr/ajax.texy index 2502de3b69..2252cb0a0a 100644 --- a/application/tr/ajax.texy +++ b/application/tr/ajax.texy @@ -156,7 +156,7 @@ Nette'de ayrıca bir çalışma zamanı parametresine dayalı olarak dinamik bir ```latte
    {foreach $list as $id => $item} -
  • {$item} update
  • +
  • {$item} update
  • {/foreach}
``` @@ -241,7 +241,7 @@ Bu durumda, en basit yol tüm listeyi bir parçacığa daha sarmak ve hepsini ge {snippet wholeList}
    {foreach $list as $id => $item} -
  • {$item} update
  • +
  • {$item} update
  • {/foreach}
{/snippet} diff --git a/application/uk/ajax.texy b/application/uk/ajax.texy index 657629160c..df78fc20b8 100644 --- a/application/uk/ajax.texy +++ b/application/uk/ajax.texy @@ -156,7 +156,7 @@ $this->isControlInvalid('footer'); // -> true ```latte ``` @@ -241,7 +241,7 @@ $this->redrawControl('item'); {snippet wholeList} {/snippet} From 40e17f5056188ad3e01224205ebd796da953edba Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 2 Oct 2023 22:12:57 +0200 Subject: [PATCH 016/137] nette/di v3.1.8 [Closes #1031] --- dependency-injection/bg/autowiring.texy | 2 +- dependency-injection/bg/configuration.texy | 2 +- dependency-injection/cs/autowiring.texy | 2 +- dependency-injection/cs/configuration.texy | 2 +- dependency-injection/de/autowiring.texy | 2 +- dependency-injection/de/configuration.texy | 2 +- dependency-injection/el/autowiring.texy | 2 +- dependency-injection/el/configuration.texy | 2 +- dependency-injection/en/autowiring.texy | 2 +- dependency-injection/en/configuration.texy | 2 +- dependency-injection/es/autowiring.texy | 2 +- dependency-injection/es/configuration.texy | 2 +- dependency-injection/fr/autowiring.texy | 2 +- dependency-injection/fr/configuration.texy | 2 +- dependency-injection/hu/autowiring.texy | 2 +- dependency-injection/hu/configuration.texy | 2 +- dependency-injection/it/autowiring.texy | 2 +- dependency-injection/it/configuration.texy | 2 +- dependency-injection/ja/autowiring.texy | 2 +- dependency-injection/ja/configuration.texy | 2 +- dependency-injection/pl/autowiring.texy | 2 +- dependency-injection/pl/configuration.texy | 2 +- dependency-injection/pt/autowiring.texy | 2 +- dependency-injection/pt/configuration.texy | 2 +- dependency-injection/ro/autowiring.texy | 2 +- dependency-injection/ro/configuration.texy | 2 +- dependency-injection/ru/autowiring.texy | 2 +- dependency-injection/ru/configuration.texy | 2 +- dependency-injection/sl/autowiring.texy | 2 +- dependency-injection/sl/configuration.texy | 2 +- dependency-injection/tr/autowiring.texy | 2 +- dependency-injection/tr/configuration.texy | 2 +- dependency-injection/uk/autowiring.texy | 2 +- dependency-injection/uk/configuration.texy | 2 +- 34 files changed, 34 insertions(+), 34 deletions(-) diff --git a/dependency-injection/bg/autowiring.texy b/dependency-injection/bg/autowiring.texy index 3b826597cd..acefa451a3 100644 --- a/dependency-injection/bg/autowiring.texy +++ b/dependency-injection/bg/autowiring.texy @@ -105,7 +105,7 @@ class ShipManager След това контейнерът DI автоматично ще предаде масив от услуги, отговарящи на зададения тип. Това ще доведе до пропускане на услуги с деактивирано автоматично свързване. -Ако не можете да контролирате формата за коментари на phpDoc, можете да подадете масив от услуги директно в конфигурацията, като използвате [`typed()` |services#Special-Functions]. +Типът в коментара може да бъде и под формата `array` или `list`. Ако не можете да контролирате формата на phpDoc коментара, можете да подадете масив от услуги директно в конфигурацията, като използвате [`typed()` |services#Special Functions]. Скаларни аргументи .[#toc-scalar-arguments] diff --git a/dependency-injection/bg/configuration.texy b/dependency-injection/bg/configuration.texy index 583f748030..632d2f7f8c 100644 --- a/dependency-injection/bg/configuration.texy +++ b/dependency-injection/bg/configuration.texy @@ -122,7 +122,7 @@ di: - Symfony\Component\Console\Application ``` -Ако не използвате масива `$container->parameters`, можете да деактивирате експортирането на параметри. Като алтернатива можете да експортирате само тези тагове, чрез които получавате услуги, като използвате метода `$container->findByTag(...)`. +Ако не използвате масива `$container->getParameters()`, можете да деактивирате експортирането на параметри. Като алтернатива можете да експортирате само тези тагове, чрез които получавате услуги, като използвате метода `$container->findByTag(...)`. Ако изобщо не извиквате този метод, можете да деактивирате напълно експортирането на тагове, като посочите `false`. Можете значително да намалите метаданните за автоматичното свързване, като посочите класовете, които използвате, като параметър в метода `$container->getByType()`. diff --git a/dependency-injection/cs/autowiring.texy b/dependency-injection/cs/autowiring.texy index 3b2b4f8e0a..d1ae064b92 100644 --- a/dependency-injection/cs/autowiring.texy +++ b/dependency-injection/cs/autowiring.texy @@ -105,7 +105,7 @@ class ShipManager DI kontejner pak automaticky předá pole služeb odpovídajících danému typu. Vynechá služby, které mají vypnutý autowiring. -Pokud nemůžete ovlivnit podobu phpDoc komentáře, můžete předat pole služeb přímo v konfiguraci pomocí [`typed()`|services#Speciální funkce]. +Typ v komentáři může být také ve tvaru `array` nebo `list`. Pokud nemůžete ovlivnit podobu phpDoc komentáře, můžete předat pole služeb přímo v konfiguraci pomocí [`typed()`|services#Speciální funkce]. Skalární argumenty diff --git a/dependency-injection/cs/configuration.texy b/dependency-injection/cs/configuration.texy index 92061e1451..6381fe31dd 100644 --- a/dependency-injection/cs/configuration.texy +++ b/dependency-injection/cs/configuration.texy @@ -122,7 +122,7 @@ di: - Symfony\Component\Console\Application ``` -Pokud nevyužíváte pole `$container->parameters`, můžete vypnout export parametrů. Dále můžete exportovat jen ty tagy, přes které získáváte služby metodou `$container->findByTag(...)`. +Pokud nevyužíváte pole `$container->getParameters()`, můžete vypnout export parametrů. Dále můžete exportovat jen ty tagy, přes které získáváte služby metodou `$container->findByTag(...)`. Pokud metodu nevoláte vůbec, můžete zcela vypnout export tagů pomocí `false`. Výrazně můžete zredukovat metadata pro [autowiring] tím, že uvedete třídy, které používáte jako parametr metody `$container->getByType()`. diff --git a/dependency-injection/de/autowiring.texy b/dependency-injection/de/autowiring.texy index b5af4bf042..9d10e2249d 100644 --- a/dependency-injection/de/autowiring.texy +++ b/dependency-injection/de/autowiring.texy @@ -105,7 +105,7 @@ class ShipManager Der DI-Container übergibt dann automatisch ein Array von Diensten, die dem angegebenen Typ entsprechen. Er wird Dienste auslassen, bei denen die automatische Verdrahtung ausgeschaltet ist. -Wenn Sie die Form des phpDoc-Kommentars nicht kontrollieren können, können Sie ein Array von Diensten direkt in der Konfiguration übergeben, indem Sie [`typed()` |services#Special Functions]. +Der Typ des Kommentars kann auch in der Form `array` oder `list`. Wenn Sie die Form des phpDoc-Kommentars nicht kontrollieren können, können Sie ein Array von Diensten direkt in der Konfiguration übergeben, indem Sie [`typed()` |services#Special Functions]. Skalar-Argumente .[#toc-scalar-arguments] diff --git a/dependency-injection/de/configuration.texy b/dependency-injection/de/configuration.texy index e4baef85bb..1667c365d3 100644 --- a/dependency-injection/de/configuration.texy +++ b/dependency-injection/de/configuration.texy @@ -122,7 +122,7 @@ di: - Symfony\Component\Console\Application ``` -Wenn Sie das Array `$container->parameters` nicht verwenden, können Sie den Export der Parameter deaktivieren. Außerdem können Sie nur die Tags exportieren, über die Sie mit der Methode `$container->findByTag(...)` Dienste erhalten. +Wenn Sie das Array `$container->getParameters()` nicht verwenden, können Sie den Export der Parameter deaktivieren. Außerdem können Sie nur die Tags exportieren, über die Sie mit der Methode `$container->findByTag(...)` Dienste erhalten. Wenn Sie die Methode gar nicht aufrufen, können Sie den Tag-Export mit `false` vollständig deaktivieren. Sie können die Metadaten für die [automatische Verdrahtung |autowiring] erheblich reduzieren, indem Sie die von Ihnen verwendeten Klassen als Parameter für die Methode `$container->getByType()` angeben. diff --git a/dependency-injection/el/autowiring.texy b/dependency-injection/el/autowiring.texy index eec1365d62..58aa89e25e 100644 --- a/dependency-injection/el/autowiring.texy +++ b/dependency-injection/el/autowiring.texy @@ -105,7 +105,7 @@ class ShipManager Ο περιέκτης DI περνάει τότε αυτόματα έναν πίνακα υπηρεσιών που ταιριάζουν στον συγκεκριμένο τύπο. Θα παραλείψει τις υπηρεσίες που έχουν απενεργοποιήσει την αυτόματη καλωδίωση. -Αν δεν μπορείτε να ελέγξετε τη μορφή του σχολίου phpDoc, μπορείτε να περάσετε έναν πίνακα υπηρεσιών απευθείας στη διαμόρφωση χρησιμοποιώντας την εντολή [`typed()` |services#Special Functions]. +Ο τύπος στο σχόλιο μπορεί επίσης να είναι της μορφής `array` ή `list`. Αν δεν μπορείτε να ελέγξετε τη μορφή του σχολίου phpDoc, μπορείτε να περάσετε έναν πίνακα υπηρεσιών απευθείας στη ρύθμιση παραμέτρων χρησιμοποιώντας την εντολή [`typed()` |services#Special Functions]. Scalar Arguments .[#toc-scalar-arguments] diff --git a/dependency-injection/el/configuration.texy b/dependency-injection/el/configuration.texy index f08eb9b714..6eb46f33c4 100644 --- a/dependency-injection/el/configuration.texy +++ b/dependency-injection/el/configuration.texy @@ -122,7 +122,7 @@ di: - Symfony\Component\Console\Application ``` -Εάν δεν χρησιμοποιείτε τον πίνακα `$container->parameters`, μπορείτε να απενεργοποιήσετε την εξαγωγή παραμέτρων. Επιπλέον, μπορείτε να εξάγετε μόνο τις ετικέτες μέσω των οποίων λαμβάνετε υπηρεσίες χρησιμοποιώντας τη μέθοδο `$container->findByTag(...)`. +Εάν δεν χρησιμοποιείτε τον πίνακα `$container->getParameters()`, μπορείτε να απενεργοποιήσετε την εξαγωγή παραμέτρων. Επιπλέον, μπορείτε να εξάγετε μόνο τις ετικέτες μέσω των οποίων λαμβάνετε υπηρεσίες χρησιμοποιώντας τη μέθοδο `$container->findByTag(...)`. Αν δεν καλείτε καθόλου τη μέθοδο, μπορείτε να απενεργοποιήσετε εντελώς την εξαγωγή ετικετών με τη μέθοδο `false`. Μπορείτε να μειώσετε σημαντικά τα μεταδεδομένα για την [αυτόματη καλωδίωση |autowiring], καθορίζοντας τις κλάσεις που χρησιμοποιείτε ως παράμετρο στη μέθοδο `$container->getByType()`. diff --git a/dependency-injection/en/autowiring.texy b/dependency-injection/en/autowiring.texy index 92c827f3de..c4c2a6728a 100644 --- a/dependency-injection/en/autowiring.texy +++ b/dependency-injection/en/autowiring.texy @@ -105,7 +105,7 @@ class ShipManager The DI container then automatically passes an array of services matching the given type. It will omit services that have autowiring turned off. -If you can't control the form of the phpDoc comment, you can pass an array of services directly in the configuration using [`typed()`|services#Special Functions]. +The type in the comment can also be of the form `array` or `list`. If you can't control the form of the phpDoc comment, you can pass an array of services directly in the configuration using [`typed()`|services#Special Functions]. Scalar Arguments diff --git a/dependency-injection/en/configuration.texy b/dependency-injection/en/configuration.texy index 9a4e4893cb..2f956842bc 100644 --- a/dependency-injection/en/configuration.texy +++ b/dependency-injection/en/configuration.texy @@ -122,7 +122,7 @@ di: - Symfony\Component\Console\Application ``` -If you don't use the `$container->parameters` array, you can disable parameter export. Furthermore, you can export only those tags through which you get services using the `$container->findByTag(...)` method. +If you don't use the `$container->getParameters()` array, you can disable parameter export. Furthermore, you can export only those tags through which you get services using the `$container->findByTag(...)` method. If you don't call the method at all, you can completely disable tag export with `false`. You can significantly reduce the metadata for [autowiring] by specifying the classes you use as a parameter to the `$container->getByType()` method. diff --git a/dependency-injection/es/autowiring.texy b/dependency-injection/es/autowiring.texy index 7a459f767c..3268f6a1a5 100644 --- a/dependency-injection/es/autowiring.texy +++ b/dependency-injection/es/autowiring.texy @@ -105,7 +105,7 @@ class ShipManager El contenedor DI pasa automáticamente una matriz de servicios que coinciden con el tipo dado. Omitirá los servicios que tengan desactivado el autowiring. -Si no puede controlar la forma del comentario phpDoc, puede pasar un array de servicios directamente en la configuración usando [`typed()`|services#Special Functions]. +El tipo en el comentario también puede ser de la forma `array` o `list`. Si no puede controlar la forma del comentario phpDoc, puede pasar un array de servicios directamente en la configuración usando [`typed()` |services#Special Functions]. Argumentos escalares .[#toc-scalar-arguments] diff --git a/dependency-injection/es/configuration.texy b/dependency-injection/es/configuration.texy index a952ee9bc5..ee2c113acb 100644 --- a/dependency-injection/es/configuration.texy +++ b/dependency-injection/es/configuration.texy @@ -122,7 +122,7 @@ di: - Symfony\Component\Console\Application ``` -Si no utilizas el array `$container->parameters`, puedes desactivar la exportación de parámetros. Además, puede exportar sólo aquellas etiquetas a través de las cuales obtiene servicios utilizando el método `$container->findByTag(...)`. +Si no utilizas el array `$container->getParameters()`, puedes desactivar la exportación de parámetros. Además, puede exportar sólo aquellas etiquetas a través de las cuales obtiene servicios utilizando el método `$container->findByTag(...)`. Si no llama al método en absoluto, puede desactivar completamente la exportación de etiquetas con `false`. Puede reducir significativamente los metadatos para [autowiring] especificando las clases que utiliza como parámetro del método `$container->getByType()`. diff --git a/dependency-injection/fr/autowiring.texy b/dependency-injection/fr/autowiring.texy index 1ab809a378..a1c95b780f 100644 --- a/dependency-injection/fr/autowiring.texy +++ b/dependency-injection/fr/autowiring.texy @@ -105,7 +105,7 @@ class ShipManager Le conteneur DI passe alors automatiquement un tableau de services correspondant au type donné. Il omettra les services dont le câblage automatique est désactivé. -Si vous ne pouvez pas contrôler la forme du commentaire phpDoc, vous pouvez passer un tableau de services directement dans la configuration en utilisant la commande [`typed()` |services#Special Functions]. +Le type dans le commentaire peut également être de la forme `array` ou `list`. Si vous ne pouvez pas contrôler la forme du commentaire phpDoc, vous pouvez passer un tableau de services directement dans la configuration en utilisant la commande [`typed()` |services#Special Functions]. Arguments scalaires .[#toc-scalar-arguments] diff --git a/dependency-injection/fr/configuration.texy b/dependency-injection/fr/configuration.texy index af47fe7a52..c6142b5867 100644 --- a/dependency-injection/fr/configuration.texy +++ b/dependency-injection/fr/configuration.texy @@ -122,7 +122,7 @@ di: - Symfony\Component\Console\Application ``` -Si vous n'utilisez pas le tableau `$container->parameters`, vous pouvez désactiver l'exportation des paramètres. En outre, vous pouvez exporter uniquement les balises par lesquelles vous obtenez des services en utilisant la méthode `$container->findByTag(...)`. +Si vous n'utilisez pas le tableau `$container->getParameters()`, vous pouvez désactiver l'exportation des paramètres. En outre, vous pouvez exporter uniquement les balises par lesquelles vous obtenez des services en utilisant la méthode `$container->findByTag(...)`. Si vous n'appelez pas du tout la méthode, vous pouvez désactiver complètement l'exportation des balises avec `false`. Vous pouvez réduire considérablement les métadonnées pour le [câblage automatique |autowiring] en spécifiant les classes que vous utilisez comme paramètre de la méthode `$container->getByType()`. diff --git a/dependency-injection/hu/autowiring.texy b/dependency-injection/hu/autowiring.texy index fd1c0b7e10..743d7cc478 100644 --- a/dependency-injection/hu/autowiring.texy +++ b/dependency-injection/hu/autowiring.texy @@ -105,7 +105,7 @@ class ShipManager A DI konténer ekkor automatikusan átadja a megadott típusnak megfelelő szolgáltatások tömbjét. Kihagyja azokat a szolgáltatásokat, amelyeknél az automatikus kapcsolás ki van kapcsolva. -Ha nem tudja ellenőrizni a phpDoc megjegyzés formáját, akkor közvetlenül a konfigurációban is átadhatja a szolgáltatások tömbjét a következővel [`typed()` |services#Special Functions]. +A megjegyzésben szereplő típus lehet a következő formájú is `array` vagy `list`. Ha nem tudja ellenőrizni a phpDoc megjegyzés formáját, akkor közvetlenül a konfigurációban átadhatja a szolgáltatások tömbjét a következővel [`typed()` |services#Special Functions]. Skaláris argumentumok .[#toc-scalar-arguments] diff --git a/dependency-injection/hu/configuration.texy b/dependency-injection/hu/configuration.texy index 63f920f291..3b883fe631 100644 --- a/dependency-injection/hu/configuration.texy +++ b/dependency-injection/hu/configuration.texy @@ -122,7 +122,7 @@ di: - Symfony\Component\Console\Application ``` -Ha nem használja a `$container->parameters` tömböt, kikapcsolhatja a paraméterek exportálását. Továbbá csak azokat a címkéket exportálhatja, amelyeken keresztül a `$container->findByTag(...)` módszerrel szolgáltatásokat kap. +Ha nem használja a `$container->getParameters()` tömböt, kikapcsolhatja a paraméterek exportálását. Továbbá csak azokat a címkéket exportálhatja, amelyeken keresztül a `$container->findByTag(...)` módszerrel szolgáltatásokat kap. Ha egyáltalán nem hívja meg a módszert, akkor a `false` segítségével teljesen letilthatja a címkék exportálását. Jelentősen csökkentheti az [autowiring |autowiring] metaadatait, ha a `$container->getByType()` metódus paramétereként megadja a használt osztályokat. diff --git a/dependency-injection/it/autowiring.texy b/dependency-injection/it/autowiring.texy index 35b1a3f2d4..3c94f70378 100644 --- a/dependency-injection/it/autowiring.texy +++ b/dependency-injection/it/autowiring.texy @@ -105,7 +105,7 @@ class ShipManager Il contenitore DI passa automaticamente un array di servizi che corrispondono al tipo dato. Ometterà i servizi che hanno il cablaggio automatico disattivato. -Se non si può controllare la forma del commento di phpDoc, si può passare un array di servizi direttamente nella configurazione, usando il metodo [`typed()` |services#Special Functions]. +Il tipo nel commento può anche essere della forma `array` oppure `list`. Se non si può controllare la forma del commento di phpDoc, si può passare un array di servizi direttamente nella configurazione usando [`typed()` |services#Special Functions]. Argomenti scalari .[#toc-scalar-arguments] diff --git a/dependency-injection/it/configuration.texy b/dependency-injection/it/configuration.texy index a4d17c7f7d..4307f5c7ad 100644 --- a/dependency-injection/it/configuration.texy +++ b/dependency-injection/it/configuration.texy @@ -122,7 +122,7 @@ di: - Symfony\Component\Console\Application ``` -Se non si usa l'array `$container->parameters`, si può disabilitare l'esportazione dei parametri. Inoltre, si possono esportare solo i tag attraverso i quali si ottengono servizi con il metodo `$container->findByTag(...)`. +Se non si usa l'array `$container->getParameters()`, si può disabilitare l'esportazione dei parametri. Inoltre, si possono esportare solo i tag attraverso i quali si ottengono servizi con il metodo `$container->findByTag(...)`. Se non si chiama affatto il metodo, si può disabilitare completamente l'esportazione dei tag con `false`. È possibile ridurre in modo significativo i metadati per il [cablaggio automatico |autowiring], specificando le classi utilizzate come parametro del metodo `$container->getByType()`. diff --git a/dependency-injection/ja/autowiring.texy b/dependency-injection/ja/autowiring.texy index b968fa720e..9d99f3d2fb 100644 --- a/dependency-injection/ja/autowiring.texy +++ b/dependency-injection/ja/autowiring.texy @@ -105,7 +105,7 @@ class ShipManager DI コンテナは、指定した型に対応するサービスの配列を自動的に渡します。DI コンテナは、指定した型に対応するサービスの配列を自動的に渡します。自動配線が無効になっているサービスは省略されます。 -phpDoc のコメントの形式を制御できない場合は、 サービスの配列を直接設定に渡すこともできます。 [`typed()` |services#Special Functions]. +コメントの型は、以下の形式も可能である。 `array`または `list`.phpDoc のコメントの形式を制御できない場合は、 サービスの配列を直接渡すこともできます。 [`typed()` |services#Special Functions]. スカラー引数 .[#toc-scalar-arguments] diff --git a/dependency-injection/ja/configuration.texy b/dependency-injection/ja/configuration.texy index 7bb044010c..a5e0019136 100644 --- a/dependency-injection/ja/configuration.texy +++ b/dependency-injection/ja/configuration.texy @@ -122,7 +122,7 @@ di: - Symfony\Component\Console\Application ``` -`$container->parameters` 配列を使用しない場合は、パラメータのエクスポートを無効にすることができます。さらに、`$container->findByTag(...)` メソッドを使って、サービスを取得するタグだけをエクスポートすることができます。 +`$container->getParameters()` 配列を使用しない場合は、パラメータのエクスポートを無効にすることができます。さらに、`$container->findByTag(...)` メソッドを使って、サービスを取得するタグだけをエクスポートすることができます。 このメソッドを全く呼び出さない場合は、`false` を使ってタグのエクスポートを完全に無効にすることができます。 `$container->getByType()` メソッドのパラメータとして使用するクラスを指定すれば、[自動配線の |autowiring]ためのメタデータを大幅に減らすことができます。 diff --git a/dependency-injection/pl/autowiring.texy b/dependency-injection/pl/autowiring.texy index e9c7612788..eba26cb570 100644 --- a/dependency-injection/pl/autowiring.texy +++ b/dependency-injection/pl/autowiring.texy @@ -105,7 +105,7 @@ class ShipManager Następnie kontener DI automatycznie przekaże tablicę usług pasujących do tego typu. Pominie usługi, które mają wyłączone autowiring. -Jeśli nie możesz kontrolować formy komentarza phpDoc, możesz przekazać pole usługi bezpośrednio w konfiguracji za pomocą [`typed()` |services#Special-Functions]. +Typ w komentarzu może mieć również postać `array` lub `list`. Jeśli nie możesz kontrolować formy komentarza phpDoc, możesz przekazać tablicę usług bezpośrednio w konfiguracji za pomocą [`typed()` |services#Special Functions]. Argumenty skalarne .[#toc-scalar-arguments] diff --git a/dependency-injection/pl/configuration.texy b/dependency-injection/pl/configuration.texy index e497fcd3b5..d40613b4ca 100644 --- a/dependency-injection/pl/configuration.texy +++ b/dependency-injection/pl/configuration.texy @@ -122,7 +122,7 @@ di: - Symfony\Component\Console\Application ``` -Jeśli nie używasz pola `$container->parameters`, możesz wyłączyć eksport parametrów. Można również wyeksportować tylko te tagi, za pośrednictwem których uzyskuje się usługi metodą `$container->findByTag(...)`. +Jeśli nie używasz pola `$container->getParameters()`, możesz wyłączyć eksport parametrów. Można również wyeksportować tylko te tagi, za pośrednictwem których uzyskuje się usługi metodą `$container->findByTag(...)`. Jeśli w ogóle nie wywołujesz metody, możesz całkowicie wyłączyć eksport tagów za pomocą `false`. Możesz znacznie zmniejszyć metadane dla [autowiring |autowiring], określając klasy, których używasz jako parametr metody `$container->getByType()`. diff --git a/dependency-injection/pt/autowiring.texy b/dependency-injection/pt/autowiring.texy index b970520160..94a303420b 100644 --- a/dependency-injection/pt/autowiring.texy +++ b/dependency-injection/pt/autowiring.texy @@ -105,7 +105,7 @@ class ShipManager O recipiente DI passa então automaticamente uma série de serviços que correspondem ao tipo dado. Ele irá omitir serviços que tenham a fiação automática desligada. -Se você não pode controlar a forma do comentário phpDoc, você pode passar uma série de serviços diretamente na configuração usando [`typed()` |services#Special Functions]. +O tipo no comentário também pode ter o formato `array` ou `list`. Se não for possível controlar a forma do comentário do phpDoc, você poderá passar uma matriz de serviços diretamente na configuração usando [`typed()` |services#Special Functions]. Argumentos escalares .[#toc-scalar-arguments] diff --git a/dependency-injection/pt/configuration.texy b/dependency-injection/pt/configuration.texy index 2c21c894db..985378810e 100644 --- a/dependency-injection/pt/configuration.texy +++ b/dependency-injection/pt/configuration.texy @@ -122,7 +122,7 @@ di: - Symfony\Component\Console\Application ``` -Se você não usar a matriz `$container->parameters`, você pode desativar a exportação de parâmetros. Além disso, você pode exportar somente as tags através das quais você obtém serviços usando o método `$container->findByTag(...)`. +Se você não usar a matriz `$container->getParameters()`, você pode desativar a exportação de parâmetros. Além disso, você pode exportar somente as tags através das quais você obtém serviços usando o método `$container->findByTag(...)`. Se você não chamar o método, você pode desabilitar completamente a exportação de tags com `false`. Você pode reduzir significativamente os metadados para a [fiação automática |autowiring] especificando as classes que você usa como parâmetro para o método `$container->getByType()`. diff --git a/dependency-injection/ro/autowiring.texy b/dependency-injection/ro/autowiring.texy index d9f7b90586..3a4b41cf82 100644 --- a/dependency-injection/ro/autowiring.texy +++ b/dependency-injection/ro/autowiring.texy @@ -105,7 +105,7 @@ class ShipManager Recipientul DI transmite apoi automat un array de servicii care corespund tipului dat. Acesta va omite serviciile care au cablarea automată dezactivată. -Dacă nu puteți controla forma comentariului phpDoc, puteți trece o matrice de servicii direct în configurație, utilizând [`typed()` |services#Special Functions]. +Tipul din comentariu poate fi, de asemenea, de forma `array` sau `list`. Dacă nu puteți controla forma comentariului phpDoc, puteți trece o matrice de servicii direct în configurație folosind [`typed()` |services#Special Functions]. Argumente scalare .[#toc-scalar-arguments] diff --git a/dependency-injection/ro/configuration.texy b/dependency-injection/ro/configuration.texy index 870d2ff9ba..eedc191b10 100644 --- a/dependency-injection/ro/configuration.texy +++ b/dependency-injection/ro/configuration.texy @@ -122,7 +122,7 @@ di: - Symfony\Component\Console\Application ``` -Dacă nu utilizați matricea `$container->parameters`, puteți dezactiva exportul de parametri. În plus, puteți exporta numai acele etichete prin care obțineți servicii utilizând metoda `$container->findByTag(...)`. +Dacă nu utilizați matricea `$container->getParameters()`, puteți dezactiva exportul de parametri. În plus, puteți exporta numai acele etichete prin care obțineți servicii utilizând metoda `$container->findByTag(...)`. Dacă nu apelați deloc metoda, puteți dezactiva complet exportul de etichete cu `false`. Puteți reduce în mod semnificativ metadatele pentru [cablarea |autowiring] automată prin specificarea claselor pe care le utilizați ca parametru pentru metoda `$container->getByType()`. diff --git a/dependency-injection/ru/autowiring.texy b/dependency-injection/ru/autowiring.texy index 1bf1746b0c..6c4a828720 100644 --- a/dependency-injection/ru/autowiring.texy +++ b/dependency-injection/ru/autowiring.texy @@ -105,7 +105,7 @@ class ShipManager Затем контейнер DI автоматически передает массив сервисов, соответствующих заданному типу. При этом будут пропущены сервисы, у которых отключено автосвязывание. -Если вы не можете контролировать форму комментария phpDoc, вы можете передать массив сервисов непосредственно в конфигурации, используя [`typed()`|services#Special-Functions]. +Тип в комментарии также может иметь вид `array` или `list`. Если нет возможности управлять формой комментария phpDoc, то можно передать массив сервисов непосредственно в конфигурации, используя [`typed()` |services#Special Functions]. Скалярные аргументы .[#toc-scalar-arguments] diff --git a/dependency-injection/ru/configuration.texy b/dependency-injection/ru/configuration.texy index 3d552530aa..4527e1e6b5 100644 --- a/dependency-injection/ru/configuration.texy +++ b/dependency-injection/ru/configuration.texy @@ -122,7 +122,7 @@ di: - Symfony\Component\Console\Application ``` -Если вы не используете массив `$container->parameters`, можно отключить экспорт параметров. Кроме того, вы можете экспортировать только те теги, через которые вы получаете сервисы, используя метод `$container->findByTag(...)`. +Если вы не используете массив `$container->getParameters()`, можно отключить экспорт параметров. Кроме того, вы можете экспортировать только те теги, через которые вы получаете сервисы, используя метод `$container->findByTag(...)`. Если вы не вызываете этот метод вовсе, можно полностью отключить экспорт тегов, указав значение `false`. Вы можете значительно уменьшить метаданные для автоматического подключения, указав классы, которые вы используете в качестве параметра в методе `$container->getByType()`. diff --git a/dependency-injection/sl/autowiring.texy b/dependency-injection/sl/autowiring.texy index db5b689b51..fbeccc1741 100644 --- a/dependency-injection/sl/autowiring.texy +++ b/dependency-injection/sl/autowiring.texy @@ -105,7 +105,7 @@ class ShipManager Vsebnik DI nato samodejno posreduje polje storitev, ki ustrezajo dani vrsti. Izpusti storitve, ki imajo izklopljeno samodejno napeljavo. -Če ne morete nadzorovati oblike komentarja phpDoc, lahko polje storitev posredujete neposredno v konfiguraciji z uporabo [`typed()` |services#Special Functions]. +Vrsta v komentarju je lahko tudi v obliki `array` ali `list`. Če ne morete nadzorovati oblike komentarja phpDoc, lahko posredujete polje storitev neposredno v konfiguraciji z uporabo [`typed()` |services#Special Functions]. Skalarni argumenti .[#toc-scalar-arguments] diff --git a/dependency-injection/sl/configuration.texy b/dependency-injection/sl/configuration.texy index 4ccc57cc4f..80b2c5e1b5 100644 --- a/dependency-injection/sl/configuration.texy +++ b/dependency-injection/sl/configuration.texy @@ -122,7 +122,7 @@ di: - Symfony\Component\Console\Application ``` -Če ne uporabljate polja `$container->parameters`, lahko onemogočite izvoz parametrov. Poleg tega lahko izvozite samo tiste oznake, prek katerih pridobivate storitve z uporabo metode `$container->findByTag(...)`. +Če ne uporabljate polja `$container->getParameters()`, lahko onemogočite izvoz parametrov. Poleg tega lahko izvozite samo tiste oznake, prek katerih pridobivate storitve z uporabo metode `$container->findByTag(...)`. Če metode sploh ne kličete, lahko izvoz značk popolnoma onemogočite z metodo `false`. Metapodatke za [samodejno vnašanje |autowiring] lahko bistveno zmanjšate tako, da razrede, ki jih uporabljate, določite kot parameter metode `$container->getByType()`. diff --git a/dependency-injection/tr/autowiring.texy b/dependency-injection/tr/autowiring.texy index 4677539383..59333e2592 100644 --- a/dependency-injection/tr/autowiring.texy +++ b/dependency-injection/tr/autowiring.texy @@ -105,7 +105,7 @@ class ShipManager DI kapsayıcısı daha sonra verilen türle eşleşen bir dizi hizmeti otomatik olarak geçirir. Otomatik kablolamanın kapalı olduğu hizmetleri atlar. -Eğer phpDoc yorumunun biçimini kontrol edemiyorsanız, yapılandırmada doğrudan bir dizi hizmet iletebilirsiniz [`typed()` |services#Special Functions]. +Yorumdaki tür şu biçimde de olabilir `array` veya `list`. Eğer phpDoc yorumunun biçimini kontrol edemiyorsanız, yapılandırmada doğrudan bir dizi hizmet iletebilirsiniz [`typed()` |services#Special Functions]. Skaler Argümanlar .[#toc-scalar-arguments] diff --git a/dependency-injection/tr/configuration.texy b/dependency-injection/tr/configuration.texy index 0c5f7e7728..7d25ced52a 100644 --- a/dependency-injection/tr/configuration.texy +++ b/dependency-injection/tr/configuration.texy @@ -122,7 +122,7 @@ di: - Symfony\Component\Console\Application ``` -`$container->parameters` dizisini kullanmıyorsanız, parametre dışa aktarımını devre dışı bırakabilirsiniz. Ayrıca, yalnızca `$container->findByTag(...)` yöntemini kullanarak hizmet aldığınız etiketleri dışa aktarabilirsiniz. +`$container->getParameters()` dizisini kullanmıyorsanız, parametre dışa aktarımını devre dışı bırakabilirsiniz. Ayrıca, yalnızca `$container->findByTag(...)` yöntemini kullanarak hizmet aldığınız etiketleri dışa aktarabilirsiniz. Yöntemi hiç çağırmazsanız, `false` ile etiket dışa aktarımını tamamen devre dışı bırakabilirsiniz. Kullandığınız sınıfları `$container->getByType()` yöntemine parametre olarak belirterek [otomatik kablolama |autowiring] için meta verileri önemli ölçüde azaltabilirsiniz. diff --git a/dependency-injection/uk/autowiring.texy b/dependency-injection/uk/autowiring.texy index 908a454513..356325153f 100644 --- a/dependency-injection/uk/autowiring.texy +++ b/dependency-injection/uk/autowiring.texy @@ -105,7 +105,7 @@ class ShipManager Потім контейнер DI автоматично передає масив сервісів, що відповідають заданому типу. При цьому будуть пропущені сервіси, у яких відключено автозв'язування. -Якщо ви не можете контролювати форму коментаря phpDoc, ви можете передати масив сервісів безпосередньо в конфігурації, використовуючи [`typed()` |services#Special-Functions]. +Тип у коментарі також може мати вигляд `array` або `list`. Якщо ви не можете контролювати форму коментаря phpDoc, ви можете передати масив сервісів безпосередньо в конфігурації за допомогою [`typed()` |services#Special Functions]. Скалярні аргументи .[#toc-scalar-arguments] diff --git a/dependency-injection/uk/configuration.texy b/dependency-injection/uk/configuration.texy index f88af94d58..cf5a5c700e 100644 --- a/dependency-injection/uk/configuration.texy +++ b/dependency-injection/uk/configuration.texy @@ -122,7 +122,7 @@ di: - Symfony\Component\Console\Application ``` -Якщо ви не використовуєте масив `$container->parameters`, можна вимкнути експорт параметрів. Крім того, ви можете експортувати тільки ті теги, через які ви отримуєте сервіси, використовуючи метод `$container->findByTag(...)`. +Якщо ви не використовуєте масив `$container->getParameters()`, можна вимкнути експорт параметрів. Крім того, ви можете експортувати тільки ті теги, через які ви отримуєте сервіси, використовуючи метод `$container->findByTag(...)`. Якщо ви не викликаєте цей метод зовсім, можна повністю відключити експорт тегів, вказавши значення `false`. Ви можете значно зменшити метадані для автоматичного підключення, вказавши класи, які ви використовуєте як параметр у методі `$container->getByType()`. From a8ece7abd8f72ae1ace0862abf2bd128c3eeb4d6 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 4 Oct 2023 02:14:27 +0200 Subject: [PATCH 017/137] nette/schema 1.2.5 --- schema/bg/@home.texy | 140 ++++++++++++++++++++++++++++------------- schema/cs/@home.texy | 140 ++++++++++++++++++++++++++++------------- schema/de/@home.texy | 140 ++++++++++++++++++++++++++++------------- schema/el/@home.texy | 140 ++++++++++++++++++++++++++++------------- schema/en/@home.texy | 140 ++++++++++++++++++++++++++++------------- schema/es/@home.texy | 138 ++++++++++++++++++++++++++++------------- schema/fr/@home.texy | 140 ++++++++++++++++++++++++++++------------- schema/hu/@home.texy | 140 ++++++++++++++++++++++++++++------------- schema/it/@home.texy | 140 ++++++++++++++++++++++++++++------------- schema/ja/@home.texy | 142 +++++++++++++++++++++++++++++------------- schema/pl/@home.texy | 140 ++++++++++++++++++++++++++++------------- schema/pt/@home.texy | 144 +++++++++++++++++++++++++++++-------------- schema/ro/@home.texy | 138 ++++++++++++++++++++++++++++------------- schema/ru/@home.texy | 144 +++++++++++++++++++++++++++++-------------- schema/sl/@home.texy | 140 ++++++++++++++++++++++++++++------------- schema/tr/@home.texy | 140 ++++++++++++++++++++++++++++------------- schema/uk/@home.texy | 140 ++++++++++++++++++++++++++++------------- 17 files changed, 1652 insertions(+), 734 deletions(-) diff --git a/schema/bg/@home.texy b/schema/bg/@home.texy index 76d7bab75d..06400a7c5b 100644 --- a/schema/bg/@home.texy +++ b/schema/bg/@home.texy @@ -353,78 +353,89 @@ $processor->process($schema, ['a', 'b', 'c']); // Неуспешно изпълнение на командата "Дори елементи в масив" за елемент с масив от стойности. ``` -Този метод може да бъде извикан многократно за добавяне на нови твърдения. +Методът може да бъде извикан многократно, за да се добавят множество ограничения. Той може да се смесва с извикванията на `transform()` и `castTo()`. -Съпоставяне с обекти: from() .[#toc-sopostavlenie-s-ob-ektami-from] -------------------------------------------------------------------- +Трансформация: transform() .[#toc-transformation-transform] +----------------------------------------------------------- -От класа може да се генерира структурна схема. Пример: +Успешно валидираните данни могат да бъдат модифицирани с помощта на потребителска функция: ```php -class Config -{ - public string $name; - public string|null $password; - public bool $admin = false; -} - -$schema = Expect::from(new Config); +// conversion to uppercase: +Expect::string()->transform(fn(string $s) => strtoupper($s)); +``` -$data = [ - 'name' => 'jeff', -]; +Методът може да бъде извикан многократно, за да се добавят множество трансформации. Той може да се смесва с извиквания на `assert()` и `castTo()`. Операциите ще бъдат изпълнени в реда, в който са декларирани: -$normalized = $processor->process($schema, $data); -// $normalized instanceof Config -// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false} +```php +Expect::type('string|int') + ->castTo('string') + ->assert('ctype_lower', 'All characters must be lowercased') + ->transform(fn(string $s) => strtoupper($s)); // conversion to uppercase ``` -Ако използвате PHP 7.4 или по-нова версия, можете да използвате вградените типове: +Методът `transform()` може едновременно да трансформира и валидира стойността. Това често е по-просто и по-малко излишно от верижното използване на `transform()` и `assert()`. За тази цел функцията получава обект [Context |api:Nette\Schema\Context] с метод `addError()`, който може да се използва за добавяне на информация за проблеми с валидирането: ```php -class Config -{ - public string $name; - public ?string $password; - public bool $admin = false; -} +Expect::string() + ->transform(function (string $s, Nette\Schema\Context $context) { + if (!ctype_lower($s)) { + $context->addError('All characters must be lowercased', 'my.case.error'); + return null; + } -$schema = Expect::from(new Config); + return strtoupper($s); + }); ``` -Поддържат се и анонимни класове: + +Заличаване: castTo() .[#toc-casting-castto] +------------------------------------------- + +Успешно валидираните данни могат да бъдат хвърлени: ```php -$schema = Expect::from(new class { - public string $name; - public ?string $password; - public bool $admin = false; -}); +Expect::scalar()->castTo('string'); ``` -Тъй като информацията от дефиницията на класа може да не е достатъчна, можете да добавите потребителска схема за елементите с втори параметър: +В допълнение към нативните PHP типове можете да използвате и класове. Той разграничава дали става въпрос за обикновен клас без конструктор или за клас с конструктор. Ако класът няма конструктор, се създава негова инстанция и всички елементи на структурата се записват в свойствата му: ```php -$schema = Expect::from(new Config, [ - 'name' => Expect::string()->pattern('\w:.*'), -]); -``` +class Info +{ + public bool $processRefund; + public int $refundAmount; +} +Expect::structure([ + 'processRefund' => Expect::bool(), + 'refundAmount' => Expect::int(), +])->castTo(Info::class); -Заличаване: castTo() .[#toc-privedenie-castto] ----------------------------------------------- +// creates '$obj = new Info' and writes to $obj->processRefund and $obj->refundAmount +``` -Успешно тестваните данни могат да бъдат изхвърлени: +Ако класът има конструктор, елементите на структурата се предават като именувани параметри на конструктора: ```php -Expect::scalar()->castTo('string'); +class Info +{ + public function __construct( + public bool $processRefund, + public int $refundAmount, + ) { + } +} + +// creates $obj = new Info(processRefund: ..., refundAmount: ...) ``` -В допълнение към собствените типове на PHP можете също така да се обръщате към класове: +Casting в комбинация със скаларен параметър създава обект и предава стойността като единствен параметър на конструктора: ```php -Expect::scalar()->castTo('AddressEntity'); +Expect::string()->castTo(DateTime::class); +// creates new DateTime(...) ``` @@ -443,4 +454,47 @@ $normalized = $processor->process($schema, 'a b c'); // OK, возвращает ['a', 'b', 'c'] ``` + +Съпоставяне с обекти: from() .[#toc-mapping-to-objects-from] +------------------------------------------------------------ + +Можете да генерирате структурна схема от класа. Пример: + +```php +class Config +{ + public string $name; + public string|null $password; + public bool $admin = false; +} + +$schema = Expect::from(new Config); + +$data = [ + 'name' => 'jeff', +]; + +$normalized = $processor->process($schema, $data); +// $normalized instanceof Config +// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false} +``` + +Поддържат се и анонимни класове: + +```php +$schema = Expect::from(new class { + public string $name; + public ?string $password; + public bool $admin = false; +}); +``` + +Тъй като информацията, получена от дефиницията на класа, може да не е достатъчна, можете да добавите потребителска схема за елементите с втория параметър: + +```php +$schema = Expect::from(new Config, [ + 'name' => Expect::string()->pattern('\w:.*'), +]); +``` + {{leftbar: nette:@menu-topics}} diff --git a/schema/cs/@home.texy b/schema/cs/@home.texy index 4d40dc3cdf..b2d8b4b01f 100644 --- a/schema/cs/@home.texy +++ b/schema/cs/@home.texy @@ -353,78 +353,89 @@ $processor->process($schema, ['a', 'b', 'c']); // Failed assertion "Even items in array" for item with value array. ``` -Metodu lze volat opakovaně a tak přidat více omezení. +Metodu lze volat opakovaně a tak přidat více omezení. Lze ji prokládat s voláním `transform()` a `castTo()`. -Mapování na objekty: from() ---------------------------- +Transformace: transform() .{data-version:1.2.5} +----------------------------------------------- -Schéma struktury si můžeme nechat vygenerovat ze třídy. Příklad: +Úspěšně zvalidovaná data lze upravovat pomocí vlastní funkce: ```php -class Config -{ - public string $name; - public string|null $password; - public bool $admin = false; -} +// převod na velká písmena: +Expect::string()->transform(fn(string $s) => strtoupper($s)); +``` -$schema = Expect::from(new Config); +Metodu lze volat opakovaně a tak přidat více transformací. Lze ji prokládat s voláním `assert()` a `castTo()`. Operace se provedou v pořadí, v jakém jsou deklarovány: -$data = [ - 'name' => 'franta', -]; - -$normalized = $processor->process($schema, $data); -// $normalized instanceof Config -// $normalized = {'name' => 'franta', 'password' => null, 'admin' => false} +```php +Expect::type('string|int') + ->castTo('string') + ->assert('ctype_lower', 'All characters must be lowercased') + ->transform(fn(string $s) => strtoupper($s)); // převod na velká písmena ``` -Pokud používáte PHP 7.4 nebo vyšší, můžete využít nativních typů: +Metoda `transform()` může současně transformovat i validovat hodnotu. To je často jednodušší a méně duplicitní než řetězení `transform()` a `assert()`. K tomuto účelu funkce obdrží objekt [Context |api:Nette\Schema\Context] s metodou `addError()`, kterou lze použít k přidání informací o problémech s validací: ```php -class Config -{ - public string $name; - public ?string $password; - public bool $admin = false; -} +Expect::string() + ->transform(function (string $s, Nette\Schema\Context $context) { + if (!ctype_lower($s)) { + $context->addError('All characters must be lowercased', 'my.case.error'); + return null; + } -$schema = Expect::from(new Config); + return strtoupper($s); + }); ``` -Podporovány jsou i anonymní třídy: + +Přetypování: castTo() +--------------------- + +Úspěšně zvalidovaná data lze přetypovat: ```php -$schema = Expect::from(new class { - public string $name; - public ?string $password; - public bool $admin = false; -}); +Expect::scalar()->castTo('string'); ``` -Protože informace získané z definice třídy nemusí být dostačující, můžete druhým parametrem doplnit prvkům vlastní schéma: +Kromě nativních PHP typů lze přetypovávat i na třídy. Přitom se rozlišuje, zda jde o jednoduchou třídu bez kontruktoru, nebo třídu s konstruktorem. Pokud třída nemá konstruktor, vytvoří se její instance a všechny prvky struktury se zapíší do properties: ```php -$schema = Expect::from(new Config, [ - 'name' => Expect::string()->pattern('\w:.*'), -]); -``` +class Info +{ + public bool $processRefund; + public int $refundAmount; +} +Expect::structure([ + 'processRefund' => Expect::bool(), + 'refundAmount' => Expect::int(), +])->castTo(Info::class); -Přetypování: castTo() ---------------------- +// vytvoří '$obj = new Info' a zapíše do $obj->processRefund a $obj->refundAmount +``` -Úspěšně zvalidovaná data lze přetypovat: +Pokud třída konstruktor má, prvky struktury se předají jako pojmenované parametry konstruktoru: ```php -Expect::scalar()->castTo('string'); +class Info +{ + public function __construct( + public bool $processRefund, + public int $refundAmount, + ) { + } +} + +// vytvoří $obj = new Info(processRefund: ..., refundAmount: ...) ``` -Kromě nativních PHP typů lze přetypovávat i na třídy: +Přetypování v kombinaci se skalárním parametrem vytvoří objekt a hodnotu předá jako jediný parametr konstrukturu: ```php -Expect::scalar()->castTo('AddressEntity'); +Expect::string()->castTo(DateTime::class); +// vytvoří new DateTime(...) ``` @@ -444,4 +455,47 @@ $normalized = $processor->process($schema, 'a b c'); ``` +Mapování na objekty: from() +--------------------------- + +Schéma struktury si můžeme nechat vygenerovat ze třídy. Příklad: + +```php +class Config +{ + public string $name; + public string|null $password; + public bool $admin = false; +} + +$schema = Expect::from(new Config); + +$data = [ + 'name' => 'franta', +]; + +$normalized = $processor->process($schema, $data); +// $normalized instanceof Config +// $normalized = {'name' => 'franta', 'password' => null, 'admin' => false} +``` + +Podporovány jsou i anonymní třídy: + +```php +$schema = Expect::from(new class { + public string $name; + public ?string $password; + public bool $admin = false; +}); +``` + +Protože informace získané z definice třídy nemusí být dostačující, můžete druhým parametrem doplnit prvkům vlastní schéma: + +```php +$schema = Expect::from(new Config, [ + 'name' => Expect::string()->pattern('\w:.*'), +]); +``` + + {{leftbar: nette:@menu-topics}} diff --git a/schema/de/@home.texy b/schema/de/@home.texy index 615b2a8c1b..e9493a67c2 100644 --- a/schema/de/@home.texy +++ b/schema/de/@home.texy @@ -353,78 +353,89 @@ $processor->process($schema, ['a', 'b', 'c']); // Fehlgeschlagene Assertion "Gerade Elemente in Array" für Element mit Wert array. ``` -Die Methode kann wiederholt aufgerufen werden, um weitere Behauptungen hinzuzufügen. +Die Methode kann wiederholt aufgerufen werden, um mehrere Beschränkungen hinzuzufügen. Sie kann mit Aufrufen von `transform()` und `castTo()` vermischt werden. -Zuordnung zu Objekten: from() .[#toc-mapping-to-objects-from] -------------------------------------------------------------- +Umwandlung: transform() .[#toc-transformation-transform] +-------------------------------------------------------- -Sie können aus der Klasse ein Strukturschema erzeugen. Beispiel: +Erfolgreich überprüfte Daten können mit einer benutzerdefinierten Funktion geändert werden: ```php -class Config -{ - public string $name; - public string|null $password; - public bool $admin = false; -} - -$schema = Expect::from(new Config); +// conversion to uppercase: +Expect::string()->transform(fn(string $s) => strtoupper($s)); +``` -$data = [ - 'name' => 'jeff', -]; +Die Methode kann wiederholt aufgerufen werden, um mehrere Transformationen hinzuzufügen. Sie kann mit Aufrufen von `assert()` und `castTo()` vermischt werden. Die Operationen werden in der Reihenfolge ausgeführt, in der sie deklariert sind: -$normalized = $processor->process($schema, $data); -// $normalized instanceof Config -// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false} +```php +Expect::type('string|int') + ->castTo('string') + ->assert('ctype_lower', 'All characters must be lowercased') + ->transform(fn(string $s) => strtoupper($s)); // conversion to uppercase ``` -Wenn Sie PHP 7.4 oder höher verwenden, können Sie native Typen verwenden: +Die Methode `transform()` kann den Wert gleichzeitig transformieren und validieren. Dies ist oft einfacher und weniger redundant als die Verkettung von `transform()` und `assert()`. Zu diesem Zweck erhält die Funktion ein [Context-Objekt |api:Nette\Schema\Context] mit einer `addError()` -Methode, die dazu verwendet werden kann, Informationen über Validierungsprobleme hinzuzufügen: ```php -class Config -{ - public string $name; - public ?string $password; - public bool $admin = false; -} +Expect::string() + ->transform(function (string $s, Nette\Schema\Context $context) { + if (!ctype_lower($s)) { + $context->addError('All characters must be lowercased', 'my.case.error'); + return null; + } -$schema = Expect::from(new Config); + return strtoupper($s); + }); ``` -Anonyme Klassen werden ebenfalls unterstützt: + +Gießen: castTo() .[#toc-casting-castto] +--------------------------------------- + +Erfolgreich überprüfte Daten können gecastet werden: ```php -$schema = Expect::from(new class { - public string $name; - public ?string $password; - public bool $admin = false; -}); +Expect::scalar()->castTo('string'); ``` -Da die aus der Klassendefinition gewonnenen Informationen möglicherweise nicht ausreichen, können Sie mit dem zweiten Parameter ein benutzerdefiniertes Schema für die Elemente hinzufügen: +Zusätzlich zu den nativen PHP-Typen können Sie auch auf Klassen casten. Es wird unterschieden, ob es sich um eine einfache Klasse ohne Konstruktor oder um eine Klasse mit Konstruktor handelt. Wenn die Klasse keinen Konstruktor hat, wird eine Instanz der Klasse erstellt und alle Elemente der Struktur werden in ihre Eigenschaften geschrieben: ```php -$schema = Expect::from(new Config, [ - 'name' => Expect::string()->pattern('\w:.*'), -]); -``` +class Info +{ + public bool $processRefund; + public int $refundAmount; +} +Expect::structure([ + 'processRefund' => Expect::bool(), + 'refundAmount' => Expect::int(), +])->castTo(Info::class); -Casting: castTo() .[#toc-casting-castto] ----------------------------------------- +// creates '$obj = new Info' and writes to $obj->processRefund and $obj->refundAmount +``` -Erfolgreich überprüfte Daten können gecastet werden: +Wenn die Klasse einen Konstruktor hat, werden die Elemente der Struktur als benannte Parameter an den Konstruktor übergeben: ```php -Expect::scalar()->castTo('string'); +class Info +{ + public function __construct( + public bool $processRefund, + public int $refundAmount, + ) { + } +} + +// creates $obj = new Info(processRefund: ..., refundAmount: ...) ``` -Zusätzlich zu den nativen PHP-Typen können Sie auch auf Klassen casten: +Casting in Verbindung mit einem skalaren Parameter erzeugt ein Objekt und übergibt den Wert als einzigen Parameter an den Konstruktor: ```php -Expect::scalar()->castTo('AddressEntity'); +Expect::string()->castTo(DateTime::class); +// creates new DateTime(...) ``` @@ -443,4 +454,47 @@ $normalized = $processor->process($schema, 'a b c'); // OK, liefert ['a', 'b', 'c'] ``` + +Zuordnung zu Objekten: from() .[#toc-mapping-to-objects-from] +------------------------------------------------------------- + +Sie können aus der Klasse ein Strukturschema erzeugen. Beispiel: + +```php +class Config +{ + public string $name; + public string|null $password; + public bool $admin = false; +} + +$schema = Expect::from(new Config); + +$data = [ + 'name' => 'jeff', +]; + +$normalized = $processor->process($schema, $data); +// $normalized instanceof Config +// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false} +``` + +Anonyme Klassen werden ebenfalls unterstützt: + +```php +$schema = Expect::from(new class { + public string $name; + public ?string $password; + public bool $admin = false; +}); +``` + +Da die aus der Klassendefinition gewonnenen Informationen möglicherweise nicht ausreichen, können Sie mit dem zweiten Parameter ein benutzerdefiniertes Schema für die Elemente hinzufügen: + +```php +$schema = Expect::from(new Config, [ + 'name' => Expect::string()->pattern('\w:.*'), +]); +``` + {{leftbar: nette:@menu-topics}} diff --git a/schema/el/@home.texy b/schema/el/@home.texy index 4041fa7bdb..73d579437b 100644 --- a/schema/el/@home.texy +++ b/schema/el/@home.texy @@ -353,78 +353,89 @@ $processor->process($schema, ['a', 'b', 'c']); // Αποτυχημένος ισχυρισμός "Even items in array" για στοιχείο με τιμή array. ``` -Η μέθοδος μπορεί να κληθεί επανειλημμένα για να προσθέσετε περισσότερους ισχυρισμούς. +Η μέθοδος μπορεί να κληθεί επανειλημμένα για την προσθήκη πολλαπλών περιορισμών. Μπορεί να αναμειχθεί με κλήσεις στις `transform()` και `castTo()`. -Αντιστοίχιση σε αντικείμενα: from() .[#toc-mapping-to-objects-from] -------------------------------------------------------------------- +Μετασχηματισμός: transform() .[#toc-transformation-transform] +------------------------------------------------------------- -Μπορείτε να δημιουργήσετε σχήμα δομής από την κλάση. Παράδειγμα: +Τα επιτυχώς επικυρωμένα δεδομένα μπορούν να τροποποιηθούν χρησιμοποιώντας μια προσαρμοσμένη συνάρτηση: ```php -class Config -{ - public string $name; - public string|null $password; - public bool $admin = false; -} +// conversion to uppercase: +Expect::string()->transform(fn(string $s) => strtoupper($s)); +``` -$schema = Expect::from(new Config); +Η μέθοδος μπορεί να κληθεί επανειλημμένα για την προσθήκη πολλαπλών μετασχηματισμών. Μπορεί να αναμειχθεί με κλήσεις στις `assert()` και `castTo()`. Οι λειτουργίες θα εκτελούνται με τη σειρά με την οποία δηλώνονται: -$data = [ - 'name' => 'jeff', -]; - -$normalized = $processor->process($schema, $data); -// $normalized instanceof Config -// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false} +```php +Expect::type('string|int') + ->castTo('string') + ->assert('ctype_lower', 'All characters must be lowercased') + ->transform(fn(string $s) => strtoupper($s)); // conversion to uppercase ``` -Εάν χρησιμοποιείτε PHP 7.4 ή νεότερη έκδοση, μπορείτε να χρησιμοποιήσετε εγγενείς τύπους: +Η μέθοδος `transform()` μπορεί να μετασχηματίσει και να επικυρώσει την τιμή ταυτόχρονα. Αυτό είναι συχνά απλούστερο και λιγότερο περιττό από την αλυσιδωτή εκτέλεση των `transform()` και `assert()`. Για το σκοπό αυτό, η συνάρτηση λαμβάνει ένα αντικείμενο [Context |api:Nette\Schema\Context] με μια μέθοδο `addError()`, η οποία μπορεί να χρησιμοποιηθεί για την προσθήκη πληροφοριών σχετικά με τα θέματα επικύρωσης: ```php -class Config -{ - public string $name; - public ?string $password; - public bool $admin = false; -} +Expect::string() + ->transform(function (string $s, Nette\Schema\Context $context) { + if (!ctype_lower($s)) { + $context->addError('All characters must be lowercased', 'my.case.error'); + return null; + } -$schema = Expect::from(new Config); + return strtoupper($s); + }); ``` -Υποστηρίζονται επίσης ανώνυμες κλάσεις: + +Casting: castTo() .[#toc-casting-castto] +---------------------------------------- + +Τα επιτυχώς επικυρωμένα δεδομένα μπορούν να μεταφερθούν: ```php -$schema = Expect::from(new class { - public string $name; - public ?string $password; - public bool $admin = false; -}); +Expect::scalar()->castTo('string'); ``` -Μπορείτε να προσθέσετε ένα προσαρμοσμένο σχήμα για τα στοιχεία με τη δεύτερη παράμετρο: +Εκτός από τους εγγενείς τύπους της PHP, μπορείτε επίσης να κάνετε cast σε κλάσεις. Διακρίνεται αν πρόκειται για μια απλή κλάση χωρίς κατασκευαστή ή για μια κλάση με κατασκευαστή. Αν η κλάση δεν έχει κατασκευαστή, δημιουργείται μια παρουσία της και όλα τα στοιχεία της δομής γράφονται στις ιδιότητές της: ```php -$schema = Expect::from(new Config, [ - 'name' => Expect::string()->pattern('\w:.*'), -]); -``` +class Info +{ + public bool $processRefund; + public int $refundAmount; +} +Expect::structure([ + 'processRefund' => Expect::bool(), + 'refundAmount' => Expect::int(), +])->castTo(Info::class); -Casting: castTo() .[#toc-casting-castto] ----------------------------------------- +// creates '$obj = new Info' and writes to $obj->processRefund and $obj->refundAmount +``` -Τα επιτυχώς επικυρωμένα δεδομένα μπορούν να μεταφερθούν: +Εάν η κλάση διαθέτει κατασκευαστή, τα στοιχεία της δομής μεταβιβάζονται ως ονομαστικές παράμετροι στον κατασκευαστή: ```php -Expect::scalar()->castTo('string'); +class Info +{ + public function __construct( + public bool $processRefund, + public int $refundAmount, + ) { + } +} + +// creates $obj = new Info(processRefund: ..., refundAmount: ...) ``` -Εκτός από τους εγγενείς τύπους της PHP, μπορείτε επίσης να κάνετε cast σε κλάσεις: +Η χύτευση σε συνδυασμό με μια κλιμακωτή παράμετρο δημιουργεί ένα αντικείμενο και μεταβιβάζει την τιμή ως μοναδική παράμετρο στον κατασκευαστή: ```php -Expect::scalar()->castTo('AddressEntity'); +Expect::string()->castTo(DateTime::class); +// creates new DateTime(...) ``` @@ -443,4 +454,47 @@ $normalized = $processor->process($schema, 'a b c'); // OK, επιστρέφει ['a', 'b', 'c'] ``` + +Αντιστοίχιση σε αντικείμενα: from() .[#toc-mapping-to-objects-from] +------------------------------------------------------------------- + +Μπορείτε να δημιουργήσετε σχήμα δομής από την κλάση. Παράδειγμα: + +```php +class Config +{ + public string $name; + public string|null $password; + public bool $admin = false; +} + +$schema = Expect::from(new Config); + +$data = [ + 'name' => 'jeff', +]; + +$normalized = $processor->process($schema, $data); +// $normalized instanceof Config +// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false} +``` + +Υποστηρίζονται επίσης ανώνυμες κλάσεις: + +```php +$schema = Expect::from(new class { + public string $name; + public ?string $password; + public bool $admin = false; +}); +``` + +Μπορείτε να προσθέσετε ένα προσαρμοσμένο σχήμα για τα στοιχεία με τη δεύτερη παράμετρο: + +```php +$schema = Expect::from(new Config, [ + 'name' => Expect::string()->pattern('\w:.*'), +]); +``` + {{leftbar: nette:@menu-topics}} diff --git a/schema/en/@home.texy b/schema/en/@home.texy index 2d1eb11cb2..e9da6d083a 100644 --- a/schema/en/@home.texy +++ b/schema/en/@home.texy @@ -353,78 +353,89 @@ $processor->process($schema, ['a', 'b', 'c']); // Failed assertion "Even items in array" for item with value array. ``` -The method can be called repeatedly to add more assertions. +The method can be called repeatedly to add multiple constraints. It can be intermixed with calls to `transform()` and `castTo()`. -Mapping to Objects: from() --------------------------- +Transformation: transform() .{data-version:1.2.5} +------------------------------------------------- -You can generate structure schema from the class. Example: +Successfully validated data can be modified using a custom function: ```php -class Config -{ - public string $name; - public string|null $password; - public bool $admin = false; -} +// conversion to uppercase: +Expect::string()->transform(fn(string $s) => strtoupper($s)); +``` -$schema = Expect::from(new Config); +The method can be called repeatedly to add multiple transformations. It can be intermixed with calls to `assert()` and `castTo()`. The operations will be executed in the order in which they are declared: -$data = [ - 'name' => 'jeff', -]; - -$normalized = $processor->process($schema, $data); -// $normalized instanceof Config -// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false} +```php +Expect::type('string|int') + ->castTo('string') + ->assert('ctype_lower', 'All characters must be lowercased') + ->transform(fn(string $s) => strtoupper($s)); // conversion to uppercase ``` -If you are using PHP 7.4 or higher, you can use native types: +The `transform()` method can both transform and validate the value simultaneously. This is often simpler and less redundant than chaining `transform()` and `assert()`. For this purpose, the function receives a [Context |api:Nette\Schema\Context] object with an `addError()` method, which can be used to add information about validation issues: ```php -class Config -{ - public string $name; - public ?string $password; - public bool $admin = false; -} +Expect::string() + ->transform(function (string $s, Nette\Schema\Context $context) { + if (!ctype_lower($s)) { + $context->addError('All characters must be lowercased', 'my.case.error'); + return null; + } -$schema = Expect::from(new Config); + return strtoupper($s); + }); ``` -Anonymous classes are also supported: + +Casting: castTo() +----------------- + +Successfully validated data can be cast: ```php -$schema = Expect::from(new class { - public string $name; - public ?string $password; - public bool $admin = false; -}); +Expect::scalar()->castTo('string'); ``` -Because the information obtained from the class definition may not be sufficient, you can add a custom schema for the elements with the second parameter: +In addition to native PHP types, you can also cast to classes. It distinguishes whether it is a simple class without a constructor or a class with a constructor. If the class has no constructor, an instance of it is created and all elements of the structure are written to its properties: ```php -$schema = Expect::from(new Config, [ - 'name' => Expect::string()->pattern('\w:.*'), -]); -``` +class Info +{ + public bool $processRefund; + public int $refundAmount; +} +Expect::structure([ + 'processRefund' => Expect::bool(), + 'refundAmount' => Expect::int(), +])->castTo(Info::class); -Casting: castTo() ------------------ +// creates '$obj = new Info' and writes to $obj->processRefund and $obj->refundAmount +``` -Successfully validated data can be cast: +If the class has a constructor, the elements of the structure are passed as named parameters to the constructor: ```php -Expect::scalar()->castTo('string'); +class Info +{ + public function __construct( + public bool $processRefund, + public int $refundAmount, + ) { + } +} + +// creates $obj = new Info(processRefund: ..., refundAmount: ...) ``` -In addition to native PHP types, you can also cast to classes: +Casting combined with a scalar parameter creates an object and passes the value as the sole parameter to the constructor: ```php -Expect::scalar()->castTo('AddressEntity'); +Expect::string()->castTo(DateTime::class); +// creates new DateTime(...) ``` @@ -443,4 +454,47 @@ $normalized = $processor->process($schema, 'a b c'); // OK, returns ['a', 'b', 'c'] ``` + +Mapping to Objects: from() +-------------------------- + +You can generate structure schema from the class. Example: + +```php +class Config +{ + public string $name; + public string|null $password; + public bool $admin = false; +} + +$schema = Expect::from(new Config); + +$data = [ + 'name' => 'jeff', +]; + +$normalized = $processor->process($schema, $data); +// $normalized instanceof Config +// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false} +``` + +Anonymous classes are also supported: + +```php +$schema = Expect::from(new class { + public string $name; + public ?string $password; + public bool $admin = false; +}); +``` + +Because the information obtained from the class definition may not be sufficient, you can add a custom schema for the elements with the second parameter: + +```php +$schema = Expect::from(new Config, [ + 'name' => Expect::string()->pattern('\w:.*'), +]); +``` + {{leftbar: nette:@menu-topics}} diff --git a/schema/es/@home.texy b/schema/es/@home.texy index b74af864a3..5610a275b7 100644 --- a/schema/es/@home.texy +++ b/schema/es/@home.texy @@ -353,78 +353,89 @@ $processor->process($schema, ['a', 'b', 'c']); // Fallo en la aserción "Even items in array" para el elemento con valor array. ``` -El método puede ser llamado repetidamente para añadir más aserciones. +El método puede llamarse repetidamente para añadir múltiples restricciones. Puede entremezclarse con llamadas a `transform()` y `castTo()`. -Asignación a objetos: from() .[#toc-mapping-to-objects-from] +Transformación: transform() .[#toc-transformation-transform] ------------------------------------------------------------ -Se puede generar esquema de estructura a partir de la clase. Ejemplo: +Los datos validados correctamente pueden modificarse mediante una función personalizada: ```php -class Config -{ - public string $name; - public string|null $password; - public bool $admin = false; -} - -$schema = Expect::from(new Config); +// conversion to uppercase: +Expect::string()->transform(fn(string $s) => strtoupper($s)); +``` -$data = [ - 'name' => 'jeff', -]; +El método puede llamarse repetidamente para añadir múltiples transformaciones. Puede entremezclarse con llamadas a `assert()` y `castTo()`. Las operaciones se ejecutarán en el orden en que se declaren: -$normalized = $processor->process($schema, $data); -// $normalized instanceof Config -// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false} +```php +Expect::type('string|int') + ->castTo('string') + ->assert('ctype_lower', 'All characters must be lowercased') + ->transform(fn(string $s) => strtoupper($s)); // conversion to uppercase ``` -Si está usando PHP 7.4 o superior, puede usar tipos nativos: +El método `transform()` puede transformar y validar el valor simultáneamente. Esto suele ser más sencillo y menos redundante que encadenar `transform()` y `assert()`. Para ello, la función recibe un objeto [Context |api:Nette\Schema\Context] con un método `addError()`, que puede utilizarse para añadir información sobre problemas de validación: ```php -class Config -{ - public string $name; - public ?string $password; - public bool $admin = false; -} +Expect::string() + ->transform(function (string $s, Nette\Schema\Context $context) { + if (!ctype_lower($s)) { + $context->addError('All characters must be lowercased', 'my.case.error'); + return null; + } -$schema = Expect::from(new Config); + return strtoupper($s); + }); ``` -Las clases anónimas también están soportadas: + +Casting: castTo() .[#toc-casting-castto] +---------------------------------------- + +Los datos validados correctamente pueden ser emitidos: ```php -$schema = Expect::from(new class { - public string $name; - public ?string $password; - public bool $admin = false; -}); +Expect::scalar()->castTo('string'); ``` -Dado que la información obtenida de la definición de la clase puede no ser suficiente, puede añadir un esquema personalizado para los elementos con el segundo parámetro: +Además de los tipos nativos de PHP, también se puede hacer cast a clases. Distingue si se trata de una clase simple sin constructor o de una clase con constructor. Si la clase no tiene constructor, se crea una instancia de la misma y todos los elementos de la estructura se escriben en sus propiedades: ```php -$schema = Expect::from(new Config, [ - 'name' => Expect::string()->pattern('\w:.*'), -]); -``` +class Info +{ + public bool $processRefund; + public int $refundAmount; +} +Expect::structure([ + 'processRefund' => Expect::bool(), + 'refundAmount' => Expect::int(), +])->castTo(Info::class); -Casting: castTo() .[#toc-casting-castto] ----------------------------------------- +// creates '$obj = new Info' and writes to $obj->processRefund and $obj->refundAmount +``` -Los datos validados correctamente pueden ser emitidos: +Si la clase tiene un constructor, los elementos de la estructura se pasan como parámetros con nombre al constructor: ```php -Expect::scalar()->castTo('string'); +class Info +{ + public function __construct( + public bool $processRefund, + public int $refundAmount, + ) { + } +} + +// creates $obj = new Info(processRefund: ..., refundAmount: ...) ``` -Además de los tipos nativos de PHP, también se pueden convertir a clases: +El moldeado combinado con un parámetro escalar crea un objeto y pasa el valor como único parámetro al constructor: ```php -Expect::scalar()->castTo('AddressEntity'); +Expect::string()->castTo(DateTime::class); +// creates new DateTime(...) ``` @@ -443,4 +454,47 @@ $normalized = $processor->process($schema, 'a b c'); // OK, devuelve ['a', 'b', 'c'] ``` + +Asignación a objetos: from() .[#toc-mapping-to-objects-from] +------------------------------------------------------------ + +Se puede generar esquema de estructura a partir de la clase. Ejemplo: + +```php +class Config +{ + public string $name; + public string|null $password; + public bool $admin = false; +} + +$schema = Expect::from(new Config); + +$data = [ + 'name' => 'jeff', +]; + +$normalized = $processor->process($schema, $data); +// $normalized instanceof Config +// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false} +``` + +También se admiten clases anónimas: + +```php +$schema = Expect::from(new class { + public string $name; + public ?string $password; + public bool $admin = false; +}); +``` + +Dado que la información obtenida de la definición de la clase puede no ser suficiente, puede añadir un esquema personalizado para los elementos con el segundo parámetro: + +```php +$schema = Expect::from(new Config, [ + 'name' => Expect::string()->pattern('\w:.*'), +]); +``` + {{leftbar: nette:@menu-topics}} diff --git a/schema/fr/@home.texy b/schema/fr/@home.texy index 06c25f68ef..036493c90a 100644 --- a/schema/fr/@home.texy +++ b/schema/fr/@home.texy @@ -353,78 +353,89 @@ $processor->process($schema, ['a', 'b', 'c']); // Failed assertion "Even items in array" for item with value array. ``` -La méthode peut être appelée à plusieurs reprises pour ajouter d'autres assertions. +La méthode peut être appelée plusieurs fois pour ajouter plusieurs contraintes. Elle peut être combinée avec les appels à `transform()` et `castTo()`. -Mappage vers les objets : from() .[#toc-mapping-to-objects-from] ----------------------------------------------------------------- +Transformation : transform() .[#toc-transformation-transform] +------------------------------------------------------------- -Vous pouvez générer un schéma de structure à partir de la classe. Exemple : +Les données validées avec succès peuvent être modifiées à l'aide d'une fonction personnalisée : ```php -class Config -{ - public string $name; - public string|null $password; - public bool $admin = false; -} +// conversion to uppercase: +Expect::string()->transform(fn(string $s) => strtoupper($s)); +``` -$schema = Expect::from(new Config); +La méthode peut être appelée à plusieurs reprises pour ajouter des transformations multiples. Elle peut être combinée avec des appels à `assert()` et `castTo()`. Les opérations seront exécutées dans l'ordre dans lequel elles sont déclarées : -$data = [ - 'name' => 'jeff', -]; - -$normalized = $processor->process($schema, $data); -// $normalized instanceof Config -// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false} +```php +Expect::type('string|int') + ->castTo('string') + ->assert('ctype_lower', 'All characters must be lowercased') + ->transform(fn(string $s) => strtoupper($s)); // conversion to uppercase ``` -Si vous utilisez PHP 7.4 ou plus, vous pouvez utiliser les types natifs : +La méthode `transform()` peut transformer et valider la valeur simultanément. C'est souvent plus simple et moins redondant que d'enchaîner `transform()` et `assert()`. À cette fin, la fonction reçoit un objet [Contexte |api:Nette\Schema\Context] avec une méthode `addError()`, qui peut être utilisée pour ajouter des informations sur les problèmes de validation : ```php -class Config -{ - public string $name; - public ?string $password; - public bool $admin = false; -} +Expect::string() + ->transform(function (string $s, Nette\Schema\Context $context) { + if (!ctype_lower($s)) { + $context->addError('All characters must be lowercased', 'my.case.error'); + return null; + } -$schema = Expect::from(new Config); + return strtoupper($s); + }); ``` -Les classes anonymes sont également supportées : + +Casting : castTo() .[#toc-casting-castto] +----------------------------------------- + +Les données validées avec succès peuvent être coulées : ```php -$schema = Expect::from(new class { - public string $name; - public ?string $password; - public bool $admin = false; -}); +Expect::scalar()->castTo('string'); ``` -Comme les informations obtenues à partir de la définition de la classe peuvent ne pas être suffisantes, vous pouvez ajouter un schéma personnalisé pour les éléments avec le deuxième paramètre : +En plus des types natifs de PHP, vous pouvez également utiliser des classes. Cela permet de distinguer s'il s'agit d'une classe simple sans constructeur ou d'une classe avec constructeur. Si la classe n'a pas de constructeur, une instance est créée et tous les éléments de la structure sont inscrits dans ses propriétés : ```php -$schema = Expect::from(new Config, [ - 'name' => Expect::string()->pattern('\w:.*'), -]); -``` +class Info +{ + public bool $processRefund; + public int $refundAmount; +} +Expect::structure([ + 'processRefund' => Expect::bool(), + 'refundAmount' => Expect::int(), +])->castTo(Info::class); -Casting : castTo() .[#toc-casting-castto] ------------------------------------------ +// creates '$obj = new Info' and writes to $obj->processRefund and $obj->refundAmount +``` -Les données validées avec succès peuvent être coulées : +Si la classe a un constructeur, les éléments de la structure sont transmis au constructeur en tant que paramètres nommés : ```php -Expect::scalar()->castTo('string'); +class Info +{ + public function __construct( + public bool $processRefund, + public int $refundAmount, + ) { + } +} + +// creates $obj = new Info(processRefund: ..., refundAmount: ...) ``` -En plus des types natifs de PHP, vous pouvez également effectuer des castings vers des classes : +La fonte combinée à un paramètre scalaire crée un objet et transmet la valeur comme seul paramètre au constructeur : ```php -Expect::scalar()->castTo('AddressEntity'); +Expect::string()->castTo(DateTime::class); +// creates new DateTime(...) ``` @@ -443,4 +454,47 @@ $normalized = $processor->process($schema, 'a b c'); // OK, renvoie ['a', 'b', 'c'] ``` + +Mapping to Objects : from() .[#toc-mapping-to-objects-from] +----------------------------------------------------------- + +Vous pouvez générer un schéma de structure à partir de la classe. Exemple : + +```php +class Config +{ + public string $name; + public string|null $password; + public bool $admin = false; +} + +$schema = Expect::from(new Config); + +$data = [ + 'name' => 'jeff', +]; + +$normalized = $processor->process($schema, $data); +// $normalized instanceof Config +// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false} +``` + +Les classes anonymes sont également prises en charge : + +```php +$schema = Expect::from(new class { + public string $name; + public ?string $password; + public bool $admin = false; +}); +``` + +Comme les informations obtenues à partir de la définition de la classe peuvent ne pas être suffisantes, vous pouvez ajouter un schéma personnalisé pour les éléments à l'aide du deuxième paramètre : + +```php +$schema = Expect::from(new Config, [ + 'name' => Expect::string()->pattern('\w:.*'), +]); +``` + {{leftbar: nette:@menu-topics}} diff --git a/schema/hu/@home.texy b/schema/hu/@home.texy index bccac8b89b..c98bb38845 100644 --- a/schema/hu/@home.texy +++ b/schema/hu/@home.texy @@ -353,78 +353,89 @@ $processor->process($schema, ['a', 'b', 'c']); // Sikertelen "Páros elemek a tömbben" állítás a tömb értékű elemre. ``` -A metódus ismételten meghívható további állítások hozzáadásához. +A módszer többször is meghívható, hogy több korlátozást adjon hozzá. A `transform()` és a `castTo()` hívásokkal keverhető. -Objektumokra való leképezés: from() .[#toc-mapping-to-objects-from] -------------------------------------------------------------------- +Transzformáció: transform() .[#toc-transformation-transform] +------------------------------------------------------------ -Az osztályból struktúra sémát generálhatunk. Példa: +A sikeresen érvényesített adatok egy egyéni függvény segítségével módosíthatók: ```php -class Config -{ - public string $name; - public string|null $password; - public bool $admin = false; -} - -$schema = Expect::from(new Config); +// conversion to uppercase: +Expect::string()->transform(fn(string $s) => strtoupper($s)); +``` -$data = [ - 'name' => 'jeff', -]; +A módszer ismételten meghívható több átalakítás hozzáadásához. Ez keverhető a `assert()` és a `castTo()` hívásaival. A műveletek a deklaráció sorrendjében kerülnek végrehajtásra: -$normalized = $processor->process($schema, $data); -// $normalized instanceof Config -// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false} +```php +Expect::type('string|int') + ->castTo('string') + ->assert('ctype_lower', 'All characters must be lowercased') + ->transform(fn(string $s) => strtoupper($s)); // conversion to uppercase ``` -Ha a PHP 7.4 vagy magasabb verziószámú PHP-t használ, használhat natív típusokat: +A `transform()` módszer egyszerre tudja átalakítani és érvényesíteni az értéket. Ez gyakran egyszerűbb és kevésbé redundáns, mint a `transform()` és a `assert()` láncolása. Ehhez a funkció egy [Context |api:Nette\Schema\Context] objektumot kap egy `addError()` metódussal, amely az érvényesítési problémákra vonatkozó információk hozzáadására használható: ```php -class Config -{ - public string $name; - public ?string $password; - public bool $admin = false; -} +Expect::string() + ->transform(function (string $s, Nette\Schema\Context $context) { + if (!ctype_lower($s)) { + $context->addError('All characters must be lowercased', 'my.case.error'); + return null; + } -$schema = Expect::from(new Config); + return strtoupper($s); + }); ``` -A névtelen osztályok is támogatottak: + +Casting: castTo() .[#toc-casting-castto] +---------------------------------------- + +Sikeresen érvényesített adatok önthetők: ```php -$schema = Expect::from(new class { - public string $name; - public ?string $password; - public bool $admin = false; -}); +Expect::scalar()->castTo('string'); ``` -A második paraméterrel egyéni sémát adhat az elemekhez, mivel az osztálydefinícióból kapott információ nem feltétlenül elegendő: +A natív PHP-típusok mellett osztályokba is átvihetők. Megkülönbözteti, hogy egyszerű, konstruktor nélküli osztályról vagy konstruktorral rendelkező osztályról van-e szó. Ha az osztálynak nincs konstruktora, akkor létrejön egy példánya, és a struktúra minden elemét kiírja a tulajdonságaiba: ```php -$schema = Expect::from(new Config, [ - 'name' => Expect::string()->pattern('\w:.*'), -]); -``` +class Info +{ + public bool $processRefund; + public int $refundAmount; +} +Expect::structure([ + 'processRefund' => Expect::bool(), + 'refundAmount' => Expect::int(), +])->castTo(Info::class); -Casting: castTo() .[#toc-casting-castto] ----------------------------------------- +// creates '$obj = new Info' and writes to $obj->processRefund and $obj->refundAmount +``` -Sikeresen érvényesített adatok önthetők: +Ha az osztálynak van konstruktora, akkor a struktúra elemeit a konstruktornak nevesített paraméterként adjuk át: ```php -Expect::scalar()->castTo('string'); +class Info +{ + public function __construct( + public bool $processRefund, + public int $refundAmount, + ) { + } +} + +// creates $obj = new Info(processRefund: ..., refundAmount: ...) ``` -A natív PHP-típusok mellett osztályokba is átvihetők: +A skalár paraméterrel kombinált öntött objektum létrehoz egy objektumot, és az értéket adja át egyetlen paraméterként a konstruktornak: ```php -Expect::scalar()->castTo('AddressEntity'); +Expect::string()->castTo(DateTime::class); +// creates new DateTime(...) ``` @@ -443,4 +454,47 @@ $normalized = $processor->process($schema, 'a b c'); // OK, visszaadja ['a', 'b', 'c'] ``` + +Objektumokra való leképezés: from() .[#toc-mapping-to-objects-from] +------------------------------------------------------------------- + +Az osztályból struktúra sémát generálhatunk. Példa: + +```php +class Config +{ + public string $name; + public string|null $password; + public bool $admin = false; +} + +$schema = Expect::from(new Config); + +$data = [ + 'name' => 'jeff', +]; + +$normalized = $processor->process($schema, $data); +// $normalized instanceof Config +// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false} +``` + +Névtelen osztályok is támogatottak: + +```php +$schema = Expect::from(new class { + public string $name; + public ?string $password; + public bool $admin = false; +}); +``` + +A második paraméterrel egyéni sémát adhat az elemekhez, mivel az osztálydefinícióból kapott információk nem feltétlenül elegendőek: + +```php +$schema = Expect::from(new Config, [ + 'name' => Expect::string()->pattern('\w:.*'), +]); +``` + {{leftbar: nette:@menu-topics}} diff --git a/schema/it/@home.texy b/schema/it/@home.texy index 8904af0559..01c04d05c8 100644 --- a/schema/it/@home.texy +++ b/schema/it/@home.texy @@ -353,78 +353,89 @@ $processor->process($schema, ['a', 'b', 'c']); // Asserzione fallita "Elementi pari nell'array" per l'elemento con valore array. ``` -Il metodo può essere richiamato più volte per aggiungere altre asserzioni. +Il metodo può essere richiamato più volte per aggiungere più vincoli. Può essere mescolato con le chiamate a `transform()` e `castTo()`. -Mappatura a oggetti: from() .[#toc-mapping-to-objects-from] ------------------------------------------------------------ +Trasformazione: transform() .[#toc-transformation-transform] +------------------------------------------------------------ -È possibile generare uno schema di struttura dalla classe. Esempio: +I dati convalidati con successo possono essere modificati utilizzando una funzione personalizzata: ```php -class Config -{ - public string $name; - public string|null $password; - public bool $admin = false; -} +// conversion to uppercase: +Expect::string()->transform(fn(string $s) => strtoupper($s)); +``` -$schema = Expect::from(new Config); +Il metodo può essere richiamato ripetutamente per aggiungere più trasformazioni. Può essere mescolato con le chiamate a `assert()` e `castTo()`. Le operazioni saranno eseguite nell'ordine in cui sono state dichiarate: -$data = [ - 'name' => 'jeff', -]; - -$normalized = $processor->process($schema, $data); -// $normalized instanceof Config -// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false} +```php +Expect::type('string|int') + ->castTo('string') + ->assert('ctype_lower', 'All characters must be lowercased') + ->transform(fn(string $s) => strtoupper($s)); // conversion to uppercase ``` -Se si utilizza PHP 7.4 o superiore, si possono usare i tipi nativi: +Il metodo `transform()` può trasformare e convalidare il valore contemporaneamente. Spesso è più semplice e meno ridondante che concatenare `transform()` e `assert()`. A questo scopo, la funzione riceve un oggetto [Context |api:Nette\Schema\Context] con un metodo `addError()`, che può essere usato per aggiungere informazioni sui problemi di validazione: ```php -class Config -{ - public string $name; - public ?string $password; - public bool $admin = false; -} +Expect::string() + ->transform(function (string $s, Nette\Schema\Context $context) { + if (!ctype_lower($s)) { + $context->addError('All characters must be lowercased', 'my.case.error'); + return null; + } -$schema = Expect::from(new Config); + return strtoupper($s); + }); ``` -Sono supportate anche le classi anonime: + +Casting: castTo() .[#toc-casting-castto] +---------------------------------------- + +I dati convalidati con successo possono essere lanciati: ```php -$schema = Expect::from(new class { - public string $name; - public ?string $password; - public bool $admin = false; -}); +Expect::scalar()->castTo('string'); ``` -Poiché le informazioni ottenute dalla definizione della classe potrebbero non essere sufficienti, è possibile aggiungere uno schema personalizzato per gli elementi con il secondo parametro: +Oltre ai tipi nativi di PHP, è possibile eseguire il cast su classi. Si distingue se si tratta di una classe semplice senza costruttore o di una classe con costruttore. Se la classe non ha un costruttore, ne viene creata un'istanza e tutti gli elementi della struttura vengono scritti nelle sue proprietà: ```php -$schema = Expect::from(new Config, [ - 'name' => Expect::string()->pattern('\w:.*'), -]); -``` +class Info +{ + public bool $processRefund; + public int $refundAmount; +} +Expect::structure([ + 'processRefund' => Expect::bool(), + 'refundAmount' => Expect::int(), +])->castTo(Info::class); -Casting: castTo() .[#toc-casting-castto] ----------------------------------------- +// creates '$obj = new Info' and writes to $obj->processRefund and $obj->refundAmount +``` -I dati convalidati con successo possono essere lanciati: +Se la classe ha un costruttore, gli elementi della struttura vengono passati come parametri al costruttore: ```php -Expect::scalar()->castTo('string'); +class Info +{ + public function __construct( + public bool $processRefund, + public int $refundAmount, + ) { + } +} + +// creates $obj = new Info(processRefund: ..., refundAmount: ...) ``` -Oltre ai tipi nativi di PHP, è possibile eseguire il cast su classi: +Il casting combinato con un parametro scalare crea un oggetto e passa il valore come unico parametro al costruttore: ```php -Expect::scalar()->castTo('AddressEntity'); +Expect::string()->castTo(DateTime::class); +// creates new DateTime(...) ``` @@ -443,4 +454,47 @@ $normalized = $processor->process($schema, 'a b c'); // OK, restituisce ['a', 'b', 'c'] ``` + +Mappatura a oggetti: from() .[#toc-mapping-to-objects-from] +----------------------------------------------------------- + +È possibile generare uno schema di struttura dalla classe. Esempio: + +```php +class Config +{ + public string $name; + public string|null $password; + public bool $admin = false; +} + +$schema = Expect::from(new Config); + +$data = [ + 'name' => 'jeff', +]; + +$normalized = $processor->process($schema, $data); +// $normalized instanceof Config +// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false} +``` + +Sono supportate anche le classi anonime: + +```php +$schema = Expect::from(new class { + public string $name; + public ?string $password; + public bool $admin = false; +}); +``` + +Poiché le informazioni ottenute dalla definizione della classe potrebbero non essere sufficienti, è possibile aggiungere uno schema personalizzato per gli elementi con il secondo parametro: + +```php +$schema = Expect::from(new Config, [ + 'name' => Expect::string()->pattern('\w:.*'), +]); +``` + {{leftbar: nette:@menu-topics}} diff --git a/schema/ja/@home.texy b/schema/ja/@home.texy index 76554d052d..a29b9a1617 100644 --- a/schema/ja/@home.texy +++ b/schema/ja/@home.texy @@ -353,78 +353,89 @@ $processor->process($schema, ['a', 'b', 'c']); // Failed assertion "Even items in array" for item with value array. ``` -このメソッドは、繰り返しコールしてアサーションを追加することができます。 +このメソッドは、複数の制約を追加するために繰り返し呼び出すことができる。これは、`transform()` と`castTo()` の呼び出しと混在させることができます。 -オブジェクトへのマッピング: from() .[#toc-mapping-to-objects-from] ------------------------------------------------------ +変換: transform() .[#toc-transformation-transform] +------------------------------------------------ -クラスから構造体スキーマを生成することができます。例 +バリデーションに成功したデータは、カスタム関数を使用して変更することができます: ```php -class Config -{ - public string $name; - public string|null $password; - public bool $admin = false; -} +// conversion to uppercase: +Expect::string()->transform(fn(string $s) => strtoupper($s)); +``` -$schema = Expect::from(new Config); +このメソッドを繰り返し呼び出すことで、複数の変換を加えることができる。このメソッドは、`assert()` や`castTo()` の呼び出しと混在させることができる。操作は宣言された順番に実行される: -$data = [ - 'name' => 'jeff', -]; - -$normalized = $processor->process($schema, $data); -// $normalized instanceof Config -// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false} +```php +Expect::type('string|int') + ->castTo('string') + ->assert('ctype_lower', 'All characters must be lowercased') + ->transform(fn(string $s) => strtoupper($s)); // conversion to uppercase ``` -PHP 7.4 以降を使用している場合は、ネイティブタイプを使用することができます。 +`transform()` メソッドは、値の変換と検証を同時に行うことができる。これは、`transform()` と`assert()` を連鎖させるよりも単純で冗長性が少ないことが多い。この目的のために、この関数は`addError()` メソッドを持つ[Context |api:Nette\Schema\Context]オブジェクトを受け取ります: ```php -class Config -{ - public string $name; - public ?string $password; - public bool $admin = false; -} +Expect::string() + ->transform(function (string $s, Nette\Schema\Context $context) { + if (!ctype_lower($s)) { + $context->addError('All characters must be lowercased', 'my.case.error'); + return null; + } -$schema = Expect::from(new Config); + return strtoupper($s); + }); ``` -匿名クラスもサポートされています。 + +キャスト: castTo() .[#toc-casting-castto] +------------------------------------- + +バリデーションに成功したデータをキャストすることができます: ```php -$schema = Expect::from(new class { - public string $name; - public ?string $password; - public bool $admin = false; -}); +Expect::scalar()->castTo('string'); ``` -クラス定義から得られる情報だけでは十分でない場合があるため、2番目のパラメータで要素にカスタムスキーマを追加することができます。 +PHP ネイティブの型に加えて、クラスへのキャストも可能です。これは、コンストラクタのない単純なクラスなのかコンストラクタのあるクラスなのかを区別します。コンストラクタのないクラスの場合は、そのインスタンスが作成され、 構造体のすべての要素がそのプロパティに書き込まれます: ```php -$schema = Expect::from(new Config, [ - 'name' => Expect::string()->pattern('\w:.*'), -]); -``` +class Info +{ + public bool $processRefund; + public int $refundAmount; +} +Expect::structure([ + 'processRefund' => Expect::bool(), + 'refundAmount' => Expect::int(), +])->castTo(Info::class); -キャスト: castTo() .[#toc-casting-castto] -------------------------------------- +// creates '$obj = new Info' and writes to $obj->processRefund and $obj->refundAmount +``` -バリデーションに成功したデータをキャストすることができます。 +コンストラクタを持つクラスの場合、構造体の要素は名前付きパラメータとしてコンストラクタに渡されます: ```php -Expect::scalar()->castTo('string'); +class Info +{ + public function __construct( + public bool $processRefund, + public int $refundAmount, + ) { + } +} + +// creates $obj = new Info(processRefund: ..., refundAmount: ...) ``` -PHP のネイティブな型だけでなく、クラスへのキャストも可能です。 +キャストとスカラー・パラメータを組み合わせると、オブジェクトが生成され、その値が唯一のパラメータとしてコンストラクタに渡されます: ```php -Expect::scalar()->castTo('AddressEntity'); +Expect::string()->castTo(DateTime::class); +// creates new DateTime(...) ``` @@ -443,4 +454,47 @@ $normalized = $processor->process($schema, 'a b c'); // OK, returns ['a', 'b', 'c'] ``` -{{leftbar: nette:en:@menu-topics}} + +オブジェクトへのマッピング: from() .[#toc-mapping-to-objects-from] +----------------------------------------------------- + +クラスから構造スキーマを生成することができます。例 + +```php +class Config +{ + public string $name; + public string|null $password; + public bool $admin = false; +} + +$schema = Expect::from(new Config); + +$data = [ + 'name' => 'jeff', +]; + +$normalized = $processor->process($schema, $data); +// $normalized instanceof Config +// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false} +``` + +匿名クラスもサポートされています: + +```php +$schema = Expect::from(new class { + public string $name; + public ?string $password; + public bool $admin = false; +}); +``` + +クラス定義から得られる情報だけでは十分でない可能性があるため、2番目のパラメータで要素のカスタム・スキーマを追加できます: + +```php +$schema = Expect::from(new Config, [ + 'name' => Expect::string()->pattern('\w:.*'), +]); +``` + +{{leftbar: nette:@menu-topics}} diff --git a/schema/pl/@home.texy b/schema/pl/@home.texy index 4e9930ca5b..c05548476b 100644 --- a/schema/pl/@home.texy +++ b/schema/pl/@home.texy @@ -353,78 +353,89 @@ $processor->process($schema, ['a', 'b', 'c']); // Failed assertion "Even items in array" for item with value array. ``` -Metoda ta może być wywoływana wielokrotnie, aby dodać więcej ograniczeń. +Metoda ta może być wywoływana wielokrotnie w celu dodania wielu ograniczeń. Można ją łączyć z wywołaniami `transform()` i `castTo()`. -Mapowanie na obiekty: from() .[#toc-mapping-to-objects-from] ------------------------------------------------------------- +Transformacja: transform() .[#toc-transformation-transform] +----------------------------------------------------------- -Możemy mieć schemat struktury wygenerowany z klasy. Przykład: +Pomyślnie zweryfikowane dane można modyfikować za pomocą funkcji niestandardowej: ```php -class Config -{ - public string $name; - public string|null $password; - public bool $admin = false; -} - -$schema = Expect::from(new Config); +// conversion to uppercase: +Expect::string()->transform(fn(string $s) => strtoupper($s)); +``` -$data = [ - 'name' => 'franta', -]; +Metoda ta może być wywoływana wielokrotnie w celu dodania wielu przekształceń. Można ją mieszać z wywołaniami `assert()` i `castTo()`. Operacje będą wykonywane w kolejności, w jakiej zostały zadeklarowane: -$normalized = $processor->process($schema, $data); -// $normalized instanceof Config -// $normalized = {'name' => 'franta', 'password' => null, 'admin' => false} +```php +Expect::type('string|int') + ->castTo('string') + ->assert('ctype_lower', 'All characters must be lowercased') + ->transform(fn(string $s) => strtoupper($s)); // conversion to uppercase ``` -Jeśli używasz PHP 7.4 lub nowszego, możesz użyć typów natywnych: +Metoda `transform()` może jednocześnie przekształcać i weryfikować wartość. Jest to często prostsze i mniej zbędne niż łączenie metod `transform()` i `assert()`. W tym celu funkcja otrzymuje obiekt [Context |api:Nette\Schema\Context] z metodą `addError()`, która może być użyta do dodania informacji o kwestiach walidacji: ```php -class Config -{ - public string $name; - public ?string $password; - public bool $admin = false; -} +Expect::string() + ->transform(function (string $s, Nette\Schema\Context $context) { + if (!ctype_lower($s)) { + $context->addError('All characters must be lowercased', 'my.case.error'); + return null; + } -$schema = Expect::from(new Config); + return strtoupper($s); + }); ``` -Obsługiwane są również klasy anonimowe: + +Casting: castTo() .[#toc-casting-castto] +---------------------------------------- + +Pomyślnie zweryfikowane dane mogą być rzutowane: ```php -$schema = Expect::from(new class { - public string $name; - public ?string $password; - public bool $admin = false; -}); +Expect::scalar()->castTo('string'); ``` -Ponieważ informacje uzyskane z definicji klasy mogą nie być wystarczające, możesz użyć drugiego parametru, aby dodać własny schemat do elementów: +Oprócz natywnych typów PHP, można również rzutować na klasy. Rozróżnia to, czy jest to prosta klasa bez konstruktora, czy klasa z konstruktorem. Jeśli klasa nie ma konstruktora, tworzona jest jej instancja, a wszystkie elementy struktury są zapisywane w jej właściwościach: ```php -$schema = Expect::from(new Config, [ - 'name' => Expect::string()->pattern('\w:.*'), -]); -``` +class Info +{ + public bool $processRefund; + public int $refundAmount; +} +Expect::structure([ + 'processRefund' => Expect::bool(), + 'refundAmount' => Expect::int(), +])->castTo(Info::class); -Override: castTo() .[#toc-casting-castto] ------------------------------------------ +// creates '$obj = new Info' and writes to $obj->processRefund and $obj->refundAmount +``` -Pomyślnie zwalidowane dane mogą zostać poddane repatriacji: +Jeśli klasa ma konstruktor, elementy struktury są przekazywane jako nazwane parametry do konstruktora: ```php -Expect::scalar()->castTo('string'); +class Info +{ + public function __construct( + public bool $processRefund, + public int $refundAmount, + ) { + } +} + +// creates $obj = new Info(processRefund: ..., refundAmount: ...) ``` -Oprócz natywnych typów PHP, może być również przepisany na klasy: +Rzutowanie w połączeniu z parametrem skalarnym tworzy obiekt i przekazuje wartość jako jedyny parametr do konstruktora: ```php -Expect::scalar()->castTo('AddressEntity'); +Expect::string()->castTo(DateTime::class); +// creates new DateTime(...) ``` @@ -444,4 +455,47 @@ $normalized = $processor->process($schema, 'a b c'); ``` +Mapowanie do obiektów: from() .[#toc-mapping-to-objects-from] +------------------------------------------------------------- + +Można wygenerować schemat struktury z klasy. Przykład: + +```php +class Config +{ + public string $name; + public string|null $password; + public bool $admin = false; +} + +$schema = Expect::from(new Config); + +$data = [ + 'name' => 'jeff', +]; + +$normalized = $processor->process($schema, $data); +// $normalized instanceof Config +// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false} +``` + +Obsługiwane są również klasy anonimowe: + +```php +$schema = Expect::from(new class { + public string $name; + public ?string $password; + public bool $admin = false; +}); +``` + +Ponieważ informacje uzyskane z definicji klasy mogą nie być wystarczające, można dodać niestandardowy schemat dla elementów za pomocą drugiego parametru: + +```php +$schema = Expect::from(new Config, [ + 'name' => Expect::string()->pattern('\w:.*'), +]); +``` + +{{leftbar: nette:@menu-topics}} {{leftbar: nette:@menu-topics}} diff --git a/schema/pt/@home.texy b/schema/pt/@home.texy index 0184591815..76b78e5a6e 100644 --- a/schema/pt/@home.texy +++ b/schema/pt/@home.texy @@ -353,83 +353,94 @@ $processor->process($schema, ['a', 'b', 'c']); // afirmação falhada "Itens pares na matriz" para item com matriz de valores. ``` -O método pode ser chamado repetidamente para acrescentar mais afirmações. +O método pode ser chamado repetidamente para adicionar várias restrições. Ele pode ser misturado com chamadas para `transform()` e `castTo()`. -Mapeamento para Objetos: de() .[#toc-mapping-to-objects-from] -------------------------------------------------------------- +Transformação: transform() .[#toc-transformation-transform] +----------------------------------------------------------- -Você pode gerar um esquema de estrutura a partir da classe. Exemplo: +Os dados validados com sucesso podem ser modificados usando uma função personalizada: ```php -class Config -{ - public string $name; - public string|null $password; - public bool $admin = false; -} +// conversion to uppercase: +Expect::string()->transform(fn(string $s) => strtoupper($s)); +``` -$schema = Expect::from(new Config); +O método pode ser chamado repetidamente para adicionar várias transformações. Ele pode ser misturado com chamadas para `assert()` e `castTo()`. As operações serão executadas na ordem em que forem declaradas: -$data = [ - 'name' => 'jeff', -]; - -$normalized = $processor->process($schema, $data); -// $normalized instanceof Config -// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false} +```php +Expect::type('string|int') + ->castTo('string') + ->assert('ctype_lower', 'All characters must be lowercased') + ->transform(fn(string $s) => strtoupper($s)); // conversion to uppercase ``` -Se você estiver usando PHP 7.4 ou superior, você pode usar tipos nativos: +O método `transform()` pode transformar e validar o valor simultaneamente. Isso geralmente é mais simples e menos redundante do que encadear `transform()` e `assert()`. Para esse fim, a função recebe um objeto [Context |api:Nette\Schema\Context] com um método `addError()`, que pode ser usado para adicionar informações sobre problemas de validação: ```php -class Config -{ - public string $name; - public ?string $password; - public bool $admin = false; -} +Expect::string() + ->transform(function (string $s, Nette\Schema\Context $context) { + if (!ctype_lower($s)) { + $context->addError('All characters must be lowercased', 'my.case.error'); + return null; + } -$schema = Expect::from(new Config); + return strtoupper($s); + }); ``` -Aulas anônimas também são suportadas: + +Transmissão: castTo() .[#toc-casting-castto] +-------------------------------------------- + +Os dados validados com sucesso podem ser convertidos: ```php -$schema = Expect::from(new class { - public string $name; - public ?string $password; - public bool $admin = false; -}); +Expect::scalar()->castTo('string'); ``` -Como as informações obtidas da definição de classe podem não ser suficientes, pode-se adicionar um esquema personalizado para os elementos com o segundo parâmetro: +Além dos tipos nativos do PHP, você também pode converter para classes. Ele distingue se é uma classe simples sem um construtor ou uma classe com um construtor. Se a classe não tiver um construtor, será criada uma instância dela e todos os elementos da estrutura serão gravados em suas propriedades: ```php -$schema = Expect::from(new Config, [ - 'name' => Expect::string()->pattern('\w:.*'), -]); -``` +class Info +{ + public bool $processRefund; + public int $refundAmount; +} +Expect::structure([ + 'processRefund' => Expect::bool(), + 'refundAmount' => Expect::int(), +])->castTo(Info::class); -Fundição: castTo() .[#toc-casting-castto] ------------------------------------------ +// creates '$obj = new Info' and writes to $obj->processRefund and $obj->refundAmount +``` -Os dados validados com sucesso podem ser lançados: +Se a classe tiver um construtor, os elementos da estrutura serão passados como parâmetros nomeados para o construtor: ```php -Expect::scalar()->castTo('string'); +class Info +{ + public function __construct( + public bool $processRefund, + public int $refundAmount, + ) { + } +} + +// creates $obj = new Info(processRefund: ..., refundAmount: ...) ``` -Além dos tipos de PHP nativos, você também pode participar de aulas: +A conversão combinada com um parâmetro escalar cria um objeto e passa o valor como o único parâmetro para o construtor: ```php -Expect::scalar()->castTo('AddressEntity'); +Expect::string()->castTo(DateTime::class); +// creates new DateTime(...) ``` -Normalização: antes() .[#toc-normalization-before] --------------------------------------------------- +Normalização: before() .[#toc-normalization-before] +--------------------------------------------------- Antes da validação propriamente dita, os dados podem ser normalizados usando o método `before()`. Como exemplo, vamos ter um elemento que deve ser um conjunto de cordas (por exemplo `['a', 'b', 'c']`), mas recebe entrada sob a forma de um cordel `a b c`: @@ -443,4 +454,47 @@ $normalized = $processor->process($schema, 'a b c'); // OK, retorna ['a', 'b', 'c'] ``` + +Mapeamento para objetos: from() .[#toc-mapping-to-objects-from] +--------------------------------------------------------------- + +Você pode gerar um esquema de estrutura a partir da classe. Exemplo: + +```php +class Config +{ + public string $name; + public string|null $password; + public bool $admin = false; +} + +$schema = Expect::from(new Config); + +$data = [ + 'name' => 'jeff', +]; + +$normalized = $processor->process($schema, $data); +// $normalized instanceof Config +// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false} +``` + +Também há suporte para classes anônimas: + +```php +$schema = Expect::from(new class { + public string $name; + public ?string $password; + public bool $admin = false; +}); +``` + +Como as informações obtidas da definição da classe podem não ser suficientes, você pode adicionar um esquema personalizado para os elementos com o segundo parâmetro: + +```php +$schema = Expect::from(new Config, [ + 'name' => Expect::string()->pattern('\w:.*'), +]); +``` + {{leftbar: nette:@menu-topics}} diff --git a/schema/ro/@home.texy b/schema/ro/@home.texy index 8c257c1e51..16cb3060f3 100644 --- a/schema/ro/@home.texy +++ b/schema/ro/@home.texy @@ -353,78 +353,89 @@ $processor->process($schema, ['a', 'b', 'c']); // A eșuat aserțiunea "Even items in array" pentru elementul cu valoarea array. ``` -Metoda poate fi apelată în mod repetat pentru a adăuga mai multe afirmații. +Metoda poate fi apelată în mod repetat pentru a adăuga mai multe constrângeri. Ea poate fi amestecată cu apelurile la `transform()` și `castTo()`. -Maparea în obiecte: from() .[#toc-mapping-to-objects-from] +Transformare: transform() .[#toc-transformation-transform] ---------------------------------------------------------- -Puteți genera o schemă de structură din clasă. Exemplu: +Datele validate cu succes pot fi modificate cu ajutorul unei funcții personalizate: ```php -class Config -{ - public string $name; - public string|null $password; - public bool $admin = false; -} - -$schema = Expect::from(new Config); +// conversion to uppercase: +Expect::string()->transform(fn(string $s) => strtoupper($s)); +``` -$data = [ - 'name' => 'jeff', -]; +Metoda poate fi apelată în mod repetat pentru a adăuga mai multe transformări. Ea poate fi amestecată cu apeluri la `assert()` și `castTo()`. Operațiile vor fi executate în ordinea în care sunt declarate: -$normalized = $processor->process($schema, $data); -// $normalized instanceof Config -// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false} +```php +Expect::type('string|int') + ->castTo('string') + ->assert('ctype_lower', 'All characters must be lowercased') + ->transform(fn(string $s) => strtoupper($s)); // conversion to uppercase ``` -Dacă utilizați PHP 7.4 sau o versiune mai recentă, puteți utiliza tipuri native: +Metoda `transform()` poate transforma și valida valoarea simultan. Acest lucru este adesea mai simplu și mai puțin redundant decât înlănțuirea `transform()` și `assert()`. În acest scop, funcția primește un obiect [Context |api:Nette\Schema\Context] cu o metodă `addError()`, care poate fi utilizată pentru a adăuga informații despre problemele de validare: ```php -class Config -{ - public string $name; - public ?string $password; - public bool $admin = false; -} +Expect::string() + ->transform(function (string $s, Nette\Schema\Context $context) { + if (!ctype_lower($s)) { + $context->addError('All characters must be lowercased', 'my.case.error'); + return null; + } -$schema = Expect::from(new Config); + return strtoupper($s); + }); ``` -Clasele anonime sunt, de asemenea, acceptate: + +Casting: castTo() .[#toc-casting-castto] +---------------------------------------- + +Datele validate cu succes pot fi turnate: ```php -$schema = Expect::from(new class { - public string $name; - public ?string $password; - public bool $admin = false; -}); +Expect::scalar()->castTo('string'); ``` -Deoarece este posibil ca informațiile obținute din definiția clasei să nu fie suficiente, puteți adăuga o schemă personalizată pentru elemente cu ajutorul celui de-al doilea parametru: +În plus față de tipurile native PHP, puteți, de asemenea, să faceți cast la clase. Se distinge dacă este vorba de o clasă simplă fără constructor sau de o clasă cu constructor. În cazul în care clasa nu are constructor, se creează o instanță a acesteia și toate elementele structurii sunt scrise în proprietățile sale: ```php -$schema = Expect::from(new Config, [ - 'name' => Expect::string()->pattern('\w:.*'), -]); -``` +class Info +{ + public bool $processRefund; + public int $refundAmount; +} +Expect::structure([ + 'processRefund' => Expect::bool(), + 'refundAmount' => Expect::int(), +])->castTo(Info::class); -Casting: castTo() .[#toc-casting-castto] ----------------------------------------- +// creates '$obj = new Info' and writes to $obj->processRefund and $obj->refundAmount +``` -Datele validate cu succes pot fi turnate: +În cazul în care clasa are un constructor, elementele structurii sunt transmise constructorului ca parametri numiți: ```php -Expect::scalar()->castTo('string'); +class Info +{ + public function __construct( + public bool $processRefund, + public int $refundAmount, + ) { + } +} + +// creates $obj = new Info(processRefund: ..., refundAmount: ...) ``` -În plus față de tipurile native PHP, puteți, de asemenea, să faceți cast la clase: +Castingul combinat cu un parametru scalar creează un obiect și transmite valoarea acestuia ca unic parametru către constructor: ```php -Expect::scalar()->castTo('AddressEntity'); +Expect::string()->castTo(DateTime::class); +// creates new DateTime(...) ``` @@ -443,4 +454,47 @@ $normalized = $processor->process($schema, 'a b c'); // OK, returnează ['a', 'b', 'c'] ``` + +Maparea în obiecte: from() .[#toc-mapping-to-objects-from] +---------------------------------------------------------- + +Puteți genera o schemă de structură din clasă. Exemplu: + +```php +class Config +{ + public string $name; + public string|null $password; + public bool $admin = false; +} + +$schema = Expect::from(new Config); + +$data = [ + 'name' => 'jeff', +]; + +$normalized = $processor->process($schema, $data); +// $normalized instanceof Config +// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false} +``` + +Sunt acceptate și clasele anonime: + +```php +$schema = Expect::from(new class { + public string $name; + public ?string $password; + public bool $admin = false; +}); +``` + +Deoarece este posibil ca informațiile obținute din definiția clasei să nu fie suficiente, puteți adăuga o schemă personalizată pentru elemente cu ajutorul celui de-al doilea parametru: + +```php +$schema = Expect::from(new Config, [ + 'name' => Expect::string()->pattern('\w:.*'), +]); +``` + {{leftbar: nette:@menu-topics}} diff --git a/schema/ru/@home.texy b/schema/ru/@home.texy index a0c7ce1de8..e01893dc5a 100644 --- a/schema/ru/@home.texy +++ b/schema/ru/@home.texy @@ -264,8 +264,8 @@ $processor->process($schema, ['additional' => true]); // ОШИБКА ``` -Устаревшие элементы .{data-version:1.1} ---------------------------------------- +Устаревшие элементы +------------------- Вы можете объявить свойство устаревшим, используя метод `deprecated([string $message])`. Уведомления об устаревании возвращаются с помощью `$processor->getWarnings()`: @@ -353,78 +353,89 @@ $processor->process($schema, ['a', 'b', 'c']); // Неудачное утверждение "Четные элементы в массиве" для элемента с массивом значений. ``` -Этот метод можно вызывать многократно для добавления новых утверждений. +Этот метод можно вызывать многократно для добавления нескольких ограничений. Его можно смешивать с вызовами `transform()` и `castTo()`. -Сопоставление с объектами: from() ---------------------------------- +Трансформация: transform() .[#toc-transformation-transform] +----------------------------------------------------------- -Из класса можно сгенерировать схему структуры. Пример: +Успешно подтвержденные данные могут быть изменены с помощью пользовательской функции: ```php -class Config -{ - public string $name; - public string|null $password; - public bool $admin = false; -} - -$schema = Expect::from(new Config); +// conversion to uppercase: +Expect::string()->transform(fn(string $s) => strtoupper($s)); +``` -$data = [ - 'name' => 'jeff', -]; +Этот метод можно вызывать многократно для добавления нескольких преобразований. Он может перемежаться с вызовами `assert()` и `castTo()`. Операции будут выполняться в том порядке, в котором они объявлены: -$normalized = $processor->process($schema, $data); -// $normalized instanceof Config -// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false} +```php +Expect::type('string|int') + ->castTo('string') + ->assert('ctype_lower', 'All characters must be lowercased') + ->transform(fn(string $s) => strtoupper($s)); // conversion to uppercase ``` -Если вы используете PHP 7.4 или выше, вы можете использовать встроенные типы: +Метод `transform()` может одновременно преобразовывать и проверять значение. Это часто проще и менее избыточно, чем выстраивание цепочек `transform()` и `assert()`. Для этого функция получает объект [Context |api:Nette\Schema\Context] с методом `addError()`, который может быть использован для добавления информации о проблемах валидации: ```php -class Config -{ - public string $name; - public ?string $password; - public bool $admin = false; -} +Expect::string() + ->transform(function (string $s, Nette\Schema\Context $context) { + if (!ctype_lower($s)) { + $context->addError('All characters must be lowercased', 'my.case.error'); + return null; + } -$schema = Expect::from(new Config); + return strtoupper($s); + }); ``` -Поддерживаются также анонимные классы: + +Кастинг: castTo() .[#toc-casting-castto] +---------------------------------------- + +Успешно проверенные данные могут быть приведены: ```php -$schema = Expect::from(new class { - public string $name; - public ?string $password; - public bool $admin = false; -}); +Expect::scalar()->castTo('string'); ``` -Поскольку информации, полученной из определения класса, может быть недостаточно, вы можете добавить пользовательскую схему для элементов с помощью второго параметра: +Помимо собственных типов PHP, можно также приводить данные к классам. При этом различается, является ли это простой класс без конструктора или класс с конструктором. Если класс не имеет конструктора, то создается его экземпляр и в его свойства записываются все элементы структуры: ```php -$schema = Expect::from(new Config, [ - 'name' => Expect::string()->pattern('\w:.*'), -]); -``` +class Info +{ + public bool $processRefund; + public int $refundAmount; +} +Expect::structure([ + 'processRefund' => Expect::bool(), + 'refundAmount' => Expect::int(), +])->castTo(Info::class); -Приведение: castTo() --------------------- +// creates '$obj = new Info' and writes to $obj->processRefund and $obj->refundAmount +``` -Успешно проверенные данные могут быть отброшены: +Если класс имеет конструктор, то элементы структуры передаются конструктору в качестве именованных параметров: ```php -Expect::scalar()->castTo('string'); +class Info +{ + public function __construct( + public bool $processRefund, + public int $refundAmount, + ) { + } +} + +// creates $obj = new Info(processRefund: ..., refundAmount: ...) ``` -В дополнение к собственным типам PHP, вы также можете приводить к классам: +Кастинг в сочетании со скалярным параметром создает объект и передает его значение в качестве единственного параметра конструктору: ```php -Expect::scalar()->castTo('AddressEntity'); +Expect::string()->castTo(DateTime::class); +// creates new DateTime(...) ``` @@ -443,4 +454,47 @@ $normalized = $processor->process($schema, 'a b c'); // OK, возвращает ['a', 'b', 'c'] ``` + +Отображение на объекты: from() .[#toc-mapping-to-objects-from] +-------------------------------------------------------------- + +Из класса можно сгенерировать структурную схему. Пример: + +```php +class Config +{ + public string $name; + public string|null $password; + public bool $admin = false; +} + +$schema = Expect::from(new Config); + +$data = [ + 'name' => 'jeff', +]; + +$normalized = $processor->process($schema, $data); +// $normalized instanceof Config +// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false} +``` + +Поддерживаются также анонимные классы: + +```php +$schema = Expect::from(new class { + public string $name; + public ?string $password; + public bool $admin = false; +}); +``` + +Поскольку информации, полученной из определения класса, может быть недостаточно, можно добавить пользовательскую схему для элементов с помощью второго параметра: + +```php +$schema = Expect::from(new Config, [ + 'name' => Expect::string()->pattern('\w:.*'), +]); +``` + {{leftbar: nette:@menu-topics}} diff --git a/schema/sl/@home.texy b/schema/sl/@home.texy index 9af7ea6247..c8c5e6eea5 100644 --- a/schema/sl/@home.texy +++ b/schema/sl/@home.texy @@ -353,78 +353,89 @@ $processor->process($schema, ['a', 'b', 'c']); // Neuspešna trditev "Even items in array" za element z vrednostjo array. ``` -Metodo lahko večkrat pokličete, če želite dodati več trditev. +Metodo lahko večkrat pokličete, če želite dodati več omejitev. Lahko se meša s klici na `transform()` in `castTo()`. -Prikazovanje v predmete: from() .[#toc-mapping-to-objects-from] ---------------------------------------------------------------- +Transformacija: transform() .[#toc-transformation-transform] +------------------------------------------------------------ -Iz razreda lahko ustvarite strukturno shemo. Primer: +Uspešno potrjene podatke lahko spremenite s funkcijo po meri: ```php -class Config -{ - public string $name; - public string|null $password; - public bool $admin = false; -} +// conversion to uppercase: +Expect::string()->transform(fn(string $s) => strtoupper($s)); +``` -$schema = Expect::from(new Config); +Metodo je mogoče poklicati večkrat, da se doda več preoblikovanj. Lahko se meša s klici na `assert()` in `castTo()`. Operacije se izvedejo v vrstnem redu, v katerem so deklarirane: -$data = [ - 'name' => 'jeff', -]; - -$normalized = $processor->process($schema, $data); -// $normalized instanceof Config -// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false} +```php +Expect::type('string|int') + ->castTo('string') + ->assert('ctype_lower', 'All characters must be lowercased') + ->transform(fn(string $s) => strtoupper($s)); // conversion to uppercase ``` -Če uporabljate PHP 7.4 ali novejši, lahko uporabite nativne tipe: +Metoda `transform()` lahko hkrati preoblikuje in potrdi vrednost. To je pogosto preprostejše in manj odvečno kot veriženje metod `transform()` in `assert()`. V ta namen funkcija prejme objekt [Context |api:Nette\Schema\Context] z metodo `addError()`, ki jo lahko uporabimo za dodajanje informacij o težavah pri potrjevanju: ```php -class Config -{ - public string $name; - public ?string $password; - public bool $admin = false; -} +Expect::string() + ->transform(function (string $s, Nette\Schema\Context $context) { + if (!ctype_lower($s)) { + $context->addError('All characters must be lowercased', 'my.case.error'); + return null; + } -$schema = Expect::from(new Config); + return strtoupper($s); + }); ``` -Podprti so tudi anonimni razredi: + +Oddajanje: castTo() .[#toc-casting-castto] +------------------------------------------ + +Uspešno potrjene podatke je mogoče oddati: ```php -$schema = Expect::from(new class { - public string $name; - public ?string $password; - public bool $admin = false; -}); +Expect::scalar()->castTo('string'); ``` -Ker informacije, pridobljene iz definicije razreda, morda ne zadostujejo, lahko z drugim parametrom dodate shemo po meri za elemente: +Poleg izvornih tipov PHP lahko podatke prelijete tudi v razrede. Razlikuje, ali gre za preprost razred brez konstruktorja ali razred s konstruktorjem. Če razred nima konstruktorja, se ustvari njegov primerek, vsi elementi strukture pa se zapišejo v njegove lastnosti: ```php -$schema = Expect::from(new Config, [ - 'name' => Expect::string()->pattern('\w:.*'), -]); -``` +class Info +{ + public bool $processRefund; + public int $refundAmount; +} +Expect::structure([ + 'processRefund' => Expect::bool(), + 'refundAmount' => Expect::int(), +])->castTo(Info::class); -Kasting: castTo() .[#toc-casting-castto] ----------------------------------------- +// creates '$obj = new Info' and writes to $obj->processRefund and $obj->refundAmount +``` -Uspešno potrjene podatke je mogoče oddati: +Če ima razred konstruktor, se elementi strukture konstruktorju posredujejo kot poimenovani parametri: ```php -Expect::scalar()->castTo('string'); +class Info +{ + public function __construct( + public bool $processRefund, + public int $refundAmount, + ) { + } +} + +// creates $obj = new Info(processRefund: ..., refundAmount: ...) ``` -Poleg nativnih tipov PHP lahko podatke prelijete tudi v razrede: +Casting v kombinaciji s skalarnim parametrom ustvari objekt in konstruktorju posreduje vrednost kot edini parameter: ```php -Expect::scalar()->castTo('AddressEntity'); +Expect::string()->castTo(DateTime::class); +// creates new DateTime(...) ``` @@ -443,4 +454,47 @@ $normalized = $processor->process($schema, 'a b c'); // V redu, vrne ['a', 'b', 'c'] ``` + +preslikava v predmete: from() .[#toc-mapping-to-objects-from] +------------------------------------------------------------- + +Iz razreda lahko ustvarite strukturno shemo. Primer: + +```php +class Config +{ + public string $name; + public string|null $password; + public bool $admin = false; +} + +$schema = Expect::from(new Config); + +$data = [ + 'name' => 'jeff', +]; + +$normalized = $processor->process($schema, $data); +// $normalized instanceof Config +// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false} +``` + +Podprti so tudi anonimni razredi: + +```php +$schema = Expect::from(new class { + public string $name; + public ?string $password; + public bool $admin = false; +}); +``` + +Ker informacije, pridobljene iz definicije razreda, morda ne zadostujejo, lahko z drugim parametrom dodate shemo po meri za elemente: + +```php +$schema = Expect::from(new Config, [ + 'name' => Expect::string()->pattern('\w:.*'), +]); +``` + {{leftbar: nette:@menu-topics}} diff --git a/schema/tr/@home.texy b/schema/tr/@home.texy index 738448d658..a2be4b7dbb 100644 --- a/schema/tr/@home.texy +++ b/schema/tr/@home.texy @@ -353,78 +353,89 @@ $processor->process($schema, ['a', 'b', 'c']); // array değerine sahip öğe için "Even items in array" iddiası başarısız oldu. ``` -Yöntem, daha fazla onay eklemek için tekrar tekrar çağrılabilir. +Yöntem, birden fazla kısıtlama eklemek için tekrar tekrar çağrılabilir. `transform()` ve `castTo()` çağrıları ile karıştırılabilir. -Nesnelere Eşleme: from() .[#toc-mapping-to-objects-from] --------------------------------------------------------- +Dönüşüm: transform() .[#toc-transformation-transform] +----------------------------------------------------- -Sınıftan yapı şeması oluşturabilirsiniz. Örnek: +Başarıyla doğrulanan veriler özel bir işlev kullanılarak değiştirilebilir: ```php -class Config -{ - public string $name; - public string|null $password; - public bool $admin = false; -} +// conversion to uppercase: +Expect::string()->transform(fn(string $s) => strtoupper($s)); +``` -$schema = Expect::from(new Config); +Yöntem, birden fazla dönüşüm eklemek için tekrar tekrar çağrılabilir. `assert()` ve `castTo()` çağrıları ile karıştırılabilir. İşlemler bildirildikleri sırayla yürütülecektir: -$data = [ - 'name' => 'jeff', -]; - -$normalized = $processor->process($schema, $data); -// $normalized instanceof Config -// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false} +```php +Expect::type('string|int') + ->castTo('string') + ->assert('ctype_lower', 'All characters must be lowercased') + ->transform(fn(string $s) => strtoupper($s)); // conversion to uppercase ``` -PHP 7.4 veya daha üstünü kullanıyorsanız, yerel türleri kullanabilirsiniz: + `transform()` yöntemi değeri aynı anda hem dönüştürebilir hem de doğrulayabilir. Bu genellikle `transform()` ve `assert()` zincirlemesinden daha basit ve daha az gereksizdir. Bu amaçla, fonksiyon, doğrulama sorunları hakkında bilgi eklemek için kullanılabilecek bir `addError()` yöntemine sahip bir [Context |api:Nette\Schema\Context] nesnesi alır: ```php -class Config -{ - public string $name; - public ?string $password; - public bool $admin = false; -} +Expect::string() + ->transform(function (string $s, Nette\Schema\Context $context) { + if (!ctype_lower($s)) { + $context->addError('All characters must be lowercased', 'my.case.error'); + return null; + } -$schema = Expect::from(new Config); + return strtoupper($s); + }); ``` -Anonim sınıflar da desteklenmektedir: + +Döküm: castTo() .[#toc-casting-castto] +-------------------------------------- + +Başarıyla doğrulanan veriler dökülebilir: ```php -$schema = Expect::from(new class { - public string $name; - public ?string $password; - public bool $admin = false; -}); +Expect::scalar()->castTo('string'); ``` -Sınıf tanımından elde edilen bilgiler yeterli olmayabileceğinden, ikinci parametre ile elemanlar için özel bir şema ekleyebilirsiniz: +Yerel PHP türlerine ek olarak, sınıflara da döküm yapabilirsiniz. Yapıcısı olmayan basit bir sınıf mı yoksa yapıcısı olan bir sınıf mı olduğu ayırt edilir. Sınıfın kurucusu yoksa, bir örneği oluşturulur ve yapının tüm elemanları özelliklerine yazılır: ```php -$schema = Expect::from(new Config, [ - 'name' => Expect::string()->pattern('\w:.*'), -]); -``` +class Info +{ + public bool $processRefund; + public int $refundAmount; +} +Expect::structure([ + 'processRefund' => Expect::bool(), + 'refundAmount' => Expect::int(), +])->castTo(Info::class); -Döküm: castTo() .[#toc-casting-castto] --------------------------------------- +// creates '$obj = new Info' and writes to $obj->processRefund and $obj->refundAmount +``` -Başarıyla doğrulanan veriler dökülebilir: +Sınıfın bir yapıcısı varsa, yapının elemanları yapıcıya adlandırılmış parametreler olarak geçirilir: ```php -Expect::scalar()->castTo('string'); +class Info +{ + public function __construct( + public bool $processRefund, + public int $refundAmount, + ) { + } +} + +// creates $obj = new Info(processRefund: ..., refundAmount: ...) ``` -Yerel PHP türlerine ek olarak, sınıflara da döküm yapabilirsiniz: +Bir skaler parametre ile birlikte döküm bir nesne oluşturur ve değeri yapıcıya tek parametre olarak geçirir: ```php -Expect::scalar()->castTo('AddressEntity'); +Expect::string()->castTo(DateTime::class); +// creates new DateTime(...) ``` @@ -443,4 +454,47 @@ $normalized = $processor->process($schema, 'a b c'); // Tamam, ['a', 'b', 'c'] döndürür ``` + +Nesnelere Eşleme: from() .[#toc-mapping-to-objects-from] +-------------------------------------------------------- + +Sınıftan yapı şeması oluşturabilirsiniz. Örnek: + +```php +class Config +{ + public string $name; + public string|null $password; + public bool $admin = false; +} + +$schema = Expect::from(new Config); + +$data = [ + 'name' => 'jeff', +]; + +$normalized = $processor->process($schema, $data); +// $normalized instanceof Config +// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false} +``` + +Anonim sınıflar da desteklenmektedir: + +```php +$schema = Expect::from(new class { + public string $name; + public ?string $password; + public bool $admin = false; +}); +``` + +Sınıf tanımından elde edilen bilgiler yeterli olmayabileceğinden, ikinci parametre ile elemanlar için özel bir şema ekleyebilirsiniz: + +```php +$schema = Expect::from(new Config, [ + 'name' => Expect::string()->pattern('\w:.*'), +]); +``` + {{leftbar: nette:@menu-topics}} diff --git a/schema/uk/@home.texy b/schema/uk/@home.texy index 38bcea526e..44e37d9b68 100644 --- a/schema/uk/@home.texy +++ b/schema/uk/@home.texy @@ -353,78 +353,89 @@ $processor->process($schema, ['a', 'b', 'c']); // Невдале твердження "Парні елементи в масиві" для елемента з масивом значень. ``` -Цей метод можна викликати багаторазово для додавання нових тверджень. +Метод можна викликати багаторазово, щоб додати кілька обмежень. Його можна змішувати з викликами `transform()` та `castTo()`. -Зіставлення з об'єктами: from() .[#toc-sopostavlenie-s-ob-ektami-from] ----------------------------------------------------------------------- +Перетворення: transform() .[#toc-transformation-transform] +---------------------------------------------------------- -З класу можна згенерувати схему структури. Приклад: +Успішно перевірені дані можна змінити за допомогою спеціальної функції: ```php -class Config -{ - public string $name; - public string|null $password; - public bool $admin = false; -} +// conversion to uppercase: +Expect::string()->transform(fn(string $s) => strtoupper($s)); +``` -$schema = Expect::from(new Config); +Метод можна викликати багаторазово, щоб додати кілька перетворень. Його можна змішувати з викликами `assert()` та `castTo()`. Операції будуть виконані в тому порядку, в якому вони були оголошені: -$data = [ - 'name' => 'jeff', -]; - -$normalized = $processor->process($schema, $data); -// $normalized instanceof Config -// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false} +```php +Expect::type('string|int') + ->castTo('string') + ->assert('ctype_lower', 'All characters must be lowercased') + ->transform(fn(string $s) => strtoupper($s)); // conversion to uppercase ``` -Якщо ви використовуєте PHP 7.4 або вище, ви можете використовувати вбудовані типи: +Метод `transform()` може одночасно перетворювати і перевіряти значення. Часто це простіше і менш надлишково, ніж ланцюжок `transform()` і `assert()`. Для цього функція отримує об'єкт [Context |api:Nette\Schema\Context] з методом `addError()`, який можна використовувати для додавання інформації про проблеми з валідацією: ```php -class Config -{ - public string $name; - public ?string $password; - public bool $admin = false; -} +Expect::string() + ->transform(function (string $s, Nette\Schema\Context $context) { + if (!ctype_lower($s)) { + $context->addError('All characters must be lowercased', 'my.case.error'); + return null; + } -$schema = Expect::from(new Config); + return strtoupper($s); + }); ``` -Підтримуються також анонімні класи: + +Кастинг: castTo() .[#toc-casting-castto] +---------------------------------------- + +Успішно перевірені дані можуть бути закинуті: ```php -$schema = Expect::from(new class { - public string $name; - public ?string $password; - public bool $admin = false; -}); +Expect::scalar()->castTo('string'); ``` -Оскільки інформації, отриманої з визначення класу, може бути недостатньо, ви можете додати користувацьку схему для елементів за допомогою другого параметра: +На додаток до власних типів PHP, ви також можете виконувати приведення до класів. При цьому розрізняється, чи це простий клас без конструктора, чи клас з конструктором. Якщо клас не має конструктора, створюється його екземпляр і всі елементи структури записуються в його властивості: ```php -$schema = Expect::from(new Config, [ - 'name' => Expect::string()->pattern('\w:.*'), -]); -``` +class Info +{ + public bool $processRefund; + public int $refundAmount; +} +Expect::structure([ + 'processRefund' => Expect::bool(), + 'refundAmount' => Expect::int(), +])->castTo(Info::class); -Приведення: castTo() .[#toc-privedenie-castto] ----------------------------------------------- +// creates '$obj = new Info' and writes to $obj->processRefund and $obj->refundAmount +``` -Успішно перевірені дані можуть бути відкинуті: +Якщо клас має конструктор, то елементи структури передаються як іменовані параметри до конструктора: ```php -Expect::scalar()->castTo('string'); +class Info +{ + public function __construct( + public bool $processRefund, + public int $refundAmount, + ) { + } +} + +// creates $obj = new Info(processRefund: ..., refundAmount: ...) ``` -На додаток до власних типів PHP, ви також можете приводити до класів: +Приведення у поєднанні зі скалярним параметром створює об'єкт і передає значення як єдиний параметр до конструктора: ```php -Expect::scalar()->castTo('AddressEntity'); +Expect::string()->castTo(DateTime::class); +// creates new DateTime(...) ``` @@ -443,4 +454,47 @@ $normalized = $processor->process($schema, 'a b c'); // OK, повертає ['a', 'b', 'c'] ``` + +Відображення на об'єкти: from() .[#toc-mapping-to-objects-from] +--------------------------------------------------------------- + +Ви можете згенерувати схему структури з класу. Приклад: + +```php +class Config +{ + public string $name; + public string|null $password; + public bool $admin = false; +} + +$schema = Expect::from(new Config); + +$data = [ + 'name' => 'jeff', +]; + +$normalized = $processor->process($schema, $data); +// $normalized instanceof Config +// $normalized = {'name' => 'jeff', 'password' => null, 'admin' => false} +``` + +Також підтримуються анонімні класи: + +```php +$schema = Expect::from(new class { + public string $name; + public ?string $password; + public bool $admin = false; +}); +``` + +Оскільки інформації, отриманої з визначення класу, може бути недостатньо, ви можете додати власну схему для елементів за допомогою другого параметра: + +```php +$schema = Expect::from(new Config, [ + 'name' => Expect::string()->pattern('\w:.*'), +]); +``` + {{leftbar: nette:@menu-topics}} From 43d6215d8f0ae622d3b94f6109e265507c5d7ba2 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 4 Oct 2023 06:24:23 +0200 Subject: [PATCH 018/137] nette/application v3.1.14 --- application/bg/creating-links.texy | 2 +- application/bg/presenters.texy | 67 ++++++++++++++++++++++++------ application/cs/creating-links.texy | 2 +- application/cs/presenters.texy | 65 ++++++++++++++++++++++++----- application/de/creating-links.texy | 2 +- application/de/presenters.texy | 67 ++++++++++++++++++++++++------ application/el/creating-links.texy | 2 +- application/el/presenters.texy | 67 ++++++++++++++++++++++++------ application/en/creating-links.texy | 2 +- application/en/presenters.texy | 65 ++++++++++++++++++++++++----- application/es/creating-links.texy | 2 +- application/es/presenters.texy | 67 ++++++++++++++++++++++++------ application/fr/creating-links.texy | 2 +- application/fr/presenters.texy | 65 ++++++++++++++++++++++++----- application/hu/creating-links.texy | 2 +- application/hu/presenters.texy | 67 ++++++++++++++++++++++++------ application/it/creating-links.texy | 2 +- application/it/presenters.texy | 65 ++++++++++++++++++++++++----- application/pl/creating-links.texy | 2 +- application/pl/presenters.texy | 67 ++++++++++++++++++++++++------ application/pt/creating-links.texy | 2 +- application/pt/presenters.texy | 67 ++++++++++++++++++++++++------ application/ro/creating-links.texy | 2 +- application/ro/presenters.texy | 65 ++++++++++++++++++++++++----- application/ru/creating-links.texy | 2 +- application/ru/presenters.texy | 67 ++++++++++++++++++++++++------ application/sl/creating-links.texy | 2 +- application/sl/presenters.texy | 65 ++++++++++++++++++++++++----- application/tr/creating-links.texy | 2 +- application/tr/presenters.texy | 67 ++++++++++++++++++++++++------ application/uk/creating-links.texy | 2 +- application/uk/presenters.texy | 67 ++++++++++++++++++++++++------ 32 files changed, 890 insertions(+), 202 deletions(-) diff --git a/application/bg/creating-links.texy b/application/bg/creating-links.texy index 659326e6fe..f56a6f00fc 100644 --- a/application/bg/creating-links.texy +++ b/application/bg/creating-links.texy @@ -38,7 +38,7 @@ подробнее ``` -Ако методът `ProductPresenter::renderShow()` няма `$lang` в сигнатурата си, той може да прочете стойността на параметъра, като използва `$lang = $this->getParameter('lang')`. +Ако методът `ProductPresenter::renderShow()` няма `$lang` в сигнатурата си, той може да извлече стойността на параметъра, като използва `$lang = $this->getParameter('lang')` или от [свойството |presenters#Request Parameters]. Ако параметрите се съхраняват в масив, те могат да бъдат разширени с помощта на оператора `(expand)` (нещо като `...` в PHP, но работи с асоциативни масиви): diff --git a/application/bg/presenters.texy b/application/bg/presenters.texy index 53606e891f..76b510873b 100644 --- a/application/bg/presenters.texy +++ b/application/bg/presenters.texy @@ -236,6 +236,32 @@ public function actionData(): void ``` +Параметри на заявката .[#toc-request-parameters] +================================================ + +Презентаторът, както и всеки компонент, получава своите параметри от HTTP заявката. Стойностите им могат да бъдат извлечени с помощта на метода `getParameter($name)` или `getParameters()`. Стойностите са низове или масиви от низове, по същество сурови данни, получени директно от URL адреса. + +За по-голямо удобство препоръчваме да направите параметрите достъпни чрез свойства. Просто ги анотирайте с `#[Parameter]` атрибут: + +```php +use Nette\Application\Attributes\Parameter; // този ред е важен + +class HomePresenter extends Nette\Application\UI\Presenter +{ + #[Parameter] + public string $theme; // трябва да е публичен +} +``` + +За свойствата предлагаме да посочите типа данни (например `string`). След това Nette автоматично ще определи стойността въз основа на него. Стойностите на параметрите също могат да бъдат [валидирани |#Validation of Parameters]. + +Когато създавате връзка, можете директно да зададете стойност за параметрите: + +```latte +click +``` + + Постоянни параметри .[#toc-persistent-parameters] ================================================= @@ -257,7 +283,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter Ако `$this->lang` има стойност като `'en'`, то връзките, създадени с помощта на `link()` или `n:href`, ще съдържат и параметъра `lang=en`. И когато върху връзката се щракне, тя отново ще бъде `$this->lang = 'en'`. -За свойствата препоръчваме да включите типа данни (например `string`), а също така можете да включите стойност по подразбиране. Стойностите на параметрите могат да бъдат [валидирани |#Validation of Persistent Parameters]. +За свойствата препоръчваме да включите типа на данните (например `string`), като можете да включите и стойност по подразбиране. Стойностите на параметрите могат да бъдат [валидирани |#Validation of Parameters]. Постоянните параметри се предават между всички действия на даден презентатор по подразбиране. За да ги предадете между няколко водещи, трябва да ги дефинирате или: @@ -307,18 +333,12 @@ class ProductPresenter extends Nette\Application\UI\Presenter Това, което показахме досега в тази глава, вероятно ще бъде достатъчно. Следващите редове са за тези, които се интересуват от презентаторите обстойно и искат да знаят всичко. -Изисквания и параметри .[#toc-requirement-and-parameters] ---------------------------------------------------------- +Утвърждаване на параметрите .[#toc-validation-of-parameters] +------------------------------------------------------------ -Заявката, която се обработва от водещия, е обектът [api:Nette\Application\Request] и се връща от метода на водещия `getRequest()`. Тя включва масив от параметри и всеки от тях принадлежи или на някой от компонентите, или директно на водещия (който всъщност също е компонент, макар и специален). Затова Nette преразпределя параметрите и преминава между отделните компоненти (и водещия), като извиква метода `loadState(array $params)`. Параметрите могат да бъдат получени чрез метода `getParameters(): array`, а поотделно чрез `getParameter($name)`. Стойностите на параметрите са низове или масиви от низове, те по същество са необработени данни, получени директно от URL адреса. +Стойностите на [параметрите на заявката |#request parameters] и [постоянните параметри, |#persistent parameters] получени от URL адреси, се записват в свойствата чрез метода `loadState()`. Той също така проверява дали типът данни, посочен в свойството, съвпада, в противен случай ще отговори с грешка 404 и страницата няма да бъде показана. - -Утвърждаване на постоянни параметри .[#toc-validation-of-persistent-parameters] -------------------------------------------------------------------------------- - -Стойностите на [постоянните параметри, |#persistent parameters] получени от URL адреси, се записват в свойствата чрез метода `loadState()`. Той също така проверява дали типът данни, посочен в свойството, съвпада, в противен случай ще отговори с грешка 404 и страницата няма да бъде показана. - -Никога не се доверявайте сляпо на постоянните параметри, тъй като те лесно могат да бъдат пренаписани от потребителя в URL адреса. Например, така проверяваме дали `$this->lang` е сред поддържаните езици. Добър начин да направите това е да пренастроите метода `loadState()`, споменат по-горе: +Никога не се доверявайте сляпо на параметрите, тъй като те лесно могат да бъдат пренаписани от потребителя в URL адреса. Например, така проверяваме дали `$this->lang` е сред поддържаните езици. Добър начин да направите това е да презапишете метода `loadState()`, споменат по-горе: ```php class ProductPresenter extends Nette\Application\UI\Presenter @@ -341,7 +361,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter Запазване и възстановяване на заявка .[#toc-save-and-restore-the-request] ------------------------------------------------------------------------- -Можете да запазите текущата заявка в сесия или да я възстановите от сесия и да позволите на водещия да я изпълни отново. Това е полезно, например когато потребителят попълни формуляр и срокът му на влизане изтече. За да избегнем загубата на данни, преди да пренасочим към страницата за регистрация, запазваме текущата заявка в сесията с функцията `$reqId = $this->storeRequest()`, която връща идентификатора като кратък низ и го предава като параметър на водещия за регистрация. +Заявката, която се обработва от водещия, е обект [api:Nette\Application\Request] и се връща от метода на водещия `getRequest()`. + +Можете да запазите текущата заявка в сесия или да я възстановите от сесия и да позволите на водещия да я изпълни отново. Това е полезно, например, когато потребител попълни формуляр и срокът на неговото влизане в системата изтече. За да не загубим данни, преди да пренасочим към страницата за вписване, запазваме текущата заявка в сесия с помощта на `$reqId = $this->storeRequest()`, която връща идентификатор под формата на кратък низ и го предава като параметър на презентатора за вписване. След като влезем в системата, извикваме метода `$this->restoreRequest($reqId)`, който извлича заявката от сесията и я препраща към нея. Методът проверява дали заявката е създадена от същия потребител, който в момента е влязъл в системата. Ако е влязъл друг потребител или ключът е невалиден, не се прави нищо и програмата продължава. @@ -425,6 +447,27 @@ $this->sendResponse(new Responses\CallbackResponse($callback)); ``` +Проверка на метода HTTP .[#toc-http-method-check] +------------------------------------------------- + +Презентаторите в Nette автоматично проверяват HTTP метода на всяка входяща заявка. Основната причина за тази проверка е сигурността. Проверката на метода се извършва в `checkHttpMethod()`, който определя дали методът, посочен в заявката, е включен в масива `$presenter->allowedMethods`. По подразбиране този масив съдържа елементите `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`, което означава, че тези методи са разрешени. + +Ако желаете допълнително да разрешите метода `OPTIONS`, това може да се постигне по следния начин: + +```php +class MyPresenter extends Nette\Application\UI\Presenter +{ + protected function checkHttpMethod(): void + { + $this->allowedMethods[] = 'OPTIONS'; + parent::checkHttpMethod(); + } +} +``` + +Изключително важно е да се подчертае, че ако разрешите метода `OPTIONS`, трябва също така да го обработвате правилно в рамките на вашия презентатор. Този метод често се използва като така наречената preflight заявка, която браузърите автоматично изпращат преди действителната заявка, когато е необходимо да се определи дали заявката е разрешена от гледна точка на политиката CORS (Cross-Origin Resource Sharing). Ако разрешите този метод, но не приложите подходящ отговор, това може да доведе до несъответствия и потенциални проблеми със сигурността. + + Допълнително четене .[#toc-further-reading] =========================================== diff --git a/application/cs/creating-links.texy b/application/cs/creating-links.texy index a21c986098..6c30a94e62 100644 --- a/application/cs/creating-links.texy +++ b/application/cs/creating-links.texy @@ -38,7 +38,7 @@ Je možné předávat i pojmenované parametry. Následující odkaz předává detail produktu ``` -Pokud metoda `ProductPresenter::renderShow()` nemá `$lang` ve své signatuře, může si hodnotu parametru zjistit pomocí `$lang = $this->getParameter('lang')`. +Pokud metoda `ProductPresenter::renderShow()` nemá `$lang` ve své signatuře, může si hodnotu parametru zjistit pomocí `$lang = $this->getParameter('lang')` nebo z [property |presenters#Parametry požadavku]. Pokud jsou parametry uložené v poli, lze je rozvinout operátorem `...` (v Latte 2.x operátorem `(expand)`): diff --git a/application/cs/presenters.texy b/application/cs/presenters.texy index 41be48834b..14dad81a49 100644 --- a/application/cs/presenters.texy +++ b/application/cs/presenters.texy @@ -236,6 +236,32 @@ public function actionData(): void ``` +Parametry požadavku .{data-version:3.1.14} +========================================== + +Presenter a také každá komponenta získává z HTTP požadavku své parametry. Jejich hodnotu zjistíte metodou `getParameter($name)` nebo `getParameters()`. Hodnoty jsou řetězce či pole řetězců, jde v podstatě o surové data získané přímo z URL. + +Pro větší pohodlí doporučujeme parametry zpřístupnit přes property. Stačí je označit atributem `#[Parameter]`: + +```php +use Nette\Application\Attributes\Parameter; // tento řádek je důležitý + +class HomePresenter extends Nette\Application\UI\Presenter +{ + #[Parameter] + public string $theme; // musí být public +} +``` + +U property doporučujeme uvádět i datový typ (např. `string`) a Nette podle něj hodnotu automaticky přetypuje. Hodnoty parametrů lze také [validovat |#Validace parametrů]. + +Při vytváření odkazu lze parametrům hodnotu přímo nastavit: + +```latte +click +``` + + Persistentní parametry ====================== @@ -257,7 +283,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter Pokud bude `$this->lang` mít hodnotu například `'en'`, tak i odkazy vytvořené pomocí `link()` nebo `n:href` budou obsahovat parameter `lang=en`. A po kliknutí na odkaz bude opět `$this->lang = 'en'`. -U property doporučujeme uvádět i datový typ (např. `string`) a můžete uvést i výchozí hodnotu. Hodnoty parametrů lze [validovat |#Validace persistentních parametrů]. +U property doporučujeme uvádět i datový typ (např. `string`) a můžete uvést i výchozí hodnotu. Hodnoty parametrů lze [validovat |#Validace parametrů]. Persistentní parametry se standardně přenášejí mezi všemi akcemi daného presenteru. Aby se přenášely i mezi více presentery, je potřeba je definovat buď: @@ -307,18 +333,12 @@ Jdeme do hloubky S tím, co jsme si dosud v této kapitole ukázali, si nejspíš úplně vystačíte. Následující řádky jsou určeny těm, kdo se zajímají o presentery do hloubky a chtějí vědět úplně všechno. -Požadavek a parametry ---------------------- +Validace parametrů +------------------ -Požadavek, který vyřizuje presenter, je objekt [api:Nette\Application\Request] a vrací ho metoda presenteru `getRequest()`. Jeho součástí je pole parametrů a každý z nich patří buď některé z komponent, nebo přímo presenteru (což je vlastně také komponenta, byť speciální). Nette tedy parametry přerozdělí a předá mezi jednotlivé komponenty (a presenter) zavoláním metody `loadState(array $params)`. Získat parametry lze metodu `getParameters(): array`, jednotlivě pomocí `getParameter($name)`. Hodnoty parametrů jsou řetězce či pole řetězců, jde v podstatě o surové data získané přímo z URL. +Hodnoty [parametrů požadavku |#Parametry požadavku] a [persistentních parametrů |#Persistentní parametry] přijatých z URL zapisuje do properties metoda `loadState()`. Ta také kontroluje, zda odpovídá datový typ uvedený u property, jinak odpoví chybou 404 a stránka se nezobrazí. - -Validace persistentních parametrů ---------------------------------- - -Hodnoty [persistentních parametrů |#Persistentní parametry] přijatých z URL zapisuje do properties metoda `loadState()`. Ta také kontroluje, zda odpovídá datový typ uvedený u property, jinak odpoví chybou 404 a stránka se nezobrazí. - -Nikdy slepě nevěřte persistentním parametrům, protože mohou být snadno uživatelem přepsány v URL. Takto například ověříme, zda je jazyk `$this->lang` mezi podporovanými. Vhodnou cestou je přepsat zmíněnou metodu `loadState()`: +Nikdy slepě nevěřte parametrům, protože mohou být snadno uživatelem přepsány v URL. Takto například ověříme, zda je jazyk `$this->lang` mezi podporovanými. Vhodnou cestou je přepsat zmíněnou metodu `loadState()`: ```php class ProductPresenter extends Nette\Application\UI\Presenter @@ -341,6 +361,8 @@ class ProductPresenter extends Nette\Application\UI\Presenter Uložení a obnovení požadavku ---------------------------- +Požadavek, který vyřizuje presenter, je objekt [api:Nette\Application\Request] a vrací ho metoda presenteru `getRequest()`. + Aktuální požadavek lze uložit do session nebo naopak z ní obnovit a nechat jej presenter znovu vykonat. To se hodí například v situaci, když uživatel vyplňuje formulář a vyprší mu přihlášení. Aby o data nepřišel, před přesměrováním na přihlašovací stránku aktuální požadavek uložíme do session pomocí `$reqId = $this->storeRequest()`, které vrátí jeho identifikátor v podobě krátkého řetězce a ten předáme jako parameter přihlašovacímu presenteru. Po přihlášení zavoláme metodu `$this->restoreRequest($reqId)`, která požadavek vyzvedne ze session a forwarduje na něj. Metoda přitom ověří, že požadavek vytvořil stejný uživatel, jako se nyní přihlásil. Pokud by se přihlásil jiný uživatel nebo klíč byl neplatný, neudělá nic a program pokračuje dál. @@ -425,6 +447,27 @@ $this->sendResponse(new Responses\CallbackResponse($callback)); ``` +Kontrola HTTP metody +-------------------- + +Presentery v Nette automaticky ověřují HTTP metodu každého příchozího požadavku. Důvodem pro tuto kontrolu je především bezpečnost. Ověření metody se provádí v `checkHttpMethod()`, která zjišťuje, zda je metoda specifikovaná v požadavku obsažena v poli `$presenter->allowedMethods`. To standardně obsahuje položky `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`, tedy tyto metody jsou povoleny. + +Chcete-li povolit navíc metodu `OPTIONS`, je možné toho dosáhnout následujícím způsobem: + +```php +class MyPresenter extends Nette\Application\UI\Presenter +{ + protected function checkHttpMethod(): void + { + $this->allowedMethods[] = 'OPTIONS'; + parent::checkHttpMethod(); + } +} +``` + +Je důležité zdůraznit, že pokud povolíte metodu `OPTIONS`, musíte ji následně také patřičně obsloužit v rámci svého presenteru. Metoda je často používána jako tzv. preflight request, který prohlížeč automaticky odesílá před skutečným požadavkem, když je potřeba zjistit, zda je požadavek povolený z hlediska CORS (Cross-Origin Resource Sharing) politiky. Pokud metodu povolíte, ale neimplementujete správnou odpověď, může to vést k nekonzistencím a potenciálním bezpečnostním problémům. + + Další četba =========== diff --git a/application/de/creating-links.texy b/application/de/creating-links.texy index 1ec3fbd1e9..b462d2177f 100644 --- a/application/de/creating-links.texy +++ b/application/de/creating-links.texy @@ -38,7 +38,7 @@ Es ist auch möglich, benannte Parameter zu übergeben. Der folgende Link überg detail ``` -Wenn die Methode `ProductPresenter::renderShow()` nicht `$lang` in ihrer Signatur hat, kann sie den Wert des Parameters mit `$lang = $this->getParameter('lang')` lesen. +Wenn die Methode `ProductPresenter::renderShow()` nicht `$lang` in ihrer Signatur hat, kann sie den Wert des Parameters über `$lang = $this->getParameter('lang')` oder über die [Eigenschaft |presenters#Request Parameters] abrufen. Wenn die Parameter in einem Array gespeichert sind, können sie mit dem `...` -Operator (oder `(expand)` -Operator in Latte 2.x) expandiert werden: diff --git a/application/de/presenters.texy b/application/de/presenters.texy index 35bc4c3513..b96fcc7772 100644 --- a/application/de/presenters.texy +++ b/application/de/presenters.texy @@ -236,6 +236,32 @@ public function actionData(): void ``` +Parameter anfordern .[#toc-request-parameters] +============================================== + +Der Präsentator, wie auch jede Komponente, bezieht seine Parameter aus der HTTP-Anfrage. Ihre Werte können mit der Methode `getParameter($name)` oder `getParameters()` abgerufen werden. Bei den Werten handelt es sich um Strings oder Arrays von Strings, also im Wesentlichen um Rohdaten, die direkt aus der URL bezogen werden. + +Für zusätzlichen Komfort empfiehlt es sich, die Parameter über Eigenschaften zugänglich zu machen. Beschriften Sie sie einfach mit dem `#[Parameter]` Attribut: + +```php +use Nette\Application\Attributes\Parameter; // diese Zeile ist wichtig + +class HomePresenter extends Nette\Application\UI\Presenter +{ + #[Parameter] + public string $theme; // muss öffentlich sein +} +``` + +Für Eigenschaften empfehlen wir die Angabe des Datentyps (z. B. `string`). Nette wird den Wert dann automatisch auf der Grundlage dieses Typs umwandeln. Parameterwerte können auch [validiert |#Validation of Parameters] werden. + +Beim Erstellen einer Verknüpfung können Sie den Wert für die Parameter direkt festlegen: + +```latte +click +``` + + Dauerhafte Parameter .[#toc-persistent-parameters] ================================================== @@ -257,7 +283,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter Wenn `$this->lang` einen Wert wie `'en'` hat, dann werden Links, die mit `link()` oder `n:href` erstellt werden, auch den Parameter `lang=en` enthalten. Und wenn der Link angeklickt wird, wird er wieder `$this->lang = 'en'` sein. -Für Eigenschaften wird empfohlen, den Datentyp anzugeben (z. B. `string`), und Sie können auch einen Standardwert angeben. Parameterwerte können [validiert |#Validation of Persistent Parameters] werden. +Für Eigenschaften wird empfohlen, den Datentyp anzugeben (z. B. `string`), und Sie können auch einen Standardwert angeben. Parameterwerte können [validiert |#Validation of Parameters] werden. Persistente Parameter werden standardmäßig zwischen allen Aktionen eines bestimmten Präsentators weitergegeben. Um sie zwischen mehreren Präsentatoren zu übergeben, müssen Sie sie entweder definieren: @@ -307,18 +333,12 @@ Tiefer gehen .[#toc-going-deeper] Was wir bisher in diesem Kapitel gezeigt haben, wird wahrscheinlich ausreichen. Die folgenden Zeilen sind für diejenigen gedacht, die sich eingehend mit Moderatoren beschäftigen und alles wissen wollen. -Anforderung und Parameter .[#toc-requirement-and-parameters] ------------------------------------------------------------- +Validierung von Parametern .[#toc-validation-of-parameters] +----------------------------------------------------------- -Die vom Präsentator bearbeitete Anfrage ist das Objekt [api:Nette\Application\Request] und wird von der Methode `getRequest()` des Präsentators zurückgegeben. Sie enthält ein Array von Parametern, und jeder von ihnen gehört entweder zu einer der Komponenten oder direkt zum Präsentator (der eigentlich auch eine Komponente ist, wenn auch eine spezielle). Nette verteilt also die Parameter um und übergibt sie zwischen den einzelnen Komponenten (und dem Präsentator) durch Aufruf der Methode `loadState(array $params)`. Die Parameter können mit der Methode `getParameters(): array`, einzeln mit `getParameter($name)` abgerufen werden. Bei den Parameterwerten handelt es sich um Strings oder Arrays von Strings, also im Grunde um Rohdaten, die direkt aus einer URL bezogen werden. +Die Werte von [Anfrageparametern |#request parameters] und [dauerhaften Parametern |#persistent parameters], die von URLs empfangen werden, werden von der Methode `loadState()` in Eigenschaften geschrieben. Sie prüft auch, ob der in der Eigenschaft angegebene Datentyp übereinstimmt, andernfalls antwortet sie mit einem 404-Fehler und die Seite wird nicht angezeigt. - -Validierung von persistenten Parametern .[#toc-validation-of-persistent-parameters] ------------------------------------------------------------------------------------ - -Die Werte von [persistenten Parametern |#persistent parameters], die von URLs empfangen werden, werden von der Methode `loadState()` in Eigenschaften geschrieben. Sie prüft auch, ob der in der Eigenschaft angegebene Datentyp übereinstimmt, andernfalls antwortet sie mit einem 404-Fehler und die Seite wird nicht angezeigt. - -Verlassen Sie sich niemals blind auf persistente Parameter, da sie leicht vom Benutzer in der URL überschrieben werden können. So überprüfen wir zum Beispiel, ob `$this->lang` zu den unterstützten Sprachen gehört. Eine gute Möglichkeit, dies zu tun, besteht darin, die oben erwähnte Methode `loadState()` zu überschreiben: +Verlassen Sie sich niemals blind auf Parameter, da sie leicht vom Benutzer in der URL überschrieben werden können. So überprüfen wir zum Beispiel, ob `$this->lang` zu den unterstützten Sprachen gehört. Eine gute Möglichkeit, dies zu tun, besteht darin, die oben erwähnte Methode `loadState()` zu überschreiben: ```php class ProductPresenter extends Nette\Application\UI\Presenter @@ -341,7 +361,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter Speichern und Wiederherstellen der Anfrage .[#toc-save-and-restore-the-request] ------------------------------------------------------------------------------- -Sie können die aktuelle Anfrage in einer Session speichern oder sie aus der Session wiederherstellen und den Präsentator sie erneut ausführen lassen. Dies ist z. B. nützlich, wenn ein Benutzer ein Formular ausfüllt und seine Anmeldung abläuft. Um keine Daten zu verlieren, speichern wir vor der Routing zur Anmeldeseite die aktuelle Anfrage in der Session mit `$reqId = $this->storeRequest()`, die einen Bezeichner in Form einer kurzen Zeichenkette zurückgibt und ihn als Parameter an den Anmeldepräsentator übergibt. +Die Anfrage, die der Präsentator bearbeitet, ist ein Objekt [api:Nette\Application\Request] und wird von der Methode `getRequest()` des Präsentators zurückgegeben. + +Sie können die aktuelle Anfrage in einer Sitzung speichern oder sie aus der Sitzung wiederherstellen und den Präsentator sie erneut ausführen lassen. Dies ist z. B. nützlich, wenn ein Benutzer ein Formular ausfüllt und sein Login abläuft. Um keine Daten zu verlieren, speichern wir vor der Weiterleitung zur Anmeldeseite die aktuelle Anfrage in der Sitzung mit `$reqId = $this->storeRequest()`, die einen Bezeichner in Form eines kurzen Strings zurückgibt und diesen als Parameter an den Anmeldepräsentator übergibt. Nach der Anmeldung rufen wir die Methode `$this->restoreRequest($reqId)` auf, die die Anfrage aus der Session abholt und an diese weiterleitet. Die Methode prüft, ob die Anfrage von demselben Benutzer erstellt wurde, der jetzt angemeldet ist. Wenn sich ein anderer Benutzer anmeldet oder der Schlüssel ungültig ist, tut sie nichts und das Programm läuft weiter. @@ -425,6 +447,27 @@ $this->sendResponse(new Responses\CallbackResponse($callback)); ``` +HTTP-Methodenprüfung .[#toc-http-method-check] +---------------------------------------------- + +Die Präsentatoren in Nette überprüfen automatisch die HTTP-Methode jeder eingehenden Anfrage. Der Hauptgrund für diese Überprüfung ist die Sicherheit. Die Methodenprüfung wird in `checkHttpMethod()` durchgeführt, das feststellt, ob die in der Anfrage angegebene Methode im Array `$presenter->allowedMethods` enthalten ist. Standardmäßig enthält dieses Array die Einträge `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`, was bedeutet, dass diese Methoden erlaubt sind. + +Wenn Sie zusätzlich die Methode `OPTIONS` zulassen möchten, können Sie dies auf folgende Weise erreichen: + +```php +class MyPresenter extends Nette\Application\UI\Presenter +{ + protected function checkHttpMethod(): void + { + $this->allowedMethods[] = 'OPTIONS'; + parent::checkHttpMethod(); + } +} +``` + +Es ist wichtig zu betonen, dass, wenn Sie die `OPTIONS` -Methode zulassen, Sie sie auch in Ihrem Präsentator richtig behandeln müssen. Diese Methode wird häufig als so genannte Preflight-Anfrage verwendet, die von Browsern automatisch vor der eigentlichen Anfrage gesendet wird, wenn es darum geht, festzustellen, ob die Anfrage aus Sicht der CORS-Richtlinie (Cross-Origin Resource Sharing) zulässig ist. Wenn Sie diese Methode zulassen, aber keine angemessene Antwort implementieren, kann dies zu Inkonsistenzen und potenziellen Sicherheitsproblemen führen. + + Weitere Lektüre .[#toc-further-reading] ======================================= diff --git a/application/el/creating-links.texy b/application/el/creating-links.texy index e36d982225..8d8c27fc2c 100644 --- a/application/el/creating-links.texy +++ b/application/el/creating-links.texy @@ -38,7 +38,7 @@ detail ``` -Εάν η μέθοδος `ProductPresenter::renderShow()` δεν έχει στην υπογραφή της την `$lang`, μπορεί να διαβάσει την τιμή της παραμέτρου χρησιμοποιώντας την `$lang = $this->getParameter('lang')`. +Εάν η μέθοδος `ProductPresenter::renderShow()` δεν έχει στην υπογραφή της την `$lang`, μπορεί να ανακτήσει την τιμή της παραμέτρου χρησιμοποιώντας την `$lang = $this->getParameter('lang')` ή από την [ιδιότητα |presenters#Request Parameters]. Εάν οι παράμετροι είναι αποθηκευμένες σε πίνακα, μπορούν να επεκταθούν με τον τελεστή `...` (ή `(expand)` στο Latte 2.x): diff --git a/application/el/presenters.texy b/application/el/presenters.texy index 07cb8b4482..820803188d 100644 --- a/application/el/presenters.texy +++ b/application/el/presenters.texy @@ -236,6 +236,32 @@ public function actionData(): void ``` +Παράμετροι αίτησης .[#toc-request-parameters] +============================================= + +Ο παρουσιαστής, όπως και κάθε στοιχείο, λαμβάνει τις παραμέτρους του από την αίτηση HTTP. Οι τιμές τους μπορούν να ανακτηθούν χρησιμοποιώντας τη μέθοδο `getParameter($name)` ή `getParameters()`. Οι τιμές είναι συμβολοσειρές ή πίνακες συμβολοσειρών, ουσιαστικά ακατέργαστα δεδομένα που λαμβάνονται απευθείας από τη διεύθυνση URL. + +Για μεγαλύτερη ευκολία, συνιστούμε να κάνετε τις παραμέτρους προσβάσιμες μέσω ιδιοτήτων. Απλά σχολιάστε τις με την εντολή `#[Parameter]` χαρακτηριστικό: + +```php +use Nette\Application\Attributes\Parameter; // αυτή η γραμμή είναι σημαντική + +class HomePresenter extends Nette\Application\UI\Presenter +{ + #[Parameter] + public string $theme; // πρέπει να είναι δημόσια +} +``` + +Για τις ιδιότητες, προτείνουμε να προσδιορίσετε τον τύπο δεδομένων (π.χ. `string`). Στη συνέχεια, η Nette θα μετατρέψει αυτόματα την τιμή με βάση αυτόν. Οι τιμές των παραμέτρων μπορούν επίσης να [επικυρωθούν |#Validation of Parameters]. + +Κατά τη δημιουργία ενός συνδέσμου, μπορείτε να ορίσετε απευθείας την τιμή για τις παραμέτρους: + +```latte +click +``` + + Εμμένουσες παράμετροι .[#toc-persistent-parameters] =================================================== @@ -257,7 +283,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter Εάν το `$this->lang` έχει μια τιμή όπως `'en'`, τότε οι σύνδεσμοι που δημιουργούνται με χρήση των `link()` ή `n:href` θα περιέχουν επίσης την παράμετρο `lang=en`. Και όταν ο σύνδεσμος πατηθεί, θα είναι και πάλι `$this->lang = 'en'`. -Για τις ιδιότητες, συνιστούμε να περιλαμβάνετε τον τύπο δεδομένων (π.χ. `string`) και μπορείτε επίσης να συμπεριλάβετε μια προεπιλεγμένη τιμή. Οι τιμές των παραμέτρων μπορούν να [επικυρωθούν |#Validation of Persistent Parameters]. +Για τις ιδιότητες, συνιστούμε να συμπεριλάβετε τον τύπο δεδομένων (π.χ. `string`) και μπορείτε επίσης να συμπεριλάβετε μια προεπιλεγμένη τιμή. Οι τιμές των παραμέτρων μπορούν να [επικυρωθούν |#Validation of Parameters]. Οι μόνιμες παράμετροι μεταβιβάζονται μεταξύ όλων των ενεργειών ενός συγκεκριμένου παρουσιαστή από προεπιλογή. Για να τις περάσετε μεταξύ πολλαπλών παρουσιαστών, πρέπει να τις ορίσετε είτε: @@ -307,18 +333,12 @@ class ProductPresenter extends Nette\Application\UI\Presenter Όσα έχουμε δείξει μέχρι στιγμής σε αυτό το κεφάλαιο μάλλον αρκούν. Οι επόμενες γραμμές απευθύνονται σε όσους ενδιαφέρονται για τους παρουσιαστές σε βάθος και θέλουν να μάθουν τα πάντα. -Απαίτηση και παράμετροι .[#toc-requirement-and-parameters] ----------------------------------------------------------- +Επικύρωση των παραμέτρων .[#toc-validation-of-parameters] +--------------------------------------------------------- -Το αίτημα που χειρίζεται ο παρουσιαστής είναι το αντικείμενο [api:Nette\Application\Request] και επιστρέφεται από τη μέθοδο του παρουσιαστή `getRequest()`. Περιλαμβάνει έναν πίνακα παραμέτρων και κάθε μία από αυτές ανήκει είτε σε κάποιο από τα συστατικά είτε απευθείας στον παρουσιαστή (ο οποίος στην πραγματικότητα είναι επίσης ένα συστατικό, αν και ειδικό). Έτσι, η Nette ανακατανέμει τις παραμέτρους και περνάει μεταξύ των επιμέρους συστατικών (και του παρουσιαστή) καλώντας τη μέθοδο `loadState(array $params)`. Οι παράμετροι μπορούν να ληφθούν με τη μέθοδο `getParameters(): array`, μεμονωμένα με τη χρήση του `getParameter($name)`. Οι τιμές των παραμέτρων είναι συμβολοσειρές ή πίνακες συμβολοσειρών, είναι ουσιαστικά ακατέργαστα δεδομένα που λαμβάνονται απευθείας από μια διεύθυνση URL. +Οι τιμές των [παραμέτρων αίτησης |#request parameters] και των [μόνιμων παραμέτρων |#persistent parameters] που λαμβάνονται από τις διευθύνσεις URL εγγράφονται στις ιδιότητες από τη μέθοδο `loadState()`. Ελέγχει επίσης αν ο τύπος δεδομένων που καθορίζεται στην ιδιότητα ταιριάζει, διαφορετικά θα απαντήσει με σφάλμα 404 και η σελίδα δεν θα εμφανιστεί. - -Επικύρωση μόνιμων παραμέτρων .[#toc-validation-of-persistent-parameters] ------------------------------------------------------------------------- - -Οι τιμές των [μόνιμων παραμέτρων |#persistent parameters] που λαμβάνονται από τις διευθύνσεις URL εγγράφονται στις ιδιότητες με τη μέθοδο `loadState()`. Ελέγχει επίσης αν ο τύπος δεδομένων που καθορίζεται στην ιδιότητα ταιριάζει, διαφορετικά θα απαντήσει με σφάλμα 404 και η σελίδα δεν θα εμφανιστεί. - -Ποτέ μην εμπιστεύεστε τυφλά τις μόνιμες παραμέτρους, καθώς μπορούν εύκολα να αντικατασταθούν από τον χρήστη στη διεύθυνση URL. Για παράδειγμα, με αυτόν τον τρόπο ελέγχουμε αν το `$this->lang` είναι μεταξύ των υποστηριζόμενων γλωσσών. Ένας καλός τρόπος για να το κάνετε αυτό είναι να παρακάμψετε τη μέθοδο `loadState()` που αναφέρθηκε παραπάνω: +Ποτέ μην εμπιστεύεστε τυφλά τις παραμέτρους, καθώς μπορούν εύκολα να αντικατασταθούν από τον χρήστη στη διεύθυνση URL. Για παράδειγμα, με αυτόν τον τρόπο ελέγχουμε αν το `$this->lang` είναι μεταξύ των υποστηριζόμενων γλωσσών. Ένας καλός τρόπος για να το κάνετε αυτό είναι να παρακάμψετε τη μέθοδο `loadState()` που αναφέρθηκε παραπάνω: ```php class ProductPresenter extends Nette\Application\UI\Presenter @@ -341,7 +361,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter Αποθήκευση και επαναφορά της αίτησης .[#toc-save-and-restore-the-request] ------------------------------------------------------------------------- -Μπορείτε να αποθηκεύσετε την τρέχουσα αίτηση σε μια συνεδρία ή να την επαναφέρετε από τη συνεδρία και να αφήσετε τον παρουσιαστή να την εκτελέσει ξανά. Αυτό είναι χρήσιμο, για παράδειγμα, όταν ένας χρήστης συμπληρώνει μια φόρμα και λήγει η σύνδεσή του. Για να μην χαθούν δεδομένα, πριν από την ανακατεύθυνση στη σελίδα σύνδεσης, αποθηκεύουμε το τρέχον αίτημα στη σύνοδο χρησιμοποιώντας το `$reqId = $this->storeRequest()`, το οποίο επιστρέφει ένα αναγνωριστικό με τη μορφή σύντομης συμβολοσειράς και το περνάει ως παράμετρο στον παρουσιαστή σύνδεσης. +Το αίτημα που χειρίζεται ο παρουσιαστής είναι ένα αντικείμενο [api:Nette\Application\Request] και επιστρέφεται από τη μέθοδο του παρουσιαστή `getRequest()`. + +Μπορείτε να αποθηκεύσετε την τρέχουσα αίτηση σε μια συνεδρία ή να την επαναφέρετε από τη συνεδρία και να αφήσετε τον παρουσιαστή να την εκτελέσει ξανά. Αυτό είναι χρήσιμο, για παράδειγμα, όταν ένας χρήστης συμπληρώνει μια φόρμα και η σύνδεσή του λήγει. Για να μην χαθούν δεδομένα, πριν από την ανακατεύθυνση στη σελίδα σύνδεσης, αποθηκεύουμε την τρέχουσα αίτηση στη σύνοδο χρησιμοποιώντας τη μέθοδο `$reqId = $this->storeRequest()`, η οποία επιστρέφει ένα αναγνωριστικό με τη μορφή σύντομης συμβολοσειράς και το περνάει ως παράμετρο στον παρουσιαστή σύνδεσης. Μετά την είσοδο, καλούμε τη μέθοδο `$this->restoreRequest($reqId)`, η οποία παραλαμβάνει το αίτημα από τη σύνοδο και το προωθεί σε αυτήν. Η μέθοδος επαληθεύει ότι το αίτημα δημιουργήθηκε από τον ίδιο χρήστη που τώρα έχει συνδεθεί είναι. Αν συνδεθεί άλλος χρήστης ή το κλειδί είναι άκυρο, δεν κάνει τίποτα και το πρόγραμμα συνεχίζει. @@ -425,6 +447,27 @@ $this->sendResponse(new Responses\CallbackResponse($callback)); ``` +Έλεγχος μεθόδου HTTP .[#toc-http-method-check] +---------------------------------------------- + +Οι παρουσιαστές στη Nette ελέγχουν αυτόματα τη μέθοδο HTTP κάθε εισερχόμενης αίτησης. Ο κύριος λόγος για αυτή την επαλήθευση είναι η ασφάλεια. Ο έλεγχος της μεθόδου πραγματοποιείται στο `checkHttpMethod()`, το οποίο καθορίζει αν η μέθοδος που καθορίζεται στην αίτηση περιλαμβάνεται στον πίνακα `$presenter->allowedMethods`. Από προεπιλογή, αυτός ο πίνακας περιέχει τα στοιχεία `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`, που σημαίνει ότι αυτές οι μέθοδοι επιτρέπονται. + +Αν θέλετε να επιτρέψετε επιπλέον τη μέθοδο `OPTIONS`, αυτό μπορεί να επιτευχθεί με τον ακόλουθο τρόπο: + +```php +class MyPresenter extends Nette\Application\UI\Presenter +{ + protected function checkHttpMethod(): void + { + $this->allowedMethods[] = 'OPTIONS'; + parent::checkHttpMethod(); + } +} +``` + +Είναι ζωτικής σημασίας να τονιστεί ότι αν επιτρέψετε τη μέθοδο `OPTIONS`, πρέπει επίσης να τη χειριστείτε σωστά μέσα στον παρουσιαστή σας. Αυτή η μέθοδος χρησιμοποιείται συχνά ως το λεγόμενο preflight request, το οποίο οι φυλλομετρητές στέλνουν αυτόματα πριν από το πραγματικό αίτημα, όταν είναι απαραίτητο να καθοριστεί αν το αίτημα επιτρέπεται από την άποψη της πολιτικής CORS (Cross-Origin Resource Sharing). Εάν επιτρέψετε αυτή τη μέθοδο αλλά δεν υλοποιήσετε μια κατάλληλη απάντηση, μπορεί να οδηγήσει σε ασυνέπειες και πιθανά ζητήματα ασφάλειας. + + Περαιτέρω ανάγνωση .[#toc-further-reading] ========================================== diff --git a/application/en/creating-links.texy b/application/en/creating-links.texy index 0fb783c609..6cac071b7d 100644 --- a/application/en/creating-links.texy +++ b/application/en/creating-links.texy @@ -38,7 +38,7 @@ It is also possible to pass named parameters. The following link passes paramete detail ``` -If method `ProductPresenter::renderShow()` does not have `$lang` in its signature, it can read the value of the parameter using `$lang = $this->getParameter('lang')`. +If the method `ProductPresenter::renderShow()` does not have `$lang` in its signature, it can retrieve the value of the parameter using `$lang = $this->getParameter('lang')` or from the [property |presenters#Request Parameters]. If the parameters are stored in an array, they can be expanded with the `...` operator (or `(expand)` operator in Latte 2.x): diff --git a/application/en/presenters.texy b/application/en/presenters.texy index e653f0945c..a7b72959fb 100644 --- a/application/en/presenters.texy +++ b/application/en/presenters.texy @@ -236,6 +236,32 @@ public function actionData(): void ``` +Request Parameters .{data-version:3.1.14} +========================================= + +The presenter, as well as every component, obtains its parameters from the HTTP request. Their values can be retrieved using the `getParameter($name)` method or `getParameters()`. The values are strings or arrays of strings, essentially raw data obtained directly from the URL. + +For added convenience, we recommend making parameters accessible through properties. Simply annotate them with the `#[Parameter]` attribute: + +```php +use Nette\Application\Attributes\Parameter; // this line is important + +class HomePresenter extends Nette\Application\UI\Presenter +{ + #[Parameter] + public string $theme; // must be public +} +``` + +For properties, we suggest specifying the data type (e.g., `string`). Nette will then automatically cast the value based on it. Parameter values can be also [validated |#Validation of Parameters]. + +When creating a link, you can directly set the value for the parameters: + +```latte +click +``` + + Persistent Parameters ===================== @@ -257,7 +283,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter If `$this->lang` has a value such as `'en'`, then links created using `link()` or `n:href` will also contain the `lang=en` parameter. And when the link is clicked, it will again be `$this->lang = 'en'`. -For properties, we recommend that you include the data type (e.g. `string`) and you can also include a default value. Parameter values can be [validated |#Validation of Persistent Parameters]. +For properties, we recommend that you include the data type (e.g. `string`) and you can also include a default value. Parameter values can be [validated |#Validation of Parameters]. Persistent parameters are passed between all actions of a given presenter by default. To pass them between multiple presenters, you need to define them either: @@ -307,18 +333,12 @@ Going Deeper What we have shown so far in this chapter will probably suffice. The following lines are intended for those who are interested in presenters in depth and want to know everything. -Requirement and Parameters --------------------------- +Validation of Parameters +------------------------ -The request handled by the presenter is the [api:Nette\Application\Request] object and is returned by the presenter's method `getRequest()`. It includes an array of parameters and each of them belongs either to some of the components or directly to the presenter (which is actually also a component, albeit a special one). So Nette redistributes the parameters and passes between the individual components (and the presenter) by calling the method `loadState(array $params)`. The parameters can be obtained by the method `getParameters(): array`, individually using `getParameter($name)`. Parameter values ​​are strings or arrays of strings, they are basically raw data obtained directly from a URL. +The values of [#request parameters] and [#persistent parameters] received from URLs are written to properties by the `loadState()` method. It also checks if the data type specified in the property matches, otherwise it will respond with a 404 error and the page will not be displayed. - -Validation of Persistent Parameters ------------------------------------ - -The values of [#persistent parameters] received from URLs are written to properties by the `loadState()` method. It also checks if the data type specified in the property matches, otherwise it will respond with a 404 error and the page will not be displayed. - -Never blindly trust persistent parameters, as they can easily be overwritten by the user in the URL. For example, this is how we check if `$this->lang` is among the supported languages. A good way to do this is to override the `loadState()` method mentioned above: +Never blindly trust parameters, as they can easily be overwritten by the user in the URL. For example, this is how we check if `$this->lang` is among the supported languages. A good way to do this is to override the `loadState()` method mentioned above: ```php class ProductPresenter extends Nette\Application\UI\Presenter @@ -341,6 +361,8 @@ class ProductPresenter extends Nette\Application\UI\Presenter Save and Restore the Request ---------------------------- +The request that the presenter handles is an object [api:Nette\Application\Request] and is returned by the presenter's method `getRequest()`. + You can save the current request to a session or restore it from the session and let the presenter execute it again. This is useful, for example, when a user fills out a form and its login expires. In order not to lose data, before redirecting to the sign-in page, we save the current request to the session using `$reqId = $this->storeRequest()`, which returns an identifier in the form of a short string and passes it as a parameter to the sign-in presenter. After sign in, we call the method `$this->restoreRequest($reqId)`, which picks up the request from the session and forwards it to it. The method verifies that the request was created by the same user as now logged in is. If another user logs in or the key is invalid, it does nothing and the program continues. @@ -425,6 +447,27 @@ $this->sendResponse(new Responses\CallbackResponse($callback)); ``` +HTTP Method Check +----------------- + +Presenters in Nette automatically verify the HTTP method of every incoming request. The primary reason for this verification is security. The method check is carried out in `checkHttpMethod()`, which determines if the method specified in the request is included in the `$presenter->allowedMethods` array. By default, this array contains the items `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`, meaning these methods are allowed. + +If you wish to additionally allow the `OPTIONS` method, it can be achieved in the following manner: + +```php +class MyPresenter extends Nette\Application\UI\Presenter +{ + protected function checkHttpMethod(): void + { + $this->allowedMethods[] = 'OPTIONS'; + parent::checkHttpMethod(); + } +} +``` + +It's crucial to emphasize that if you enable the `OPTIONS` method, you must also properly handle it within your presenter. This method is often used as a so-called preflight request, which browsers automatically send before the actual request when it's necessary to determine if the request is allowed from the standpoint of CORS (Cross-Origin Resource Sharing) policy. If you allow this method but do not implement an appropriate response, it can lead to inconsistencies and potential security issues. + + Further Reading =============== diff --git a/application/es/creating-links.texy b/application/es/creating-links.texy index cd4645f3a5..d6e63a4bcb 100644 --- a/application/es/creating-links.texy +++ b/application/es/creating-links.texy @@ -38,7 +38,7 @@ También es posible pasar parámetros con nombre. El siguiente enlace pasa el pa detail ``` -Si el método `ProductPresenter::renderShow()` no tiene `$lang` en su firma, puede leer el valor del parámetro usando `$lang = $this->getParameter('lang')`. +Si el método `ProductPresenter::renderShow()` no tiene `$lang` en su firma, puede recuperar el valor del parámetro utilizando `$lang = $this->getParameter('lang')` o desde la [propiedad |presenters#Request Parameters]. Si los parámetros se almacenan en una matriz, pueden expandirse con el operador `...` (o `(expand)` en Latte 2.x): diff --git a/application/es/presenters.texy b/application/es/presenters.texy index c85c74305c..8007ff63de 100644 --- a/application/es/presenters.texy +++ b/application/es/presenters.texy @@ -236,6 +236,32 @@ public function actionData(): void ``` +Parámetros de solicitud .[#toc-request-parameters] +================================================== + +El presentador, al igual que todos los componentes, obtiene sus parámetros de la petición HTTP. Sus valores pueden recuperarse utilizando el método `getParameter($name)` o `getParameters()`. Los valores son cadenas o matrices de cadenas, esencialmente datos sin procesar obtenidos directamente de la URL. + +Para mayor comodidad, recomendamos que los parámetros sean accesibles a través de propiedades. Basta con anotarlas con el atributo `#[Parameter]` atributo: + +```php +use Nette\Application\Attributes\Parameter; // esta línea es importante + +class HomePresenter extends Nette\Application\UI\Presenter +{ + #[Parameter] + public string $theme; // debe ser pública +} +``` + +Para las propiedades, le sugerimos que especifique el tipo de datos (por ejemplo, `string`). A continuación, Nette asignará automáticamente el valor basándose en él. Los valores de los parámetros también pueden [validarse |#Validation of Parameters]. + +Al crear un enlace, puede establecer directamente el valor de los parámetros: + +```latte +click +``` + + Parámetros persistentes .[#toc-persistent-parameters] ===================================================== @@ -257,7 +283,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter Si `$this->lang` tiene un valor como `'en'`, entonces los enlaces creados usando `link()` o `n:href` también contendrán el parámetro `lang=en`. Y cuando se haga clic en el enlace, volverá a ser `$this->lang = 'en'`. -Para las propiedades, se recomienda incluir el tipo de datos (por ejemplo, `string`) y también se puede incluir un valor por defecto. Los valores de los parámetros se pueden [validar |#Validation of Persistent Parameters]. +Para las propiedades, le recomendamos que incluya el tipo de datos (por ejemplo, `string`) y también puede incluir un valor por defecto. Los valores de los parámetros se pueden [validar |#Validation of Parameters]. Los parámetros persistentes se pasan entre todas las acciones de un presentador determinado por defecto. Para pasarlos entre varios presentadores, es necesario definirlos: @@ -307,18 +333,12 @@ Profundizando .[#toc-going-deeper] Lo que hemos mostrado hasta ahora en este capítulo probablemente será suficiente. Las líneas siguientes están pensadas para quienes estén interesados en los presentadores en profundidad y quieran saberlo todo. -Requisitos y parámetros .[#toc-requirement-and-parameters] ----------------------------------------------------------- +Validación de parámetros .[#toc-validation-of-parameters] +--------------------------------------------------------- -La solicitud gestionada por el presentador es el objeto [api:Nette\Application\Request] y es devuelta por el método del presentador `getRequest()`. Incluye una matriz de parámetros y cada uno de ellos pertenece a alguno de los componentes o directamente al presentador (que en realidad también es un componente, aunque especial). Así pues, Nette redistribuye los parámetros y los pasa entre los distintos componentes (y el presentador) llamando al método `loadState(array $params)`. Los parámetros pueden obtenerse mediante el método `getParameters(): array`, individualmente mediante `getParameter($name)`. Los valores de los parámetros son cadenas o matrices de cadenas, son básicamente datos en bruto obtenidos directamente de una URL. +Los valores de los parámetros de [petición |#request parameters] y [de los parámetros persistentes |#persistent parameters] recibidos de las URLs son escritos en propiedades por el método `loadState()`. También comprueba si el tipo de datos especificado en la propiedad coincide, de lo contrario responderá con un error 404 y la página no se mostrará. - -Validación de parámetros persistentes .[#toc-validation-of-persistent-parameters] ---------------------------------------------------------------------------------- - -Los valores de los parámetros [persistentes |#persistent parameters] recibidos de las URLs son escritos en propiedades por el método `loadState()`. También comprueba si el tipo de datos especificado en la propiedad coincide, de lo contrario responderá con un error 404 y no se mostrará la página. - -Nunca confíes ciegamente en los parámetros persistentes, ya que pueden ser fácilmente sobrescritos por el usuario en la URL. Por ejemplo, así es como comprobamos si `$this->lang` está entre los idiomas soportados. Una buena forma de hacerlo es sobrescribir el método `loadState()` mencionado anteriormente: +Nunca confíes ciegamente en los parámetros, ya que pueden ser fácilmente sobrescritos por el usuario en la URL. Por ejemplo, así es como comprobamos si `$this->lang` está entre los idiomas soportados. Una buena forma de hacerlo es sobrescribir el método `loadState()` mencionado anteriormente: ```php class ProductPresenter extends Nette\Application\UI\Presenter @@ -341,7 +361,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter Guardar y restaurar la petición .[#toc-save-and-restore-the-request] -------------------------------------------------------------------- -Puede guardar la solicitud actual en una sesión o restaurarla desde la sesión y dejar que el presentador la ejecute de nuevo. Esto es útil, por ejemplo, cuando un usuario rellena un formulario y su login expira. Para no perder datos, antes de redirigir a la página de inicio de sesión, guardamos la solicitud actual en la sesión utilizando `$reqId = $this->storeRequest()`, que devuelve un identificador en forma de cadena corta y lo pasa como parámetro al presentador de inicio de sesión. +La solicitud que gestiona el presentador es un objeto [api:Nette\Application\Request] y la devuelve el método del presentador `getRequest()`. + +Puede guardar la solicitud actual en una sesión o restaurarla desde la sesión y dejar que el presentador la ejecute de nuevo. Esto es útil, por ejemplo, cuando un usuario rellena un formulario y su login caduca. Para no perder datos, antes de redirigir a la página de inicio de sesión, guardamos la solicitud actual en la sesión mediante `$reqId = $this->storeRequest()`, que devuelve un identificador en forma de cadena corta y lo pasa como parámetro al presentador de inicio de sesión. Después de iniciar sesión, llamamos al método `$this->restoreRequest($reqId)`, que recoge la solicitud de la sesión y se la reenvía. El método verifica que la petición ha sido creada por el mismo usuario que ahora ha iniciado la sesión. Si otro usuario inicia sesión o la clave no es válida, no hace nada y el programa continúa. @@ -425,6 +447,27 @@ $this->sendResponse(new Responses\CallbackResponse($callback)); ``` +Comprobación del método HTTP .[#toc-http-method-check] +------------------------------------------------------ + +Los presentadores en Nette verifican automáticamente el método HTTP de cada solicitud entrante. La razón principal de esta verificación es la seguridad. La comprobación del método se lleva a cabo en `checkHttpMethod()`, que determina si el método especificado en la petición está incluido en la matriz `$presenter->allowedMethods`. Por defecto, esta matriz contiene los elementos `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`, lo que significa que estos métodos están permitidos. + +Si desea permitir adicionalmente el método `OPTIONS`, puede conseguirlo de la siguiente manera: + +```php +class MyPresenter extends Nette\Application\UI\Presenter +{ + protected function checkHttpMethod(): void + { + $this->allowedMethods[] = 'OPTIONS'; + parent::checkHttpMethod(); + } +} +``` + +Es crucial enfatizar que si permite el método `OPTIONS`, también debe manejarlo adecuadamente dentro de su presentador. Este método se utiliza a menudo como una solicitud de comprobación previa, que los navegadores envían automáticamente antes de la solicitud real cuando es necesario determinar si la solicitud está permitida desde el punto de vista de la política CORS (Cross-Origin Resource Sharing). Si permite este método pero no implementa una respuesta adecuada, puede provocar incoherencias y posibles problemas de seguridad. + + Lecturas complementarias .[#toc-further-reading] ================================================ diff --git a/application/fr/creating-links.texy b/application/fr/creating-links.texy index c6786ac362..0c6c184066 100644 --- a/application/fr/creating-links.texy +++ b/application/fr/creating-links.texy @@ -38,7 +38,7 @@ Il est également possible de passer des paramètres nommés. Le lien suivant pa detail ``` -Si la méthode `ProductPresenter::renderShow()` n'a pas `$lang` dans sa signature, elle peut lire la valeur du paramètre en utilisant `$lang = $this->getParameter('lang')`. +Si la méthode `ProductPresenter::renderShow()` n'a pas `$lang` dans sa signature, elle peut récupérer la valeur du paramètre à l'aide de `$lang = $this->getParameter('lang')` ou de la [propriété |presenters#Request Parameters]. Si les paramètres sont stockés dans un tableau, ils peuvent être développés avec l'opérateur `...` (ou `(expand)` dans Latte 2.x) : diff --git a/application/fr/presenters.texy b/application/fr/presenters.texy index b6a772400e..fb2e2e361c 100644 --- a/application/fr/presenters.texy +++ b/application/fr/presenters.texy @@ -236,6 +236,32 @@ public function actionData(): void ``` +Paramètres de la demande .[#toc-request-parameters] +=================================================== + +Le présentateur, ainsi que chaque composant, obtient ses paramètres à partir de la demande HTTP. Leurs valeurs peuvent être récupérées à l'aide de la méthode `getParameter($name)` ou `getParameters()`. Les valeurs sont des chaînes ou des tableaux de chaînes, essentiellement des données brutes obtenues directement à partir de l'URL. + +Pour plus de commodité, nous recommandons de rendre les paramètres accessibles par le biais de propriétés. Il suffit de les annoter avec l'attribut `#[Parameter]` attribut : + +```php +use Nette\Application\Attributes\Parameter; // cette ligne est importante + +class HomePresenter extends Nette\Application\UI\Presenter +{ + #[Parameter] + public string $theme; // doit être publique +} +``` + +Pour les propriétés, nous suggérons de spécifier le type de données (par exemple, `string`). Nette va alors automatiquement calculer la valeur en fonction de ce type de données. Les valeurs des paramètres peuvent également être [validées |#Validation of Parameters]. + +Lors de la création d'un lien, vous pouvez directement définir la valeur des paramètres : + +```latte +click +``` + + Paramètres persistants .[#toc-persistent-parameters] ==================================================== @@ -257,7 +283,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter Si `$this->lang` a une valeur telle que `'en'`, les liens créés à l'aide de `link()` ou `n:href` contiendront également le paramètre `lang=en`. Et lorsque le lien sera cliqué, il s'agira à nouveau de `$this->lang = 'en'`. -Pour les propriétés, nous vous recommandons d'indiquer le type de données (par exemple `string`) et vous pouvez également inclure une valeur par défaut. Les valeurs des paramètres peuvent être [validées |#Validation of Persistent Parameters]. +Pour les propriétés, nous vous recommandons d'indiquer le type de données (par exemple `string`) et vous pouvez également inclure une valeur par défaut. Les valeurs des paramètres peuvent être [validées |#Validation of Parameters]. Les paramètres persistants sont transmis par défaut entre toutes les actions d'un présentateur donné. Pour les transmettre entre plusieurs présentateurs, vous devez les définir : @@ -307,18 +333,12 @@ Pour aller plus loin .[#toc-going-deeper] Ce que nous avons montré jusqu'à présent dans ce chapitre suffira probablement. Les lignes suivantes sont destinées à ceux qui s'intéressent aux présentateurs en profondeur et veulent tout savoir. -Exigences et paramètres .[#toc-requirement-and-parameters] +Validation des paramètres .[#toc-validation-of-parameters] ---------------------------------------------------------- -La requête traitée par le présentateur est l'objet [api:Nette\Application\Request] et est renvoyée par la méthode du présentateur `getRequest()`. Elle comprend un tableau de paramètres et chacun d'entre eux appartient soit à l'un des composants, soit directement au présentateur (qui est également un composant, bien qu'il soit spécial). Nette redistribue donc les paramètres et les transmet entre les différents composants (et le présentateur) en appelant la méthode `loadState(array $params)`. Les paramètres peuvent être obtenus par la méthode `getParameters(): array`, individuellement en utilisant `getParameter($name)`. Les valeurs des paramètres sont des chaînes ou des tableaux de chaînes, il s'agit essentiellement de données brutes obtenues directement à partir d'une URL. +Les valeurs des [paramètres de requête |#request parameters] et des [paramètres persistants |#persistent parameters] reçus des URL sont écrites dans les propriétés par la méthode `loadState()`. Elle vérifie également si le type de données spécifié dans la propriété correspond, sinon elle répondra par une erreur 404 et la page ne sera pas affichée. - -Validation des paramètres persistants .[#toc-validation-of-persistent-parameters] ---------------------------------------------------------------------------------- - -Les valeurs des [paramètres persistants |#persistent parameters] reçus des URL sont écrites dans les propriétés par la méthode `loadState()`. Elle vérifie également si le type de données spécifié dans la propriété correspond, sinon elle répondra par une erreur 404 et la page ne sera pas affichée. - -Ne faites jamais aveuglément confiance aux paramètres persistants, car ils peuvent facilement être remplacés par l'utilisateur dans l'URL. Par exemple, voici comment nous vérifions si `$this->lang` fait partie des langues prises en charge. Une bonne façon de le faire est de surcharger la méthode `loadState()` mentionnée ci-dessus : +Ne faites jamais aveuglément confiance aux paramètres, car ils peuvent facilement être remplacés par l'utilisateur dans l'URL. Par exemple, voici comment nous vérifions si `$this->lang` fait partie des langues prises en charge. Une bonne façon de le faire est de surcharger la méthode `loadState()` mentionnée ci-dessus : ```php class ProductPresenter extends Nette\Application\UI\Presenter @@ -341,7 +361,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter Sauvegarde et restauration de la demande .[#toc-save-and-restore-the-request] ----------------------------------------------------------------------------- -Vous pouvez enregistrer la demande en cours dans une session ou la restaurer à partir de la session et laisser le présentateur l'exécuter à nouveau. Ceci est utile, par exemple, lorsqu'un utilisateur remplit un formulaire et que sa connexion expire. Afin de ne pas perdre de données, avant de rediriger l'utilisateur vers la page de connexion, nous sauvegardons la demande actuelle dans la session à l'aide de `$reqId = $this->storeRequest()`, qui renvoie un identifiant sous la forme d'une chaîne courte et le transmet comme paramètre au présentateur de connexion. +La demande traitée par le présentateur est un objet [api:Nette\Application\Request] et est renvoyée par la méthode du présentateur `getRequest()`. + +Vous pouvez enregistrer la requête en cours dans une session ou la restaurer à partir de la session et laisser le présentateur l'exécuter à nouveau. Ceci est utile, par exemple, lorsqu'un utilisateur remplit un formulaire et que son login expire. Afin de ne pas perdre de données, avant de rediriger l'utilisateur vers la page de connexion, nous sauvegardons la demande en cours dans la session à l'aide de la méthode `$reqId = $this->storeRequest()`, qui renvoie un identifiant sous la forme d'une chaîne courte et le transmet en tant que paramètre au présentateur de connexion. Après l'ouverture de session, nous appelons la méthode `$this->restoreRequest($reqId)`, qui récupère la demande de la session et la lui transmet. La méthode vérifie que la requête a été créée par le même utilisateur que celui qui est maintenant connecté. Si un autre utilisateur se connecte ou si la clé n'est pas valide, elle ne fait rien et le programme continue. @@ -425,6 +447,27 @@ $this->sendResponse(new Responses\CallbackResponse($callback)); ``` +Vérification de la méthode HTTP .[#toc-http-method-check] +--------------------------------------------------------- + +Les présentateurs de Nette vérifient automatiquement la méthode HTTP de chaque requête entrante. La raison principale de cette vérification est la sécurité. La vérification de la méthode est effectuée dans `checkHttpMethod()`, qui détermine si la méthode spécifiée dans la demande est incluse dans le tableau `$presenter->allowedMethods`. Par défaut, ce tableau contient les éléments `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`, ce qui signifie que ces méthodes sont autorisées. + +Si vous souhaitez autoriser en plus la méthode `OPTIONS`, vous pouvez le faire de la manière suivante : + +```php +class MyPresenter extends Nette\Application\UI\Presenter +{ + protected function checkHttpMethod(): void + { + $this->allowedMethods[] = 'OPTIONS'; + parent::checkHttpMethod(); + } +} +``` + +Il est essentiel de souligner que si vous autorisez la méthode `OPTIONS`, vous devez également la gérer correctement dans votre présentateur. Cette méthode est souvent utilisée comme une requête dite "preflight", que les navigateurs envoient automatiquement avant la requête réelle lorsqu'il est nécessaire de déterminer si la requête est autorisée du point de vue de la politique CORS (Cross-Origin Resource Sharing). Si vous autorisez cette méthode mais ne mettez pas en œuvre une réponse appropriée, cela peut entraîner des incohérences et des problèmes de sécurité potentiels. + + Autres lectures .[#toc-further-reading] ======================================= diff --git a/application/hu/creating-links.texy b/application/hu/creating-links.texy index 8f7c11af58..cf2d0df2e8 100644 --- a/application/hu/creating-links.texy +++ b/application/hu/creating-links.texy @@ -38,7 +38,7 @@ Lehetőség van nevesített paraméterek átadására is. A következő hivatkoz detail ``` -Ha a `ProductPresenter::renderShow()` metódus szignatúrájában nem szerepel a `$lang`, akkor a paraméter értékét a `$lang = $this->getParameter('lang')` segítségével tudja beolvasni. +Ha a `ProductPresenter::renderShow()` metódus aláírásában nem szerepel a `$lang`, akkor a paraméter értékét a `$lang = $this->getParameter('lang')` segítségével vagy a [tulajdonságból |presenters#Request Parameters] tudja lekérdezni. Ha a paraméterek egy tömbben vannak tárolva, akkor a `...` operátorral (vagy a Latte 2.x-ben a `(expand)` operátorral) bővíthetők: diff --git a/application/hu/presenters.texy b/application/hu/presenters.texy index 3dadaaf424..64e5c2d8af 100644 --- a/application/hu/presenters.texy +++ b/application/hu/presenters.texy @@ -236,6 +236,32 @@ public function actionData(): void ``` +Kérési paraméterek .[#toc-request-parameters] +============================================= + +A bemutató, valamint minden komponens a HTTP-kérésből kapja a paramétereit. Értékeik a `getParameter($name)` módszerrel vagy a `getParameters()` segítségével kérhetők le. Az értékek karakterláncok vagy karakterláncok tömbjei, lényegében közvetlenül az URL-ből nyert nyers adatok. + +A további kényelem érdekében javasoljuk, hogy a paraméterek tulajdonságokon keresztül legyenek elérhetők. Egyszerűen jegyzeteljük őket a `#[Parameter]` attribútummal: + +```php +use Nette\Application\Attributes\Parameter; // ez a sor fontos + +class HomePresenter extends Nette\Application\UI\Presenter +{ + #[Parameter] + public string $theme; // nyilvánosnak kell lennie +} +``` + +A tulajdonságok esetében javasoljuk, hogy adja meg az adattípust (pl. `string`). A Nette ezután automatikusan ennek alapján alakítja ki az értéket. A paraméterek értékei is [érvényesíthetők |#Validation of Parameters]. + +A hivatkozás létrehozásakor közvetlenül megadhatja a paraméterek értékét: + +```latte +click +``` + + Tartós paraméterek .[#toc-persistent-parameters] ================================================ @@ -257,7 +283,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter Ha a `$this->lang` értéke például `'en'`, akkor a `link()` vagy `n:href` használatával létrehozott linkek a `lang=en` paramétert is tartalmazni fogják. És amikor a linkre kattintunk, akkor ismét a `$this->lang = 'en'` lesz. -A tulajdonságok esetében javasoljuk, hogy adja meg az adattípust (pl. `string`), és egy alapértelmezett értéket is megadhat. A paraméterek értékei [érvényesíthetők |#Validation of Persistent Parameters]. +A tulajdonságok esetében javasoljuk, hogy adja meg az adattípust (pl. `string`), és megadhatja az alapértelmezett értéket is. A paraméterek értékei [érvényesíthetők |#Validation of Parameters]. A perzisztens paraméterek alapértelmezés szerint egy adott bemutató összes művelete között átadásra kerülnek. Több prezenter között történő átadásukhoz vagy meg kell határozni őket: @@ -307,18 +333,12 @@ Mélyebbre ásva .[#toc-going-deeper] Amit eddig ebben a fejezetben bemutattunk, valószínűleg elegendő lesz. A következő sorok azoknak szólnak, akiket a prezenterek mélységében érdekelnek, és mindent tudni akarnak. -Követelmények és paraméterek .[#toc-requirement-and-parameters] ---------------------------------------------------------------- +A paraméterek validálása .[#toc-validation-of-parameters] +--------------------------------------------------------- -A bemutató által kezelt kérés a [api:Nette\Application\Request] objektum, amelyet a bemutató `getRequest()` metódusa ad vissza. Ez paraméterek tömbjét tartalmazza, és mindegyik paraméter vagy valamelyik komponenshez, vagy közvetlenül a prezentálóhoz tartozik (amely valójában szintén egy komponens, bár egy speciális komponens). A Nette tehát a `loadState(array $params)` metódus meghívásával újraosztja a paramétereket és átadja az egyes komponensek (és a prezenter) között. A paramétereket a `getParameters(): array` metódussal lehet megszerezni, egyenként a `getParameter($name)` segítségével. A paraméterek értékei karakterláncok vagy karakterláncok tömbjei, alapvetően közvetlenül az URL-ből nyert nyers adatok. +Az URL-ekből kapott [kérési paraméterek |#request parameters] és [állandó paraméterek |#persistent parameters] értékeit a `loadState()` módszer írja a tulajdonságokba. Azt is ellenőrzi, hogy a tulajdonságban megadott adattípus megfelel-e, ellenkező esetben 404-es hibával válaszol, és az oldal nem jelenik meg. - -A tartós paraméterek validálása .[#toc-validation-of-persistent-parameters] ---------------------------------------------------------------------------- - -Az URL-ekből kapott [állandó paraméterek |#persistent parameters] értékeit a `loadState()` módszer írja a tulajdonságokba. A módszer azt is ellenőrzi, hogy a tulajdonságban megadott adattípus megfelel-e, ellenkező esetben 404-es hibával válaszol, és az oldal nem jelenik meg. - -Soha ne bízzunk vakon a perzisztens paraméterekben, mivel azokat a felhasználó könnyen felülírhatja az URL-ben. Például így ellenőrizzük, hogy a `$this->lang` szerepel-e a támogatott nyelvek között. Jó megoldás erre a fent említett `loadState()` metódus felülírása: +Soha ne bízzon vakon a paraméterekben, mert azokat a felhasználó könnyen felülírhatja az URL-ben. Például így ellenőrizzük, hogy a `$this->lang` szerepel-e a támogatott nyelvek között. Ennek jó módja a fent említett `loadState()` metódus felülírása: ```php class ProductPresenter extends Nette\Application\UI\Presenter @@ -341,7 +361,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter A kérelem mentése és visszaállítása .[#toc-save-and-restore-the-request] ------------------------------------------------------------------------ -Az aktuális kérést elmentheti egy munkamenetbe, vagy visszaállíthatja a munkamenetből, és hagyhatja, hogy az előadó újra végrehajtsa azt. Ez például akkor hasznos, ha egy felhasználó kitölt egy űrlapot, és a bejelentkezése lejár. Annak érdekében, hogy ne veszítsünk el adatokat, a bejelentkezési oldalra való átirányítás előtt az aktuális kérést a munkamenetbe mentjük a `$reqId = $this->storeRequest()` segítségével, amely egy rövid karakterlánc formájában visszaad egy azonosítót, és paraméterként átadja a bejelentkezési prezenternek. +A kérés, amelyet a bemutató kezel, egy objektum [api:Nette\Application\Request] és a bemutató `getRequest()` metódusa adja vissza. + +Az aktuális kérést elmentheti egy munkamenetbe, vagy visszaállíthatja a munkamenetből, és hagyhatja, hogy a prezenter ismét futtassa. Ez például akkor hasznos, ha egy felhasználó kitölt egy űrlapot, és a bejelentkezése lejár. Annak érdekében, hogy ne veszítsünk el adatokat, a bejelentkezési oldalra való átirányítás előtt az aktuális kérést a munkamenetbe mentjük a `$reqId = $this->storeRequest()` segítségével, amely egy rövid karakterlánc formájában visszaad egy azonosítót, és paraméterként átadja a bejelentkezési prezenternek. A bejelentkezés után meghívjuk a `$this->restoreRequest($reqId)` metódust, amely átveszi a kérést a munkamenetből, és továbbítja azt. A módszer ellenőrzi, hogy a kérést ugyanaz a felhasználó hozta-e létre, mint aki most bejelentkezett. Ha egy másik felhasználó jelentkezik be, vagy a kulcs érvénytelen, akkor nem tesz semmit, és a program folytatódik. @@ -425,6 +447,27 @@ $this->sendResponse(new Responses\CallbackResponse($callback)); ``` +HTTP módszer ellenőrzése .[#toc-http-method-check] +-------------------------------------------------- + +A Nette bemutatói automatikusan ellenőrzik minden bejövő kérés HTTP-módszerét. Az ellenőrzés elsődleges oka a biztonság. A módszerellenőrzés a `checkHttpMethod()` oldalon történik, amely meghatározza, hogy a kérelemben megadott módszer szerepel-e a `$presenter->allowedMethods` tömbben. Alapértelmezés szerint ez a tömb a `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH` elemeket tartalmazza, vagyis ezek a módszerek engedélyezettek. + +Ha a `OPTIONS` metódust is engedélyezni kívánja, akkor ezt a következő módon érheti el: + +```php +class MyPresenter extends Nette\Application\UI\Presenter +{ + protected function checkHttpMethod(): void + { + $this->allowedMethods[] = 'OPTIONS'; + parent::checkHttpMethod(); + } +} +``` + +Fontos hangsúlyozni, hogy ha engedélyezi a `OPTIONS` módszert, akkor azt megfelelően kell kezelnie a prezenteren belül is. Ezt a módszert gyakran használják úgynevezett preflight-kérelemként, amelyet a böngészők automatikusan elküldenek a tényleges kérés előtt, amikor meg kell határozni, hogy a kérés engedélyezett-e a CORS (Cross-Origin Resource Sharing) irányelv szempontjából. Ha engedélyezi ezt a módszert, de nem valósít meg megfelelő választ, az következetlenségekhez és potenciális biztonsági problémákhoz vezethet. + + További olvasmányok .[#toc-further-reading] =========================================== diff --git a/application/it/creating-links.texy b/application/it/creating-links.texy index 7b8cafdf00..de4a530016 100644 --- a/application/it/creating-links.texy +++ b/application/it/creating-links.texy @@ -38,7 +38,7 @@ Cliccare su un link è, in parole povere, come chiamare un metodo `ProductPresen detail ``` -Se il metodo `ProductPresenter::renderShow()` non ha `$lang` nella sua firma, può leggere il valore del parametro usando `$lang = $this->getParameter('lang')`. +Se il metodo `ProductPresenter::renderShow()` non ha `$lang` nella sua firma, può recuperare il valore del parametro usando `$lang = $this->getParameter('lang')` o dalla [proprietà |presenters#Request Parameters]. Se i parametri sono memorizzati in un array, possono essere espansi con l'operatore `...` (o `(expand)` in Latte 2.x): diff --git a/application/it/presenters.texy b/application/it/presenters.texy index 687f5d900c..f9e9fb9473 100644 --- a/application/it/presenters.texy +++ b/application/it/presenters.texy @@ -236,6 +236,32 @@ public function actionData(): void ``` +Parametri di richiesta .[#toc-request-parameters] +================================================= + +Il presentatore, così come ogni componente, ottiene i suoi parametri dalla richiesta HTTP. I loro valori possono essere recuperati con il metodo `getParameter($name)` o `getParameters()`. I valori sono stringhe o array di stringhe, essenzialmente dati grezzi ottenuti direttamente dall'URL. + +Per maggiore comodità, si consiglia di rendere i parametri accessibili tramite proprietà. È sufficiente annotarli con l'attributo `#[Parameter]` attributo: + +```php +use Nette\Application\Attributes\Parameter; // questa linea è importante + +class HomePresenter extends Nette\Application\UI\Presenter +{ + #[Parameter] + public string $theme; // deve essere pubblica +} +``` + +Per le proprietà, si consiglia di specificare il tipo di dati (ad esempio, `string`). Nette calcolerà automaticamente il valore in base ad esso. Anche i valori dei parametri possono essere [convalidati |#Validation of Parameters]. + +Quando si crea un collegamento, è possibile impostare direttamente il valore dei parametri: + +```latte +click +``` + + Parametri persistenti .[#toc-persistent-parameters] =================================================== @@ -257,7 +283,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter Se `$this->lang` ha un valore come `'en'`, i link creati con `link()` o `n:href` conterranno anche il parametro `lang=en`. E quando il link viene cliccato, sarà di nuovo `$this->lang = 'en'`. -Per le proprietà, si consiglia di includere il tipo di dati (ad esempio, `string`) e si può anche includere un valore predefinito. I valori dei parametri possono essere [convalidati |#Validation of Persistent Parameters]. +Per le proprietà, si consiglia di includere il tipo di dati (ad esempio, `string`) e si può anche includere un valore predefinito. I valori dei parametri possono essere [convalidati |#Validation of Parameters]. I parametri persistenti vengono passati per impostazione predefinita tra tutte le azioni di un determinato presentatore. Per passarli tra più presentatori, è necessario definirli: @@ -307,18 +333,12 @@ Approfondimento .[#toc-going-deeper] Quanto mostrato finora in questo capitolo sarà probabilmente sufficiente. Le righe che seguono sono destinate a chi è interessato ad approfondire i presentatori e vuole sapere tutto. -Requisiti e parametri .[#toc-requirement-and-parameters] +Convalida dei parametri .[#toc-validation-of-parameters] -------------------------------------------------------- -La richiesta gestita dal presentatore è l'oggetto [api:Nette\Application\Request] e viene restituita dal metodo del presentatore `getRequest()`. Include un array di parametri e ognuno di essi appartiene o a qualche componente o direttamente al presentatore (che in realtà è anch'esso un componente, anche se speciale). Quindi Nette ridistribuisce i parametri e passa tra i singoli componenti (e il presentatore) chiamando il metodo `loadState(array $params)`. I parametri possono essere ottenuti con il metodo `getParameters(): array`, singolarmente con `getParameter($name)`. I valori dei parametri sono stringhe o array di stringhe, in pratica dati grezzi ottenuti direttamente da un URL. +I valori dei [parametri della richiesta |#request parameters] e dei [parametri persistenti |#persistent parameters] ricevuti dagli URL vengono scritti nelle proprietà dal metodo `loadState()`. Il metodo controlla anche se il tipo di dati specificato nella proprietà corrisponde, altrimenti risponde con un errore 404 e la pagina non viene visualizzata. - -Convalida dei parametri persistenti .[#toc-validation-of-persistent-parameters] -------------------------------------------------------------------------------- - -I valori dei [parametri persistenti |#persistent parameters] ricevuti dagli URL vengono scritti nelle proprietà dal metodo `loadState()`. Il metodo controlla anche se il tipo di dati specificato nella proprietà corrisponde, altrimenti risponde con un errore 404 e la pagina non viene visualizzata. - -Non fidarsi mai ciecamente dei parametri persistenti, perché possono essere facilmente sovrascritti dall'utente nell'URL. Ad esempio, è così che si controlla se `$this->lang` è tra le lingue supportate. Un buon modo per farlo è sovrascrivere il metodo `loadState()` citato in precedenza: +Non fidarsi mai ciecamente dei parametri, perché possono essere facilmente sovrascritti dall'utente nell'URL. Ad esempio, è così che controlliamo se `$this->lang` è tra le lingue supportate. Un buon modo per farlo è sovrascrivere il metodo `loadState()` citato in precedenza: ```php class ProductPresenter extends Nette\Application\UI\Presenter @@ -341,7 +361,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter Salvare e ripristinare la richiesta .[#toc-save-and-restore-the-request] ------------------------------------------------------------------------ -È possibile salvare la richiesta corrente in una sessione o ripristinarla dalla sessione e lasciare che il presentatore la esegua di nuovo. Ciò è utile, ad esempio, quando un utente compila un modulo e il suo login scade. Per non perdere i dati, prima di reindirizzare alla pagina di accesso, salviamo la richiesta corrente nella sessione usando `$reqId = $this->storeRequest()`, che restituisce un identificatore sotto forma di stringa breve e lo passa come parametro al presentatore dell'accesso. +La richiesta che il presentatore gestisce è un oggetto [api:Nette\Application\Request] e viene restituita dal metodo del presentatore `getRequest()`. + +È possibile salvare la richiesta corrente in una sessione o ripristinarla dalla sessione e lasciare che il presentatore la esegua di nuovo. Ciò è utile, ad esempio, quando un utente compila un modulo e il suo login scade. Per non perdere i dati, prima di reindirizzare alla pagina di accesso, salviamo la richiesta corrente nella sessione con il metodo `$reqId = $this->storeRequest()`, che restituisce un identificatore sotto forma di stringa breve e lo passa come parametro al presentatore di accesso. Dopo l'accesso, chiamiamo il metodo `$this->restoreRequest($reqId)`, che preleva la richiesta dalla sessione e la inoltra ad essa. Il metodo verifica che la richiesta sia stata creata dallo stesso utente che ha effettuato l'accesso. Se un altro utente accede o la chiave non è valida, non fa nulla e il programma continua. @@ -425,6 +447,27 @@ $this->sendResponse(new Responses\CallbackResponse($callback)); ``` +Controllo del metodo HTTP .[#toc-http-method-check] +--------------------------------------------------- + +I presentatori di Nette verificano automaticamente il metodo HTTP di ogni richiesta in arrivo. Il motivo principale di questa verifica è la sicurezza. La verifica del metodo viene eseguita in `checkHttpMethod()`, che determina se il metodo specificato nella richiesta è incluso nell'array `$presenter->allowedMethods`. Per impostazione predefinita, questo array contiene gli elementi `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`, il che significa che questi metodi sono consentiti. + +Se si desidera consentire anche il metodo `OPTIONS`, è possibile farlo nel modo seguente: + +```php +class MyPresenter extends Nette\Application\UI\Presenter +{ + protected function checkHttpMethod(): void + { + $this->allowedMethods[] = 'OPTIONS'; + parent::checkHttpMethod(); + } +} +``` + +È fondamentale sottolineare che se si abilita il metodo `OPTIONS`, è necessario gestirlo correttamente anche nel presenter. Questo metodo è spesso usato come una cosiddetta richiesta di preflight, che i browser inviano automaticamente prima della richiesta vera e propria quando è necessario determinare se la richiesta è consentita dal punto di vista della politica CORS (Cross-Origin Resource Sharing). Se si consente questo metodo ma non si implementa una risposta appropriata, si possono creare incongruenze e potenziali problemi di sicurezza. + + Ulteriori letture .[#toc-further-reading] ========================================= diff --git a/application/pl/creating-links.texy b/application/pl/creating-links.texy index 5c9126dba0..24a2152b62 100644 --- a/application/pl/creating-links.texy +++ b/application/pl/creating-links.texy @@ -38,7 +38,7 @@ Możliwe jest również przekazywanie nazwanych parametrów. Poniższy link prze detail produktu ``` -Jeśli metoda `ProductPresenter::renderShow()` nie ma `$lang` w swojej sygnaturze, może pobrać wartość parametru za pomocą `$lang = $this->getParameter('lang')`. +Jeśli metoda `ProductPresenter::renderShow()` nie ma w swojej sygnaturze `$lang`, może pobrać wartość parametru za pomocą `$lang = $this->getParameter('lang')` lub z [właściwości |presenters#Request Parameters]. Jeśli parametry są przechowywane w tablicy, można je rozwinąć za pomocą operatora `...` (w Latte 2.x operator `(expand)`): diff --git a/application/pl/presenters.texy b/application/pl/presenters.texy index b6a00e6d74..a95c9e7755 100644 --- a/application/pl/presenters.texy +++ b/application/pl/presenters.texy @@ -236,6 +236,32 @@ public function actionData(): void ``` +Parametry żądania .[#toc-request-parameters] +============================================ + +Prezenter, jak również każdy komponent, uzyskuje swoje parametry z żądania HTTP. Ich wartości można pobrać za pomocą metody `getParameter($name)` lub `getParameters()`. Wartości są ciągami lub tablicami ciągów, zasadniczo surowymi danymi uzyskanymi bezpośrednio z adresu URL. + +Dla większej wygody zalecamy udostępnianie parametrów za pośrednictwem właściwości. Wystarczy opatrzyć je adnotacją `#[Parameter]` atrybut: + +```php +use Nette\Application\Attributes\Parameter; // Ta linia jest ważna + +class HomePresenter extends Nette\Application\UI\Presenter +{ + #[Parameter] + public string $theme; // musi być publiczny +} +``` + +W przypadku właściwości sugerujemy określenie typu danych (np. `string`). Nette automatycznie rzuci wartość na jej podstawie. Wartości parametrów mogą być również [walidowane |#Validation of Parameters]. + +Podczas tworzenia linku można bezpośrednio ustawić wartość parametrów: + +```latte +click +``` + + Trwałe parametry .[#toc-persistent-parameters] ============================================== @@ -257,7 +283,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter Jeśli `$this->lang` ma wartość taką jak `'en'`, to linki utworzone przy użyciu `link()` lub `n:href` będą zawierały również parametr `lang=en`. A gdy link zostanie kliknięty, ponownie będzie to `$this->lang = 'en'`. -Dla właściwości zalecamy dołączenie typu danych (np. `string`) i można również dołączyć wartość domyślną. Wartości parametrów mogą być [walidowane |#Validation of Persistent Parameters]. +W przypadku właściwości zalecamy podanie typu danych (np. `string`), a także wartości domyślnej. Wartości parametrów mogą być [walidowane |#Validation of Parameters]. Trwałe parametry są domyślnie przekazywane pomiędzy wszystkimi akcjami danego prezentera. Aby przekazać je pomiędzy wieloma prezenterami, musisz je zdefiniować: @@ -307,18 +333,12 @@ Sięgając głębiej .[#toc-going-deeper] Z tym, co do tej pory omówiliśmy w tym rozdziale, jesteś prawdopodobnie całkowicie zadowolony. Kolejne wiersze są dla tych, którzy interesują się prezenterami dogłębnie i chcą wiedzieć wszystko. -Wymagania i parametry .[#toc-requirement-and-parameters] --------------------------------------------------------- +Walidacja parametrów .[#toc-validation-of-parameters] +----------------------------------------------------- -Żądanie obsługiwane przez prezentera ma postać obiektu [api:Nette\Application\Request] i jest zwracane przez metodę prezentera `getRequest()`. Zawiera ona tablicę parametrów, a każdy z nich należy albo do któregoś z komponentów, albo bezpośrednio do prezentera (który w rzeczywistości też jest komponentem, choć specjalnym). Nette dokonuje więc redystrybucji parametrów i przechodzi między poszczególnymi komponentami (i prezenterem), wywołując metodę `loadState(array $params)`. Parametry można uzyskać za pomocą metody `getParameters(): array`, indywidualnie za pomocą `getParameter($name)`. Wartości parametrów są ciągami lub tablicami ciągów, są to w zasadzie surowe dane uzyskane bezpośrednio z adresu URL. +Wartości [parametrów żądania |#request parameters] i [parametrów stałych |#persistent parameters] otrzymanych z adresów URL są zapisywane we właściwościach przez metodę `loadState()`. Sprawdza również, czy typ danych określony we właściwości jest zgodny, w przeciwnym razie odpowie błędem 404, a strona nie zostanie wyświetlona. - -Walidacja trwałych parametrów .[#toc-validation-of-persistent-parameters] -------------------------------------------------------------------------- - -Wartości [trwałych parametrów |#persistent parameters] otrzymanych z adresów URL są zapisywane do właściwości przez metodę `loadState()`. Sprawdza ona również, czy typ danych określony we właściwości pasuje, w przeciwnym razie odpowie błędem 404 i strona nie zostanie wyświetlona. - -Nigdy ślepo nie ufaj trwałym parametrom, ponieważ mogą one zostać łatwo nadpisane przez użytkownika w adresie URL. Na przykład w ten sposób sprawdzamy, czy `$this->lang` jest wśród obsługiwanych języków. Dobrym sposobem na to jest nadpisanie metody `loadState()` wspomnianej powyżej: +Nigdy nie należy ślepo ufać parametrom, ponieważ mogą one zostać łatwo nadpisane przez użytkownika w adresie URL. Na przykład w ten sposób sprawdzamy, czy `$this->lang` należy do obsługiwanych języków. Dobrym sposobem na to jest nadpisanie metody `loadState()` wspomnianej powyżej: ```php class ProductPresenter extends Nette\Application\UI\Presenter @@ -341,7 +361,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter Zapisywanie i przywracanie wniosku .[#toc-save-and-restore-the-request] ----------------------------------------------------------------------- -Bieżące żądanie można zapisać do sesji lub przywrócić z niej i pozwolić prezenterowi wykonać je ponownie. Jest to przydatne, na przykład, gdy użytkownik wypełnia formularz i jego login wygasa. Aby uniknąć utraty danych, przed przekierowaniem na stronę logowania zapisujemy bieżące żądanie do sesji za pomocą `$reqId = $this->storeRequest()`, która zwraca jej identyfikator jako krótki łańcuch i przekazuje go jako parametr do prezentera logowania. +Żądanie obsługiwane przez prezentera jest obiektem [api:Nette\Application\Request] i jest zwracane przez metodę prezentera `getRequest()`. + +Możesz zapisać bieżące żądanie w sesji lub przywrócić je z sesji i pozwolić prezenterowi wykonać je ponownie. Jest to przydatne na przykład, gdy użytkownik wypełnia formularz, a jego login wygasa. Aby nie utracić danych, przed przekierowaniem na stronę logowania zapisujemy bieżące żądanie do sesji za pomocą `$reqId = $this->storeRequest()`, która zwraca identyfikator w postaci krótkiego ciągu znaków i przekazuje go jako parametr do prezentera logowania. Po zalogowaniu się wywołujemy metodę `$this->restoreRequest($reqId)`, która pobiera żądanie z sesji i przekazuje je dalej. Ta metoda sprawdza, czy żądanie zostało utworzone przez tego samego użytkownika, który jest teraz zalogowany. Jeśli zalogował się inny użytkownik lub klucz był nieważny, nie robi nic i program kontynuuje. @@ -425,6 +447,27 @@ $this->sendResponse(new Responses\CallbackResponse($callback)); ``` +Sprawdzanie metod HTTP .[#toc-http-method-check] +------------------------------------------------ + +Prezenterzy w Nette automatycznie weryfikują metodę HTTP każdego przychodzącego żądania. Głównym powodem tej weryfikacji jest bezpieczeństwo. Weryfikacja metody jest przeprowadzana w `checkHttpMethod()`, który określa, czy metoda określona w żądaniu znajduje się w tablicy `$presenter->allowedMethods`. Domyślnie tablica ta zawiera elementy `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`, co oznacza, że metody te są dozwolone. + +Jeśli chcesz dodatkowo zezwolić na metodę `OPTIONS`, można to osiągnąć w następujący sposób: + +```php +class MyPresenter extends Nette\Application\UI\Presenter +{ + protected function checkHttpMethod(): void + { + $this->allowedMethods[] = 'OPTIONS'; + parent::checkHttpMethod(); + } +} +``` + +Ważne jest, aby podkreślić, że jeśli włączysz metodę `OPTIONS`, musisz również poprawnie obsługiwać ją w swoim prezenterze. Metoda ta jest często używana jako tak zwane żądanie wstępne, które przeglądarki automatycznie wysyłają przed faktycznym żądaniem, gdy konieczne jest ustalenie, czy żądanie jest dozwolone z punktu widzenia polityki CORS (Cross-Origin Resource Sharing). Jeśli zezwolisz na tę metodę, ale nie zaimplementujesz odpowiedniej odpowiedzi, może to prowadzić do niespójności i potencjalnych problemów z bezpieczeństwem. + + Dalsza lektura .[#toc-further-reading] ====================================== diff --git a/application/pt/creating-links.texy b/application/pt/creating-links.texy index b58d739ab1..4ecadd7bda 100644 --- a/application/pt/creating-links.texy +++ b/application/pt/creating-links.texy @@ -38,7 +38,7 @@ Também é possível passar parâmetros nomeados. O seguinte link passa o parâm detail ``` -Se o método `ProductPresenter::renderShow()` não tiver `$lang` em sua assinatura, ele pode ler o valor do parâmetro usando `$lang = $this->getParameter('lang')`. +Se o método `ProductPresenter::renderShow()` não tiver `$lang` em sua assinatura, ele poderá recuperar o valor do parâmetro usando `$lang = $this->getParameter('lang')` ou a partir da [propriedade |presenters#Request Parameters]. Se os parâmetros estiverem armazenados em uma matriz, eles podem ser expandidos com o operador `...` (ou `(expand)` operador em Latte 2.x): diff --git a/application/pt/presenters.texy b/application/pt/presenters.texy index 58522bfda0..f0d78415f6 100644 --- a/application/pt/presenters.texy +++ b/application/pt/presenters.texy @@ -236,6 +236,32 @@ public function actionData(): void ``` +Parâmetros de solicitação .[#toc-request-parameters] +==================================================== + +O apresentador, assim como todos os componentes, obtém seus parâmetros da solicitação HTTP. Seus valores podem ser recuperados usando o método `getParameter($name)` ou `getParameters()`. Os valores são cadeias de caracteres ou matrizes de cadeias de caracteres, essencialmente dados brutos obtidos diretamente do URL. + +Para maior comodidade, recomendamos tornar os parâmetros acessíveis por meio de propriedades. Basta anotá-los com o atributo `#[Parameter]` atributo: + +```php +use Nette\Application\Attributes\Parameter; // essa linha é importante + +class HomePresenter extends Nette\Application\UI\Presenter +{ + #[Parameter] + public string $theme; // deve ser pública +} +``` + +Para propriedades, sugerimos especificar o tipo de dados (por exemplo, `string`). O Nette converterá automaticamente o valor com base nele. Os valores dos parâmetros também podem ser [validados |#Validation of Parameters]. + +Ao criar um link, você pode definir diretamente o valor dos parâmetros: + +```latte +click +``` + + Parâmetros Persistentes .[#toc-persistent-parameters] ===================================================== @@ -257,7 +283,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter Se `$this->lang` tem um valor como `'en'`, então os links criados usando `link()` ou `n:href` também conterão o parâmetro `lang=en`. E quando o link for clicado, ele será novamente `$this->lang = 'en'`. -Para propriedades, recomendamos que você inclua o tipo de dados (por exemplo, `string`) e você também pode incluir um valor padrão. Os valores dos parâmetros podem ser [validados |#Validation of Persistent Parameters]. +Para propriedades, recomendamos que você inclua o tipo de dados (por exemplo, `string`) e também pode incluir um valor padrão. Os valores dos parâmetros podem ser [validados |#Validation of Parameters]. Parâmetros persistentes são passados por padrão entre todas as ações de um determinado apresentador. Para passá-los entre vários apresentadores, você precisa defini-los também: @@ -307,18 +333,12 @@ Indo mais fundo .[#toc-going-deeper] O que mostramos até agora neste capítulo provavelmente será suficiente. As seguintes linhas destinam-se àqueles que estão interessados em apresentadores em profundidade e querem saber tudo. -Requisitos e parâmetros .[#toc-requirement-and-parameters] ----------------------------------------------------------- +Validação de parâmetros .[#toc-validation-of-parameters] +-------------------------------------------------------- -O pedido tratado pelo apresentador é o objeto [api:Nette\Application\Request] e é devolvido pelo método do apresentador `getRequest()`. Ele inclui um conjunto de parâmetros e cada um deles pertence a alguns dos componentes ou diretamente ao apresentador (que na verdade é também um componente, embora especial). Assim, Nette redistribui os parâmetros e passa entre os componentes individuais (e o apresentador), chamando o método `loadState(array $params)`. Os parâmetros podem ser obtidos pelo método `getParameters(): array`, individualmente usando `getParameter($name)`. Os valores dos parâmetros são strings ou matrizes de strings, são basicamente dados brutos obtidos diretamente de uma URL. +Os valores dos [parâmetros de solicitação |#request parameters] e dos [parâmetros persistentes |#persistent parameters] recebidos dos URLs são gravados nas propriedades pelo método `loadState()`. Ele também verifica se o tipo de dados especificado na propriedade corresponde; caso contrário, ele responderá com um erro 404 e a página não será exibida. - -Validação de Parâmetros Persistentes .[#toc-validation-of-persistent-parameters] --------------------------------------------------------------------------------- - -Os valores de [parâmetros persistentes |#persistent parameters] recebidos de URLs são escritos nas propriedades pelo método `loadState()`. Ele também verifica se o tipo de dados especificado na propriedade corresponde, caso contrário, responderá com um erro 404 e a página não será exibida. - -Nunca confie cegamente em parâmetros persistentes, pois eles podem ser facilmente sobrescritos pelo usuário no URL. Por exemplo, é assim que verificamos se `$this->lang` está entre os idiomas suportados. Uma boa maneira de fazer isso é sobrescrever o método `loadState()` mencionado acima: +Nunca confie cegamente nos parâmetros, pois eles podem ser facilmente substituídos pelo usuário no URL. Por exemplo, é assim que verificamos se `$this->lang` está entre os idiomas suportados. Uma boa maneira de fazer isso é substituir o método `loadState()` mencionado acima: ```php class ProductPresenter extends Nette\Application\UI\Presenter @@ -341,7 +361,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter Salvar e Restaurar o Pedido .[#toc-save-and-restore-the-request] ---------------------------------------------------------------- -Você pode salvar o pedido atual para uma sessão ou restaurá-lo da sessão e deixar o apresentador executá-lo novamente. Isto é útil, por exemplo, quando um usuário preenche um formulário e seu login expira. Para não perder dados, antes de redirecionar para a página de login, salvamos a solicitação atual para a sessão usando `$reqId = $this->storeRequest()`, que retorna um identificador na forma de uma seqüência curta e o passa como parâmetro para o apresentador de login. +A solicitação que o apresentador trata é um objeto [api:Nette\Application\Request] e é retornada pelo método do apresentador `getRequest()`. + +Você pode salvar a solicitação atual em uma sessão ou restaurá-la da sessão e permitir que o apresentador a execute novamente. Isso é útil, por exemplo, quando um usuário preenche um formulário e seu login expira. Para não perder dados, antes de redirecionar para a página de login, salvamos a solicitação atual na sessão usando `$reqId = $this->storeRequest()`, que retorna um identificador na forma de uma cadeia de caracteres curta e o passa como parâmetro para o apresentador de login. Após o login, chamamos o método `$this->restoreRequest($reqId)`, que capta o pedido da sessão e o encaminha para ele. O método verifica que a solicitação foi criada pelo mesmo usuário que está agora logado. Se outro usuário faz o login ou a chave é inválida, ele não faz nada e o programa continua. @@ -425,6 +447,27 @@ $this->sendResponse(new Responses\CallbackResponse($callback)); ``` +Verificação do método HTTP .[#toc-http-method-check] +---------------------------------------------------- + +Os apresentadores do Nette verificam automaticamente o método HTTP de cada solicitação recebida. O principal motivo para essa verificação é a segurança. A verificação do método é realizada em `checkHttpMethod()`, que determina se o método especificado na solicitação está incluído na matriz `$presenter->allowedMethods`. Por padrão, essa matriz contém os itens `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`, o que significa que esses métodos são permitidos. + +Se você quiser permitir adicionalmente o método `OPTIONS`, isso pode ser feito da seguinte maneira: + +```php +class MyPresenter extends Nette\Application\UI\Presenter +{ + protected function checkHttpMethod(): void + { + $this->allowedMethods[] = 'OPTIONS'; + parent::checkHttpMethod(); + } +} +``` + +É fundamental enfatizar que, se você habilitar o método `OPTIONS`, também deverá tratá-lo adequadamente em seu apresentador. Esse método é frequentemente usado como a chamada solicitação de preflight, que os navegadores enviam automaticamente antes da solicitação real quando é necessário determinar se a solicitação é permitida do ponto de vista da política de CORS (Cross-Origin Resource Sharing). Se você permitir esse método, mas não implementar uma resposta adequada, isso poderá gerar inconsistências e possíveis problemas de segurança. + + Leitura adicional .[#toc-further-reading] ========================================= diff --git a/application/ro/creating-links.texy b/application/ro/creating-links.texy index 659cc88a08..a26a28b861 100644 --- a/application/ro/creating-links.texy +++ b/application/ro/creating-links.texy @@ -38,7 +38,7 @@ De asemenea, este posibil să se treacă parametri numiți. Următoarea legătur detail ``` -În cazul în care metoda `ProductPresenter::renderShow()` nu are `$lang` în semnătura sa, aceasta poate citi valoarea parametrului folosind `$lang = $this->getParameter('lang')`. +În cazul în care metoda `ProductPresenter::renderShow()` nu are `$lang` în semnătura sa, aceasta poate prelua valoarea parametrului folosind `$lang = $this->getParameter('lang')` sau din [proprietate |presenters#Request Parameters]. În cazul în care parametrii sunt stocați într-o matrice, aceștia pot fi dezvoltați cu operatorul `...` (sau cu operatorul `(expand)` în Latte 2.x): diff --git a/application/ro/presenters.texy b/application/ro/presenters.texy index c4e64bfad0..b8c7099587 100644 --- a/application/ro/presenters.texy +++ b/application/ro/presenters.texy @@ -236,6 +236,32 @@ public function actionData(): void ``` +Parametrii cererii .[#toc-request-parameters] +============================================= + +Prezentatorul, ca și fiecare componentă, își obține parametrii din cererea HTTP. Valorile acestora pot fi recuperate cu ajutorul metodei `getParameter($name)` sau `getParameters()`. Valorile sunt șiruri de caractere sau rețele de șiruri de caractere, în esență date brute obținute direct din URL. + +Pentru mai multă comoditate, recomandăm ca parametrii să fie accesibili prin intermediul proprietăților. Este suficient să îi adnotați cu ajutorul caracterului `#[Parameter]` atribut: + +```php +use Nette\Application\Attributes\Parameter; // această linie este importantă + +class HomePresenter extends Nette\Application\UI\Presenter +{ + #[Parameter] + public string $theme; // trebuie să fie publică +} +``` + +Pentru proprietăți, sugerăm să se precizeze tipul de date (de exemplu, `string`). Apoi, Nette va transforma automat valoarea pe baza acestuia. Valorile parametrilor pot fi, de asemenea, [validate |#Validation of Parameters]. + +Atunci când creați o legătură, puteți seta direct valoarea parametrilor: + +```latte +click +``` + + Parametrii persistenți .[#toc-persistent-parameters] ==================================================== @@ -257,7 +283,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter Dacă `$this->lang` are o valoare, cum ar fi `'en'`, atunci legăturile create folosind `link()` sau `n:href` vor conține și parametrul `lang=en`. Iar atunci când se face clic pe link, acesta va fi din nou `$this->lang = 'en'`. -Pentru proprietăți, vă recomandăm să includeți tipul de date (de exemplu, `string`) și puteți include și o valoare implicită. Valorile parametrilor pot fi [validate |#Validation of Persistent Parameters]. +Pentru proprietăți, vă recomandăm să includeți tipul de date (de exemplu, `string`) și puteți include și o valoare implicită. Valorile parametrilor pot fi [validate |#Validation of Parameters]. Parametrii persistenți sunt trecuți în mod implicit între toate acțiunile unui anumit prezentator. Pentru a-i transmite între mai mulți prezentatori, trebuie să îi definiți fie: @@ -307,18 +333,12 @@ Aprofundare .[#toc-going-deeper] Ceea ce am arătat până acum în acest capitol va fi probabil suficient. Rândurile următoare sunt destinate celor care sunt interesați de prezentatori în profunzime și doresc să știe totul. -Cerință și parametri .[#toc-requirement-and-parameters] +Validarea parametrilor .[#toc-validation-of-parameters] ------------------------------------------------------- -Cererea gestionată de prezentator este obiectul [api:Nette\Application\Request] și este returnată de metoda prezentatorului `getRequest()`. Acesta include o matrice de parametri și fiecare dintre ei aparține fie unora dintre componente, fie direct prezentatorului (care este de fapt tot o componentă, deși una specială). Astfel, Nette redistribuie parametrii și pasează între componentele individuale (și prezentator) prin apelarea metodei `loadState(array $params)`. Parametrii pot fi obținuți prin metoda `getParameters(): array`, folosind individual `getParameter($name)`. Valorile parametrilor sunt șiruri de caractere sau array-uri de șiruri de caractere, acestea fiind practic date brute obținute direct de la un URL. +Valorile [parametrilor de cerere |#request parameters] și ale [parametrilor persistenți |#persistent parameters] primiți de la URL-uri sunt scrise în proprietăți prin metoda `loadState()`. Aceasta verifică, de asemenea, dacă tipul de date specificat în proprietate corespunde, în caz contrar se va răspunde cu o eroare 404 și pagina nu va fi afișată. - -Validarea parametrilor persistenți .[#toc-validation-of-persistent-parameters] ------------------------------------------------------------------------------- - -Valorile [parametrilor persistenți |#persistent parameters] primite de la URL-uri sunt scrise în proprietăți prin metoda `loadState()`. Aceasta verifică, de asemenea, dacă tipul de date specificat în proprietate se potrivește, în caz contrar se va răspunde cu o eroare 404 și pagina nu va fi afișată. - -Nu vă încredeți niciodată orbește în parametrii persistenți, deoarece aceștia pot fi ușor suprascriși de către utilizator în URL. De exemplu, iată cum verificăm dacă `$this->lang` se află printre limbile acceptate. O modalitate bună de a face acest lucru este să suprascrieți metoda `loadState()` menționată mai sus: +Nu vă încredeți niciodată orbește în parametri, deoarece aceștia pot fi ușor suprascriși de către utilizator în URL. De exemplu, iată cum verificăm dacă `$this->lang` se află printre limbile acceptate. O modalitate bună de a face acest lucru este să suprascrieți metoda `loadState()` menționată mai sus: ```php class ProductPresenter extends Nette\Application\UI\Presenter @@ -341,7 +361,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter Salvarea și restaurarea cererii .[#toc-save-and-restore-the-request] -------------------------------------------------------------------- -Puteți salva cererea curentă într-o sesiune sau o puteți restaura din sesiune și permite prezentatorului să o execute din nou. Acest lucru este util, de exemplu, atunci când un utilizator completează un formular și login-ul său expiră. Pentru a nu pierde date, înainte de redirecționarea către pagina de autentificare, salvăm cererea curentă în sesiune folosind `$reqId = $this->storeRequest()`, care returnează un identificator sub forma unui șir scurt și îl transmite ca parametru către prezentatorul de autentificare. +Cererea pe care o gestionează prezentatorul este un obiect [api:Nette\Application\Request] și este returnată de metoda prezentatorului `getRequest()`. + +Puteți salva cererea curentă într-o sesiune sau o puteți restaura din sesiune și permite prezentatorului să o execute din nou. Acest lucru este util, de exemplu, atunci când un utilizator completează un formular și login-ul său expiră. Pentru a nu pierde date, înainte de redirecționarea către pagina de conectare, salvăm cererea curentă în sesiune cu ajutorul aplicației `$reqId = $this->storeRequest()`, care returnează un identificator sub forma unui șir scurt și îl transmite ca parametru către prezentatorul de conectare. După conectare, apelăm metoda `$this->restoreRequest($reqId)`, care preia cererea din sesiune și o transmite acesteia. Metoda verifică dacă cererea a fost creată de același utilizator ca și cel care s-a logat acum este. Dacă un alt utilizator se conectează sau dacă cheia nu este validă, nu face nimic și programul continuă. @@ -425,6 +447,27 @@ $this->sendResponse(new Responses\CallbackResponse($callback)); ``` +Verificarea metodei HTTP .[#toc-http-method-check] +-------------------------------------------------- + +Prezentatorii din Nette verifică automat metoda HTTP a fiecărei cereri primite. Motivul principal al acestei verificări este securitatea. Verificarea metodei se efectuează în `checkHttpMethod()`, care determină dacă metoda specificată în cerere este inclusă în matricea `$presenter->allowedMethods`. În mod implicit, această matrice conține elementele `GET`, `POST`, `HEAD`, , `PUT`, `DELETE`, `PATCH`, ceea ce înseamnă că aceste metode sunt permise. + +Dacă doriți să permiteți în plus metoda `OPTIONS`, acest lucru poate fi realizat în felul următor: + +```php +class MyPresenter extends Nette\Application\UI\Presenter +{ + protected function checkHttpMethod(): void + { + $this->allowedMethods[] = 'OPTIONS'; + parent::checkHttpMethod(); + } +} +``` + +Este esențial să subliniem faptul că, dacă activați metoda `OPTIONS`, trebuie să o gestionați în mod corespunzător și în prezentator. Această metodă este adesea utilizată ca o așa-numită cerere de preflight, pe care browserele o trimit automat înainte de cererea efectivă atunci când este necesar să se determine dacă cererea este permisă din punctul de vedere al politicii CORS (Cross-Origin Resource Sharing). Dacă permiteți această metodă, dar nu implementați un răspuns adecvat, aceasta poate duce la inconsecvențe și la potențiale probleme de securitate. + + Lecturi suplimentare .[#toc-further-reading] ============================================ diff --git a/application/ru/creating-links.texy b/application/ru/creating-links.texy index 3a4dbb4805..debaf56da0 100644 --- a/application/ru/creating-links.texy +++ b/application/ru/creating-links.texy @@ -38,7 +38,7 @@ подробнее ``` -Если метод `ProductPresenter::renderShow()` не имеет `$lang` в своей сигнатуре, он может прочитать значение параметра, используя `$lang = $this->getParameter('lang')`. +Если метод `ProductPresenter::renderShow()` не имеет в своей сигнатуре `$lang`, то он может получить значение параметра с помощью `$lang = $this->getParameter('lang')` или из [свойства |presenters#Request Parameters]. Если параметры хранятся в массиве, их можно расширить с помощью оператора `(expand)` (что-то вроде оператора `...` в PHP, но работает с ассоциативными массивами): diff --git a/application/ru/presenters.texy b/application/ru/presenters.texy index 70b5df9ace..b3b9fa2713 100644 --- a/application/ru/presenters.texy +++ b/application/ru/presenters.texy @@ -236,6 +236,32 @@ public function actionData(): void ``` +Параметры запроса .[#toc-request-parameters] +============================================ + +Ведущий, как и каждый компонент, получает свои параметры из HTTP-запроса. Их значения могут быть получены с помощью метода `getParameter($name)` или `getParameters()`. Значения представляют собой строки или массивы строк, по сути, необработанные данные, полученные непосредственно из URL. + +Для большего удобства рекомендуется сделать параметры доступными через свойства. Для этого достаточно аннотировать их с помощью `#[Parameter]` атрибутом: + +```php +use Nette\Application\Attributes\Parameter; // эта строка очень важна + +class HomePresenter extends Nette\Application\UI\Presenter +{ + #[Parameter] + public string $theme; // должна быть публичной +} +``` + +Для свойств рекомендуется указывать тип данных (например, `string`). В этом случае Nette будет автоматически приводить значение на его основе. Значения параметров также могут быть [проверены |#Validation of Parameters]. + +При создании ссылки можно непосредственно задать значение параметров: + +```latte +click +``` + + Постоянные параметры .[#toc-persistent-parameters] ================================================== @@ -257,7 +283,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter Если `$this->lang` имеет значение, например, `'en'`, то ссылки, созданные с помощью `link()` или `n:href`, также будут содержать параметр `lang=en`. И когда ссылка будет щелкнута, она снова станет `$this->lang = 'en'`. -Для свойств рекомендуется указывать тип данных (например, `string`), а также можно указать значение по умолчанию. Значения параметров могут быть [проверены |#Validation of Persistent Parameters]. +Для свойств рекомендуется указывать тип данных (например, `string`), а также можно указать значение по умолчанию. Значения параметров могут быть [проверены |#Validation of Parameters]. Постоянные параметры по умолчанию передаются между всеми действиями данного ведущего. Чтобы передать их между несколькими ведущими, необходимо определить их либо: @@ -307,18 +333,12 @@ class ProductPresenter extends Nette\Application\UI\Presenter Того, что мы показали до сих пор в этой главе, вероятно, будет достаточно. Следующие строки предназначены для тех, кто интересуется презентерами досконально и хочет знать всё. -Требования и параметры .[#toc-requirement-and-parameters] ---------------------------------------------------------- +Валидация параметров .[#toc-validation-of-parameters] +----------------------------------------------------- -Запрос, обрабатываемый ведущим, представляет собой объект [api:Nette\Application\Request] и возвращается методом ведущего `getRequest()`. Он включает в себя массив параметров, и каждый из них принадлежит либо какому-то из компонентов, либо непосредственно ведущему (который на самом деле тоже является компонентом, хотя и специальным). Поэтому Nette перераспределяет параметры и передает их между отдельными компонентами (и ведущим), вызывая метод `loadState(array $params)`. Параметры могут быть получены методом `getParameters(): array`, индивидуально с помощью `getParameter($name)`. Значения параметров представляют собой строки или массивы строк, в основном это необработанные данные, полученные непосредственно из URL. +Значения [параметров запроса |#request parameters] и [постоянных параметров |#persistent parameters], получаемых из URL, записываются в свойства методом `loadState()`. При этом также проверяется соответствие типа данных, указанного в свойстве, в противном случае выдается ответ с ошибкой 404 и страница не отображается. - -Валидация постоянных параметров .[#toc-validation-of-persistent-parameters] ---------------------------------------------------------------------------- - -Значения [постоянных параметров |#persistent parameters], полученных из URL, записываются в свойства методом `loadState()`. Он также проверяет, соответствует ли тип данных, указанный в свойстве, в противном случае выдается ошибка 404 и страница не отображается. - -Никогда не доверяйте слепо постоянным параметрам, так как они могут быть легко перезаписаны пользователем в URL. Например, так мы проверяем, входит ли `$this->lang` в число поддерживаемых языков. Хороший способ сделать это - переопределить метод `loadState()`, упомянутый выше: +Никогда не следует слепо доверять параметрам, так как они могут быть легко перезаписаны пользователем в URL. Например, так мы проверяем, входит ли `$this->lang` в число поддерживаемых языков. Хороший способ сделать это - переопределить метод `loadState()`, упомянутый выше: ```php class ProductPresenter extends Nette\Application\UI\Presenter @@ -341,7 +361,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter Сохранение и восстановление запроса .[#toc-save-and-restore-the-request] ------------------------------------------------------------------------ -Вы можете сохранить текущий запрос в сессии или восстановить его из сессии и позволить презентеру выполнить его снова. Это полезно, например, когда пользователь заполняет форму, а срок действия его логина истекает. Чтобы не потерять данные, перед перенаправлением на страницу регистрации мы сохраняем текущий запрос в сессию с помощью функции `$reqId = $this->storeRequest()`, которая возвращает идентификатор в виде короткой строки и передает его в качестве параметра презентеру для регистрации. +Запрос, который обрабатывает ведущий, представляет собой объект [api:Nette\Application\Request] и возвращается методом ведущего `getRequest()`. + +Вы можете сохранить текущий запрос в сессии или восстановить его из сессии и позволить ведущему выполнить его снова. Это удобно, например, когда пользователь заполняет форму, а его логин истекает. Чтобы не потерять данные, перед перенаправлением на страницу входа в систему мы сохраняем текущий запрос в сессии с помощью метода `$reqId = $this->storeRequest()`, который возвращает идентификатор в виде короткой строки и передает его в качестве параметра презентеру входа в систему. После входа в систему мы вызываем метод `$this->restoreRequest($reqId)`, который забирает запрос у сессии и пересылает его ей. Метод проверяет, что запрос был создан тем же пользователем, который сейчас вошел в систему. Если другой пользователь вошел в систему или ключ недействителен, он ничего не делает, и программа продолжает работу. @@ -425,6 +447,27 @@ $this->sendResponse(new Responses\CallbackResponse($callback)); ``` +Проверка метода HTTP .[#toc-http-method-check] +---------------------------------------------- + +Презентаторы в Nette автоматически проверяют HTTP-метод каждого входящего запроса. Основной причиной такой проверки является безопасность. Проверка метода осуществляется в `checkHttpMethod()`, который определяет, включен ли указанный в запросе метод в массив `$presenter->allowedMethods`. По умолчанию этот массив содержит элементы `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`, что означает, что эти методы разрешены. + +Если необходимо дополнительно разрешить метод `OPTIONS`, то это можно сделать следующим образом: + +```php +class MyPresenter extends Nette\Application\UI\Presenter +{ + protected function checkHttpMethod(): void + { + $this->allowedMethods[] = 'OPTIONS'; + parent::checkHttpMethod(); + } +} +``` + +Важно подчеркнуть, что если вы разрешаете метод `OPTIONS`, то должны правильно обработать его и в своем презентаторе. Этот метод часто используется в качестве так называемого preflight-запроса, который браузеры автоматически отправляют перед фактическим запросом, когда необходимо определить, разрешен ли запрос с точки зрения политики CORS (Cross-Origin Resource Sharing). Если разрешить этот метод, но не реализовать соответствующий ответ, это может привести к несоответствиям и потенциальным проблемам безопасности. + + Дальнейшее чтение .[#toc-further-reading] ========================================= diff --git a/application/sl/creating-links.texy b/application/sl/creating-links.texy index 4943feeb98..5944fc4ea5 100644 --- a/application/sl/creating-links.texy +++ b/application/sl/creating-links.texy @@ -38,7 +38,7 @@ Lahko ji posredujemo tudi poimenovane parametre. Naslednja povezava posreduje pa detail ``` -Če metoda `ProductPresenter::renderShow()` v svojem podpisu nima zapisa `$lang`, lahko vrednost parametra prebere z uporabo `$lang = $this->getParameter('lang')`. +Če metoda `ProductPresenter::renderShow()` v svojem podpisu nima `$lang`, lahko vrednost parametra pridobi z uporabo `$lang = $this->getParameter('lang')` ali iz [lastnosti |presenters#Request Parameters]. Če so parametri shranjeni v polju, jih je mogoče razširiti z operatorjem `...` (ali `(expand)` v Latte 2.x): diff --git a/application/sl/presenters.texy b/application/sl/presenters.texy index abfd2f2527..dd08914fe0 100644 --- a/application/sl/presenters.texy +++ b/application/sl/presenters.texy @@ -236,6 +236,32 @@ public function actionData(): void ``` +Parametri zahtevka .[#toc-request-parameters] +============================================= + +Predstavitelj in vsaka komponenta pridobi svoje parametre iz zahteve HTTP. Njihove vrednosti lahko pridobite z metodo `getParameter($name)` ali `getParameters()`. Vrednosti so nizi ali nizi nizov, v bistvu surovi podatki, pridobljeni neposredno iz URL. + +Zaradi večjega udobja priporočamo, da so parametri dostopni prek lastnosti. Preprosto jih opišite z ukazom `#[Parameter]` atributom: + +```php +use Nette\Application\Attributes\Parameter; // ta vrstica je pomembna + +class HomePresenter extends Nette\Application\UI\Presenter +{ + #[Parameter] + public string $theme; // mora biti javna. +} +``` + +Za lastnosti predlagamo, da navedete vrsto podatkov (npr. `string`). Nette bo na podlagi tega samodejno določil vrednost. Vrednosti parametrov je mogoče tudi [potrditi |#Validation of Parameters]. + +Pri ustvarjanju povezave lahko neposredno določite vrednost za parametre: + +```latte +click +``` + + Trajni parametri .[#toc-persistent-parameters] ============================================== @@ -257,7 +283,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter Če ima `$this->lang` vrednost, kot je `'en'`, bodo povezave, ustvarjene z uporabo `link()` ali `n:href`, vsebovale tudi parameter `lang=en`. In ko boste povezavo kliknili, bo ta spet imela vrednost `$this->lang = 'en'`. -Za lastnosti priporočamo, da vključite podatkovno vrsto (npr. `string`), vključite pa lahko tudi privzeto vrednost. Vrednosti parametrov je mogoče [potrditi |#Validation of Persistent Parameters]. +Za lastnosti priporočamo, da vključite podatkovno vrsto (npr. `string`), vključite pa lahko tudi privzeto vrednost. Vrednosti parametrov je mogoče [potrditi |#Validation of Parameters]. Trajni parametri se privzeto posredujejo med vsemi dejanji določenega predstavnika. Če jih želite posredovati med več predstavniki, jih morate opredeliti: @@ -307,18 +333,12 @@ Poglobitev .[#toc-going-deeper] To, kar smo doslej prikazali v tem poglavju, bo verjetno zadostovalo. Naslednje vrstice so namenjene tistim, ki jih predstavniki zanimajo poglobljeno in želijo vedeti vse. -Zahteve in parametri .[#toc-requirement-and-parameters] +Potrjevanje parametrov .[#toc-validation-of-parameters] ------------------------------------------------------- -Zahteva, ki jo obravnava predstavnik, je objekt [api:Nette\Application\Request] in jo vrne predstavnikova metoda `getRequest()`. Vključuje polje parametrov, vsak od njih pa pripada bodisi kateri od komponent bodisi neposredno predstavniku (ki je pravzaprav tudi komponenta, čeprav posebna). Nette torej parametre prerazporedi in posreduje med posameznimi komponentami (in predstavnikom) tako, da pokliče metodo `loadState(array $params)`. Parametre lahko pridobimo z metodo `getParameters(): array`, posamično pa z metodo `getParameter($name)`. Vrednosti parametrov so nizi ali polja nizov, v bistvu so surovi podatki, pridobljeni neposredno iz naslova URL. +Vrednosti [parametrov zahteve |#request parameters] in [trajnih parametrov |#persistent parameters], prejetih z naslovov URL, se zapišejo v lastnosti z metodo `loadState()`. Preveri tudi, ali se podatkovna vrsta, navedena v lastnosti, ujema, sicer se odzove z napako 404 in stran se ne prikaže. - -Potrjevanje trajnih parametrov .[#toc-validation-of-persistent-parameters] --------------------------------------------------------------------------- - -Vrednosti [trajnih parametrov |#persistent parameters], prejetih z naslovov URL, se zapišejo v lastnosti z metodo `loadState()`. Preveri tudi, ali se podatkovna vrsta, navedena v lastnosti, ujema, sicer se odzove z napako 404 in stran se ne prikaže. - -Nikoli ne zaupajte slepo trajnim parametrom, saj jih lahko uporabnik zlahka prepiše v naslovu URL. Tako na primer preverimo, ali je `$this->lang` med podprtimi jeziki. Dober način za to je, da prekrijete zgoraj omenjeno metodo `loadState()`: +Parametrom nikoli ne zaupajte na slepo, saj jih lahko uporabnik zlahka prepiše v naslovu URL. Tako na primer preverimo, ali je `$this->lang` med podprtimi jeziki. Dober način za to je, da prekrijete zgoraj omenjeno metodo `loadState()`: ```php class ProductPresenter extends Nette\Application\UI\Presenter @@ -341,7 +361,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter Shranjevanje in obnavljanje zahtevka .[#toc-save-and-restore-the-request] ------------------------------------------------------------------------- -Trenutni zahtevek lahko shranite v sejo ali pa ga obnovite iz seje in omogočite predavatelju, da ga ponovno izvede. To je na primer uporabno, ko uporabnik izpolni obrazec in mu poteče prijava. Da ne bi izgubili podatkov, pred preusmeritvijo na stran za prijavo shranimo trenutno zahtevo v sejo z uporabo `$reqId = $this->storeRequest()`, ki vrne identifikator v obliki kratkega niza in ga kot parameter posreduje predstavniku za prijavo. +Zahteva, ki jo predstavnik obravnava, je objekt [api:Nette\Application\Request] in jo vrne predstavnikova metoda `getRequest()`. + +Trenutni zahtevek lahko shranite v sejo ali pa ga obnovite iz seje in omogočite predstavniku, da ga ponovno izvede. To je na primer uporabno, ko uporabnik izpolni obrazec in mu poteče prijava. Da ne bi izgubili podatkov, pred preusmeritvijo na stran za prijavo shranimo trenutno zahtevo v sejo z uporabo `$reqId = $this->storeRequest()`, ki vrne identifikator v obliki kratkega niza in ga kot parameter posreduje predstavniku za prijavo. Po prijavi pokličemo metodo `$this->restoreRequest($reqId)`, ki prevzame zahtevo iz seje in ji jo posreduje naprej. Metoda preveri, ali je zahtevo ustvaril isti uporabnik, kot je zdaj prijavljeni. Če se prijavi drug uporabnik ali je ključ neveljaven, ne stori ničesar in program se nadaljuje. @@ -425,6 +447,27 @@ $this->sendResponse(new Responses\CallbackResponse($callback)); ``` +Preverjanje metode HTTP .[#toc-http-method-check] +------------------------------------------------- + +Predstavniki v Nette samodejno preverijo metodo HTTP vsake prejete zahteve. Glavni razlog za to preverjanje je varnost. Preverjanje metode se izvede v `checkHttpMethod()`, ki ugotovi, ali je metoda, navedena v zahtevi, vključena v polje `$presenter->allowedMethods`. Privzeto to polje vsebuje elemente `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`, kar pomeni, da so te metode dovoljene. + +Če želite dodatno dovoliti metodo `OPTIONS`, lahko to dosežete na naslednji način: + +```php +class MyPresenter extends Nette\Application\UI\Presenter +{ + protected function checkHttpMethod(): void + { + $this->allowedMethods[] = 'OPTIONS'; + parent::checkHttpMethod(); + } +} +``` + +Ključnega pomena je poudariti, da če omogočite metodo `OPTIONS`, jo morate ustrezno obdelati tudi v svojem predstavitvenem programu. Ta metoda se pogosto uporablja kot tako imenovana zahteva preflight, ki jo brskalniki samodejno pošljejo pred dejansko zahtevo, ko je treba ugotoviti, ali je zahteva dovoljena z vidika politike CORS (Cross-Origin Resource Sharing). Če to metodo dovolite, vendar ne izvedete ustreznega odziva, lahko pride do nedoslednosti in morebitnih varnostnih težav. + + Nadaljnje branje .[#toc-further-reading] ======================================== diff --git a/application/tr/creating-links.texy b/application/tr/creating-links.texy index 1b8325a446..d52dc2e452 100644 --- a/application/tr/creating-links.texy +++ b/application/tr/creating-links.texy @@ -38,7 +38,7 @@ Adlandırılmış parametreleri geçmek de mümkündür. Aşağıdaki bağlantı detail ``` -`ProductPresenter::renderShow()` yönteminin imzasında `$lang` yoksa, parametrenin değerini `$lang = $this->getParameter('lang')` kullanarak okuyabilir. +`ProductPresenter::renderShow()` yönteminin imzasında `$lang` yoksa, parametrenin değerini `$lang = $this->getParameter('lang')` kullanarak veya [özellikten |presenters#Request Parameters] alabilir. Parametreler bir dizide saklanıyorsa, `...` operatörü (veya Latte 2.x'te `(expand)` operatörü) ile genişletilebilirler: diff --git a/application/tr/presenters.texy b/application/tr/presenters.texy index 35e16c86d9..f269c3e2c7 100644 --- a/application/tr/presenters.texy +++ b/application/tr/presenters.texy @@ -236,6 +236,32 @@ public function actionData(): void ``` +İstek Parametreleri .[#toc-request-parameters] +============================================== + +Sunucu ve her bileşen, parametrelerini HTTP isteğinden alır. Değerleri `getParameter($name)` yöntemi veya `getParameters()` kullanılarak alınabilir. Değerler dizeler veya dizelerin dizileridir, esasen doğrudan URL'den elde edilen ham verilerdir. + +Daha fazla kolaylık için, parametreleri özellikler aracılığıyla erişilebilir hale getirmenizi öneririz. Bunları basitçe şu şekilde açıklayın `#[Parameter]` nitelik: + +```php +use Nette\Application\Attributes\Parameter; // bu hat önemli + +class HomePresenter extends Nette\Application\UI\Presenter +{ + #[Parameter] + public string $theme; // halka açık olmalı +} +``` + +Özellikler için veri türünü belirtmenizi öneririz (örneğin, `string`). Nette daha sonra değeri buna göre otomatik olarak dökecektir. Parametre değerleri de [doğrulanabilir |#Validation of Parameters]. + +Bir bağlantı oluştururken, parametreler için değeri doğrudan ayarlayabilirsiniz: + +```latte +click +``` + + Kalıcı Parametreler .[#toc-persistent-parameters] ================================================= @@ -257,7 +283,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter `$this->lang`, `'en'` gibi bir değere sahipse, `link()` veya `n:href` kullanılarak oluşturulan bağlantılar da `lang=en` parametresini içerecektir. Ve bağlantı tıklandığında, yine `$this->lang = 'en'` olacaktır. -Özellikler için veri türünü eklemenizi öneririz (örn. `string`) ve ayrıca varsayılan bir değer de ekleyebilirsiniz. Parametre değerleri [doğrulanabilir |#Validation of Persistent Parameters]. +Özellikler için veri türünü eklemenizi öneririz (örn. `string`) ve ayrıca varsayılan bir değer de ekleyebilirsiniz. Parametre değerleri [doğrulanabilir |#Validation of Parameters]. Kalıcı parametreler varsayılan olarak belirli bir sunum yapan kişinin tüm eylemleri arasında aktarılır. Bunları birden fazla sunum yapan kişi arasında geçirmek için tanımlamanız gerekir: @@ -307,18 +333,12 @@ Daha Derine Gitmek .[#toc-going-deeper] Bu bölümde şimdiye kadar gösterdiklerimiz muhtemelen yeterli olacaktır. Aşağıdaki satırlar, sunum yapanlarla derinlemesine ilgilenen ve her şeyi bilmek isteyenlere yöneliktir. -Gereksinim ve Parametreler .[#toc-requirement-and-parameters] -------------------------------------------------------------- +Parametrelerin Doğrulanması .[#toc-validation-of-parameters] +------------------------------------------------------------ -Sunum yapan kişi tarafından ele alınan istek [api:Nette\Application\Request] nesnesidir ve sunum yapan kişinin `getRequest()` yöntemi tarafından döndürülür. Bir dizi parametre içerir ve bunların her biri ya bazı bileşenlere ya da doğrudan sunum yapan kişiye aittir (aslında bu da özel bir bileşen olsa da bir bileşendir). Dolayısıyla Nette parametreleri yeniden dağıtır ve `loadState(array $params)` yöntemini çağırarak tek tek bileşenler (ve sunum yapan kişi) arasında geçiş yapar. Parametreler `getParameters(): array` yöntemiyle, ayrı ayrı `getParameter($name)` kullanılarak elde edilebilir. Parametre değerleri dizeler veya dizelerin dizileridir, temelde doğrudan bir URL'den elde edilen ham verilerdir. +URL'lerden alınan [istek parametr |#request parameters] eleri ve [kalıcı parametrelerin |#persistent parameters] değerleri `loadState()` metodu tarafından özelliklere yazılır. Ayrıca özellikte belirtilen veri tipinin eşleşip eşleşmediğini kontrol eder, aksi takdirde 404 hatası ile yanıt verir ve sayfa görüntülenmez. - -Kalıcı Parametrelerin Doğrulanması .[#toc-validation-of-persistent-parameters] ------------------------------------------------------------------------------- - -URL'lerden alınan [kalıcı parametrelerin |#persistent parameters] değerleri `loadState()` metodu tarafından özelliklere yazılır. Ayrıca özellikte belirtilen veri türünün eşleşip eşleşmediğini kontrol eder, aksi takdirde 404 hatası ile yanıt verir ve sayfa görüntülenmez. - -Kalıcı parametrelere asla körü körüne güvenmeyin, çünkü bunlar URL'de kullanıcı tarafından kolayca üzerine yazılabilir. Örneğin, `$this->lang` adresinin desteklenen diller arasında olup olmadığını bu şekilde kontrol ediyoruz. Bunu yapmanın iyi bir yolu, yukarıda bahsedilen `loadState()` yöntemini geçersiz kılmaktır: +URL'de kullanıcı tarafından kolayca üzerine yazılabilecekleri için parametrelere asla körü körüne güvenmeyin. Örneğin, `$this->lang` adresinin desteklenen diller arasında olup olmadığını bu şekilde kontrol ederiz. Bunu yapmanın iyi bir yolu, yukarıda bahsedilen `loadState()` yöntemini geçersiz kılmaktır: ```php class ProductPresenter extends Nette\Application\UI\Presenter @@ -341,7 +361,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter Talebi Kaydetme ve Geri Yükleme .[#toc-save-and-restore-the-request] -------------------------------------------------------------------- -Geçerli isteği bir oturuma kaydedebilir veya oturumdan geri yükleyebilir ve sunucunun tekrar yürütmesine izin verebilirsiniz. Bu, örneğin bir kullanıcı bir formu doldurduğunda ve oturum açma süresi dolduğunda kullanışlıdır. Veri kaybetmemek için, oturum açma sayfasına yönlendirmeden önce, kısa bir dize biçiminde bir tanımlayıcı döndüren ve oturum açma sunucusuna parametre olarak ileten `$reqId = $this->storeRequest()` adresini kullanarak geçerli isteği oturuma kaydederiz. +Sunum yapan kişinin ele aldığı istek bir [api:Nette\Application\Request] nesnesidir ve sunum yapan kişinin `getRequest()` yöntemi tarafından döndürülür. + +Geçerli isteği bir oturuma kaydedebilir veya oturumdan geri yükleyebilir ve sunum yapan kişinin bunu tekrar yürütmesine izin verebilirsiniz. Bu, örneğin bir kullanıcı bir formu doldurduğunda ve oturum açma süresi dolduğunda kullanışlıdır. Verileri kaybetmemek için, oturum açma sayfasına yönlendirmeden önce, kısa bir dize biçiminde bir tanımlayıcı döndüren ve oturum açma sunucusuna parametre olarak ileten `$reqId = $this->storeRequest()` adresini kullanarak geçerli isteği oturuma kaydederiz. Oturum açtıktan sonra, isteği oturumdan alan ve ona ileten `$this->restoreRequest($reqId)` yöntemini çağırıyoruz. Yöntem, isteğin şu anda oturum açmış olan kullanıcıyla aynı kullanıcı tarafından oluşturulduğunu doğrular. Başka bir kullanıcı giriş yaparsa veya anahtar geçersizse, hiçbir şey yapmaz ve program devam eder. @@ -425,6 +447,27 @@ $this->sendResponse(new Responses\CallbackResponse($callback)); ``` +HTTP Yöntem Kontrolü .[#toc-http-method-check] +---------------------------------------------- + +Nette'deki sunucular, gelen her isteğin HTTP yöntemini otomatik olarak doğrular. Bu doğrulamanın birincil nedeni güvenliktir. Yöntem kontrolü, istekte belirtilen yöntemin `$presenter->allowedMethods` dizisinde yer alıp almadığını belirleyen `checkHttpMethod()` adresinde gerçekleştirilir. Varsayılan olarak, bu dizi `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH` öğelerini içerir, yani bu yöntemlere izin verilir. + +Ek olarak `OPTIONS` yöntemine izin vermek isterseniz, bu aşağıdaki şekilde gerçekleştirilebilir: + +```php +class MyPresenter extends Nette\Application\UI\Presenter +{ + protected function checkHttpMethod(): void + { + $this->allowedMethods[] = 'OPTIONS'; + parent::checkHttpMethod(); + } +} +``` + + `OPTIONS` yöntemini etkinleştirirseniz, bunu sunucunuzda da düzgün bir şekilde ele almanız gerektiğini vurgulamak çok önemlidir. Bu yöntem genellikle, tarayıcıların CORS (Cross-Origin Resource Sharing) politikası açısından isteğe izin verilip verilmediğini belirlemek için gerekli olduğunda asıl istekten önce otomatik olarak gönderdiği bir ön kontrol isteği olarak kullanılır. Bu yönteme izin verir ancak uygun bir yanıt uygulamazsanız, tutarsızlıklara ve potansiyel güvenlik sorunlarına yol açabilir. + + Daha Fazla Okuma .[#toc-further-reading] ======================================== diff --git a/application/uk/creating-links.texy b/application/uk/creating-links.texy index 34ec0457fb..fc428edab6 100644 --- a/application/uk/creating-links.texy +++ b/application/uk/creating-links.texy @@ -38,7 +38,7 @@ подробнее ``` -Якщо метод `ProductPresenter::renderShow()` не має `$lang` у своїй сигнатурі, він може прочитати значення параметра, використовуючи `$lang = $this->getParameter('lang')`. +Якщо метод `ProductPresenter::renderShow()` не має `$lang` у своїй сигнатурі, він може отримати значення параметра за допомогою `$lang = $this->getParameter('lang')` або з [властивості |presenters#Request Parameters]. Якщо параметри зберігаються в масиві, їх можна розширити за допомогою оператора `(expand)` (щось на зразок оператора `...` у PHP, але працює з асоціативними масивами): diff --git a/application/uk/presenters.texy b/application/uk/presenters.texy index 1f81ec0dbf..d10e79fb17 100644 --- a/application/uk/presenters.texy +++ b/application/uk/presenters.texy @@ -236,6 +236,32 @@ public function actionData(): void ``` +Параметри запиту .[#toc-request-parameters] +=========================================== + +Доповідач, як і кожен компонент, отримує свої параметри з HTTP-запиту. Їх значення можна отримати за допомогою методу `getParameter($name)` або `getParameters()`. Значення є рядками або масивами рядків, по суті, необробленими даними, отриманими безпосередньо з URL-адреси. + +Для більшої зручності ми рекомендуємо зробити параметри доступними через властивості. Просто додайте до них анотацію з атрибутом `#[Parameter]` за допомогою атрибута + +```php +use Nette\Application\Attributes\Parameter; // ця лінія важлива + +class HomePresenter extends Nette\Application\UI\Presenter +{ + #[Parameter] + public string $theme; // має бути публічною +} +``` + +Для властивостей ми рекомендуємо вказувати тип даних (наприклад, `string`). Тоді Nette автоматично перетворить значення на основі цього типу. Значення параметрів також можна [перевірити |#Validation of Parameters]. + +При створенні посилання ви можете безпосередньо задати значення параметрів: + +```latte +click +``` + + Постійні параметри .[#toc-persistent-parameters] ================================================ @@ -257,7 +283,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter Якщо `$this->lang` має значення `'en'`, то посилання, створені за допомогою `link()` або `n:href`, також будуть містити параметр `lang=en`. І коли посилання буде натиснуто, воно знову стане `$this->lang = 'en'`. -Для властивостей рекомендується вказувати тип даних (наприклад, `string`), а також можна вказати значення за замовчуванням. Значення параметрів можна [перевіряти |#Validation of Persistent Parameters]. +Для властивостей рекомендується вказувати тип даних (наприклад, `string`), а також значення за замовчуванням. Значення параметрів можуть бути [перевірені |#Validation of Parameters]. Постійні параметри за замовчуванням передаються між усіма діями даного доповідача. Щоб передати їх між кількома доповідачами, вам також потрібно їх визначити: @@ -307,18 +333,12 @@ class ProductPresenter extends Nette\Application\UI\Presenter Того, що ми показали досі в цьому розділі, ймовірно, буде достатньо. Наступні рядки призначені для тих, хто цікавиться презентерами досконально і хоче знати все. -Вимоги та параметри .[#toc-requirement-and-parameters] ------------------------------------------------------- +Перевірка параметрів .[#toc-validation-of-parameters] +----------------------------------------------------- -Запит, який обробляє доповідач, є об'єктом [api:Nette\Application\Request] і повертається методом доповідача `getRequest()`. Він містить масив параметрів, кожен з яких належить або якомусь з компонентів, або безпосередньо доповідачу (який, власне, теж є компонентом, хоча й особливим). Тож Nette перерозподіляє параметри та передачі між окремими компонентами (та доповідачем) за допомогою виклику методу `loadState(array $params)`. Параметри можна отримати за допомогою методу `getParameters(): array`, окремо за допомогою `getParameter($name)`. Значення параметрів - це рядки або масиви рядків, в основному це необроблені дані, отримані безпосередньо з URL-адреси. +Значення [параметрів запиту |#request parameters] і [постійних параметрів |#persistent parameters], отриманих з URL-адрес, записуються у властивості методом `loadState()`. Також перевіряється, чи збігається тип даних, вказаний у властивості, інакше буде видано помилку 404 і сторінка не буде відображена. - -Перевірка постійних параметрів .[#toc-validation-of-persistent-parameters] --------------------------------------------------------------------------- - -Значення [постійних параметрів |#persistent parameters], отриманих з URL-адрес, записуються у властивості методом `loadState()`. Також перевіряється, чи збігається тип даних, вказаний у властивості, інакше буде видано помилку 404, і сторінка не буде відображена. - -Ніколи не довіряйте сліпо постійним параметрам, оскільки вони можуть бути легко перезаписані користувачем в URL. Наприклад, так ми перевіряємо, чи є `$this->lang` серед підтримуваних мов. Хороший спосіб зробити це - перевизначити метод `loadState()`, згаданий вище: +Ніколи не довіряйте параметрам наосліп, оскільки вони можуть бути легко переписані користувачем в URL-адресі. Наприклад, так ми перевіряємо, чи є `$this->lang` серед підтримуваних мов. Хороший спосіб зробити це - перевизначити метод `loadState()`, згаданий вище: ```php class ProductPresenter extends Nette\Application\UI\Presenter @@ -341,7 +361,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter Збереження та відновлення запиту .[#toc-save-and-restore-the-request] --------------------------------------------------------------------- -Ви можете зберегти поточний запит у сесії або відновити його із сесії та дозволити презентеру виконати його знову. Це корисно, наприклад, коли користувач заповнює форму, а термін дії його логіна закінчується. Щоб не втратити дані, перед перенаправленням на сторінку реєстрації ми зберігаємо поточний запит у сесію за допомогою функції `$reqId = $this->storeRequest()`, яка повертає ідентифікатор у вигляді короткого рядка і передає його як параметр презенту для реєстрації. +Запит, який обробляє доповідач, є об'єктом [api:Nette\Application\Request] і повертається методом доповідача `getRequest()`. + +Ви можете зберегти поточний запит в сеансі або відновити його з сеансу і дозволити ведучому виконати його знову. Це корисно, наприклад, коли користувач заповнив форму, а його логін закінчується. Щоб не втратити дані, перед перенаправленням на сторінку входу, ми зберігаємо поточний запит до сесії за допомогою `$reqId = $this->storeRequest()`, який повертає ідентифікатор у вигляді короткого рядка і передає його як параметр ведучому входу. Після входу в систему ми викликаємо метод `$this->restoreRequest($reqId)`, який забирає запит у сесії та пересилає його їй. Метод перевіряє, що запит був створений тим самим користувачем, який зараз увійшов у систему. Якщо інший користувач увійшов у систему або ключ недійсний, він нічого не робить, і програма продовжує роботу. @@ -425,6 +447,27 @@ $this->sendResponse(new Responses\CallbackResponse($callback)); ``` +Перевірка методу HTTP .[#toc-http-method-check] +----------------------------------------------- + +Доповідачі в Nette автоматично перевіряють HTTP-метод кожного вхідного запиту. Основною причиною цієї перевірки є безпека. Перевірка методу здійснюється в `checkHttpMethod()`, де визначається, чи входить вказаний у запиті метод до масиву `$presenter->allowedMethods`. За замовчуванням цей масив містить елементи `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`, що означає, що ці методи дозволені. + +Якщо ви хочете додатково дозволити метод `OPTIONS`, це можна зробити наступним чином: + +```php +class MyPresenter extends Nette\Application\UI\Presenter +{ + protected function checkHttpMethod(): void + { + $this->allowedMethods[] = 'OPTIONS'; + parent::checkHttpMethod(); + } +} +``` + +Важливо підкреслити, що якщо ви дозволите метод `OPTIONS`, ви також повинні правильно обробляти його у вашому презентері. Цей метод часто використовується як так званий попередній запит, який браузери автоматично надсилають перед самим запитом, коли необхідно визначити, чи дозволений запит з точки зору політики CORS (Cross-Origin Resource Sharing). Якщо ви дозволите цей метод, але не реалізуєте відповідну реакцію, це може призвести до невідповідностей і потенційних проблем з безпекою. + + Читати далі .[#toc-further-reading] =================================== From 6a5ebe1fd3b8dbdc6886b32f06bbd441c02760cf Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 5 Oct 2023 04:24:24 +0200 Subject: [PATCH 019/137] improvements --- forms/bg/rendering.texy | 2 ++ forms/cs/rendering.texy | 2 ++ forms/de/rendering.texy | 2 ++ forms/el/rendering.texy | 2 ++ forms/en/rendering.texy | 2 ++ forms/es/rendering.texy | 2 ++ forms/fr/rendering.texy | 2 ++ forms/hu/rendering.texy | 2 ++ forms/it/rendering.texy | 2 ++ forms/pl/rendering.texy | 2 ++ forms/pt/rendering.texy | 2 ++ forms/ro/rendering.texy | 2 ++ forms/ru/rendering.texy | 2 ++ forms/sl/rendering.texy | 2 ++ forms/tr/rendering.texy | 2 ++ forms/uk/rendering.texy | 2 ++ 16 files changed, 32 insertions(+) diff --git a/forms/bg/rendering.texy b/forms/bg/rendering.texy index a9347307a8..94b898d7b9 100644 --- a/forms/bg/rendering.texy +++ b/forms/bg/rendering.texy @@ -434,6 +434,8 @@ $form->addText('city', 'Город:'); $form->addSelect('country', 'Страна:', $countries); ``` +Рендърът рисува първо групите, а след това елементите, които не принадлежат към никоя група. + Поддръжка на Bootstrap .[#toc-bootstrap-support] ------------------------------------------------ diff --git a/forms/cs/rendering.texy b/forms/cs/rendering.texy index ec272f49fb..45963b6a9a 100644 --- a/forms/cs/rendering.texy +++ b/forms/cs/rendering.texy @@ -434,6 +434,8 @@ $form->addText('city', 'City:'); $form->addSelect('country', 'Country:', $countries); ``` +Renderer nejprve vykresluje skupiny a teprve poté prvky, které do žádné skupiny nepatří. + Podpora pro Bootstrap --------------------- diff --git a/forms/de/rendering.texy b/forms/de/rendering.texy index ca24a4ae2f..bbf6690248 100644 --- a/forms/de/rendering.texy +++ b/forms/de/rendering.texy @@ -434,6 +434,8 @@ $form->addText('city', 'City:'); $form->addSelect('country', 'Country:', $countries); ``` +Der Renderer zeichnet zuerst die Gruppen und dann die Elemente, die zu keiner Gruppe gehören. + Bootstrap-Unterstützung .[#toc-bootstrap-support] ------------------------------------------------- diff --git a/forms/el/rendering.texy b/forms/el/rendering.texy index d56be8d3f5..169c07138f 100644 --- a/forms/el/rendering.texy +++ b/forms/el/rendering.texy @@ -434,6 +434,8 @@ $form->addText('city', 'City:'); $form->addSelect('country', 'Country:', $countries); ``` +Ο renderer σχεδιάζει πρώτα τις ομάδες και στη συνέχεια τα στοιχεία που δεν ανήκουν σε καμία ομάδα. + Υποστήριξη Bootstrap .[#toc-bootstrap-support] ---------------------------------------------- diff --git a/forms/en/rendering.texy b/forms/en/rendering.texy index 27c71677e4..04d433baf8 100644 --- a/forms/en/rendering.texy +++ b/forms/en/rendering.texy @@ -434,6 +434,8 @@ $form->addText('city', 'City:'); $form->addSelect('country', 'Country:', $countries); ``` +The renderer draws groups first and then elements that do not belong to any group. + Bootstrap Support ----------------- diff --git a/forms/es/rendering.texy b/forms/es/rendering.texy index 91ce9f6d5e..2039385434 100644 --- a/forms/es/rendering.texy +++ b/forms/es/rendering.texy @@ -434,6 +434,8 @@ $form->addText('city', 'City:'); $form->addSelect('country', 'Country:', $countries); ``` +El renderizador dibuja primero los grupos y después los elementos que no pertenecen a ningún grupo. + Soporte Bootstrap .[#toc-bootstrap-support] ------------------------------------------- diff --git a/forms/fr/rendering.texy b/forms/fr/rendering.texy index 2915a9b2c9..5aaa56466a 100644 --- a/forms/fr/rendering.texy +++ b/forms/fr/rendering.texy @@ -434,6 +434,8 @@ $form->addText('city', 'City:'); $form->addSelect('country', 'Country:', $countries); ``` +Le moteur de rendu dessine d'abord les groupes, puis les éléments qui n'appartiennent à aucun groupe. + Support Bootstrap .[#toc-bootstrap-support] ------------------------------------------- diff --git a/forms/hu/rendering.texy b/forms/hu/rendering.texy index 813324306e..783a433b2a 100644 --- a/forms/hu/rendering.texy +++ b/forms/hu/rendering.texy @@ -434,6 +434,8 @@ $form->addText('city', 'City:'); $form->addSelect('country', 'Country:', $countries); ``` +A renderelő először a csoportokat rajzolja ki, majd azokat az elemeket, amelyek nem tartoznak egyik csoporthoz sem. + Bootstrap támogatás .[#toc-bootstrap-support] --------------------------------------------- diff --git a/forms/it/rendering.texy b/forms/it/rendering.texy index b1ac2c635b..a3b9c9036b 100644 --- a/forms/it/rendering.texy +++ b/forms/it/rendering.texy @@ -434,6 +434,8 @@ $form->addText('city', 'City:'); $form->addSelect('country', 'Country:', $countries); ``` +Il renderer disegna prima i gruppi e poi gli elementi che non appartengono a nessun gruppo. + Supporto Bootstrap .[#toc-bootstrap-support] -------------------------------------------- diff --git a/forms/pl/rendering.texy b/forms/pl/rendering.texy index b224e8d73d..fc31847b7e 100644 --- a/forms/pl/rendering.texy +++ b/forms/pl/rendering.texy @@ -434,6 +434,8 @@ $form->addText('city', 'City:'); $form->addSelect('country', 'Country:', $countries); ``` +Program renderujący najpierw rysuje grupy, a następnie elementy, które nie należą do żadnej grupy. + Wsparcie dla Bootstrap .[#toc-bootstrap-support] ------------------------------------------------ diff --git a/forms/pt/rendering.texy b/forms/pt/rendering.texy index 37a6d94fdc..11f39bb0d2 100644 --- a/forms/pt/rendering.texy +++ b/forms/pt/rendering.texy @@ -434,6 +434,8 @@ $form->addText('city', 'City:'); $form->addSelect('country', 'Country:', $countries); ``` +O renderizador desenha primeiro os grupos e depois os elementos que não pertencem a nenhum grupo. + Suporte de Bootstrap .[#toc-bootstrap-support] ---------------------------------------------- diff --git a/forms/ro/rendering.texy b/forms/ro/rendering.texy index 1eb25cc947..0e72098c3c 100644 --- a/forms/ro/rendering.texy +++ b/forms/ro/rendering.texy @@ -434,6 +434,8 @@ $form->addText('city', 'City:'); $form->addSelect('country', 'Country:', $countries); ``` +Dispozitivul de redare desenează mai întâi grupurile și apoi elementele care nu aparțin niciunui grup. + Suport Bootstrap .[#toc-bootstrap-support] ------------------------------------------ diff --git a/forms/ru/rendering.texy b/forms/ru/rendering.texy index 0d1a640600..5abe127075 100644 --- a/forms/ru/rendering.texy +++ b/forms/ru/rendering.texy @@ -434,6 +434,8 @@ $form->addText('city', 'Город:'); $form->addSelect('country', 'Страна:', $countries); ``` +Сначала рендерер отрисовывает группы, а затем элементы, не принадлежащие ни к одной из групп. + Поддержка Bootstrap .[#toc-bootstrap-support] --------------------------------------------- diff --git a/forms/sl/rendering.texy b/forms/sl/rendering.texy index 680af79ddd..3c6dc0d824 100644 --- a/forms/sl/rendering.texy +++ b/forms/sl/rendering.texy @@ -434,6 +434,8 @@ $form->addText('city', 'City:'); $form->addSelect('country', 'Country:', $countries); ``` +Renderer najprej izriše skupine, nato pa elemente, ki ne pripadajo nobeni skupini. + Podpora Bootstrap .[#toc-bootstrap-support] ------------------------------------------- diff --git a/forms/tr/rendering.texy b/forms/tr/rendering.texy index 2835653df8..787bb1e875 100644 --- a/forms/tr/rendering.texy +++ b/forms/tr/rendering.texy @@ -434,6 +434,8 @@ $form->addText('city', 'City:'); $form->addSelect('country', 'Country:', $countries); ``` +Oluşturucu önce grupları, ardından da herhangi bir gruba ait olmayan öğeleri çizer. + Bootstrap Desteği .[#toc-bootstrap-support] ------------------------------------------- diff --git a/forms/uk/rendering.texy b/forms/uk/rendering.texy index 95bf703c4d..6550558c6a 100644 --- a/forms/uk/rendering.texy +++ b/forms/uk/rendering.texy @@ -434,6 +434,8 @@ $form->addText('city', 'Город:'); $form->addSelect('country', 'Страна:', $countries); ``` +Рендер спочатку малює групи, а потім елементи, які не належать до жодної групи. + Підтримка Bootstrap .[#toc-bootstrap-support] --------------------------------------------- From 35101fb18672f998415304ca472c0389ce4d0ae3 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 10 Oct 2023 17:57:32 +0200 Subject: [PATCH 020/137] nette/forms 3.1.12 --- forms/bg/controls.texy | 19 ++++++++++++++++--- forms/bg/rendering.texy | 6 +++--- forms/bg/validation.texy | 2 +- forms/cs/controls.texy | 19 ++++++++++++++++--- forms/cs/rendering.texy | 6 +++--- forms/cs/validation.texy | 2 +- forms/de/controls.texy | 19 ++++++++++++++++--- forms/de/rendering.texy | 6 +++--- forms/de/validation.texy | 2 +- forms/el/controls.texy | 19 ++++++++++++++++--- forms/el/rendering.texy | 6 +++--- forms/el/validation.texy | 2 +- forms/en/controls.texy | 19 ++++++++++++++++--- forms/en/rendering.texy | 6 +++--- forms/en/validation.texy | 2 +- forms/es/controls.texy | 19 ++++++++++++++++--- forms/es/rendering.texy | 6 +++--- forms/es/validation.texy | 2 +- forms/fr/controls.texy | 19 ++++++++++++++++--- forms/fr/rendering.texy | 6 +++--- forms/fr/validation.texy | 2 +- forms/hu/controls.texy | 19 ++++++++++++++++--- forms/hu/rendering.texy | 6 +++--- forms/hu/validation.texy | 2 +- forms/it/controls.texy | 19 ++++++++++++++++--- forms/it/rendering.texy | 6 +++--- forms/it/validation.texy | 2 +- forms/pl/controls.texy | 19 ++++++++++++++++--- forms/pl/rendering.texy | 6 +++--- forms/pl/validation.texy | 2 +- forms/pt/controls.texy | 19 ++++++++++++++++--- forms/pt/rendering.texy | 6 +++--- forms/pt/validation.texy | 2 +- forms/ro/controls.texy | 19 ++++++++++++++++--- forms/ro/rendering.texy | 6 +++--- forms/ro/validation.texy | 2 +- forms/ru/controls.texy | 19 ++++++++++++++++--- forms/ru/rendering.texy | 6 +++--- forms/ru/validation.texy | 2 +- forms/sl/controls.texy | 19 ++++++++++++++++--- forms/sl/rendering.texy | 6 +++--- forms/sl/validation.texy | 2 +- forms/tr/controls.texy | 19 ++++++++++++++++--- forms/tr/rendering.texy | 6 +++--- forms/tr/validation.texy | 2 +- forms/uk/controls.texy | 19 ++++++++++++++++--- forms/uk/rendering.texy | 6 +++--- forms/uk/validation.texy | 2 +- latte/bg/tags.texy | 1 - latte/cs/tags.texy | 1 - latte/de/tags.texy | 1 - latte/el/tags.texy | 1 - latte/en/tags.texy | 1 - latte/es/tags.texy | 1 - latte/fr/tags.texy | 1 - latte/hu/tags.texy | 1 - latte/it/tags.texy | 1 - latte/ja/tags.texy | 1 - latte/pl/tags.texy | 1 - latte/pt/tags.texy | 1 - latte/ro/tags.texy | 1 - latte/ru/tags.texy | 1 - latte/sl/tags.texy | 1 - latte/tr/tags.texy | 1 - latte/uk/tags.texy | 1 - 65 files changed, 320 insertions(+), 129 deletions(-) diff --git a/forms/bg/controls.texy b/forms/bg/controls.texy index 9b6407375b..ef9f30e62f 100644 --- a/forms/bg/controls.texy +++ b/forms/bg/controls.texy @@ -20,7 +20,7 @@ $form->addText('name', 'Имя:') Максималната дължина може да бъде ограничена с помощта на `setMaxLength()`. Функцията [addFilter() |validation#Modifying-Input-Values] позволява да се промени стойността, въведена от потребителя. -Използвайте `setHtmlType()`, за да промените [типа на |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] входния елемент на `search`, `tel`, `url`, `range`, `date`, `datetime-local`, `month`, `time`, `week`, `color`. Препоръчваме да използвате [addInteger |#addInteger] и [addEmail |#addEmail] вместо `number` и `email`, тъй като те осигуряват валидиране от страна на сървъра. +Можете да използвате `setHtmlType()`, за да промените [символа на |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] входния елемент на `search`, `tel`, `url`, `range`, `datetime-local`, `month`, `time`, `week`, `color`. Вместо типовете `number` и `email` ви препоръчваме да използвате [addInteger |#addInteger], [addFloat |#addFloat] и [addEmail |#addEmail], които имат валидиране от страна на сървъра. ```php $form->addText('color', 'Выберите цвет:') @@ -58,11 +58,24 @@ addInteger(string|int $name, $label=null): TextInput .[method] Добавя поле за въвеждане на цяло число (клас [TextInput |api:Nette\Forms\Controls\TextInput]). Връща цяло число или `null`, ако потребителят не е въвел нищо. ```php -$form->addInteger('level', 'Уровень:') +$form->addInteger('year', 'Year:') + ->addRule($form::Range, 'The year must be in the range %d to %d.', [1900, 2023 |1900, 2023]); +``` + + +addFloat(string|int $name, $label=null): TextInput .[method]{data-version:3.1.12} +================================================================================= + +Adds a field for entering a decimal number ([TextInput |api:Nette\Forms\Controls\TextInput] class). Returns either float or `null`, if the user does not specify anything. + +```php +$form->addFloat('level', 'Level:') ->setDefaultValue(0) - ->addRule($form::Range, 'Уровень должен быть между %d и %d.', [0, 100]); +->addRule($form::Range, 'Нивото трябва да е в диапазона от %d до %d.', [0, 100 |0, 100]); ``` +Nette и Chrome приемат както запетая, така и точка като десетичен разделител. За да може Firefox също да приема запетая, трябва да зададете съответния език в HTML атрибута `lang`, или директно към този елемент, или към някой родителски елемент, например ``. + addEmail(string|int $name, $label=null): TextInput .[method] ============================================================ diff --git a/forms/bg/rendering.texy b/forms/bg/rendering.texy index 94b898d7b9..c0c764948a 100644 --- a/forms/bg/rendering.texy +++ b/forms/bg/rendering.texy @@ -237,15 +237,15 @@ protected function createComponentSignInForm(): Form Специални случаи .[#toc-special-cases] -------------------------------------- -Ако трябва да покажете само вътрешното съдържание на формуляра, без да `
` & `
` HTML тагове, например в AJAX заявка, можете да отваряте и затваряте формуляра, като използвате `{formContext} … {/formContext}`. В логически смисъл той работи подобно на `{form}`, като тук ви позволява да използвате други тагове, за да рисувате елементи на формата, но в същото време не рисува нищо. +Ако трябва да визуализирате само вътрешната част на формуляра без HTML тагове `
`например при изпращане на фрагменти, скрийте ги с помощта на атрибута `n:tag-if`: ```latte -{formContext signForm} +
{inputError username}
-{/formContext} +
``` Тагът `formContainer` помага за визуализиране на входните данни в контейнера на формата. diff --git a/forms/bg/validation.texy b/forms/bg/validation.texy index 742c787c3c..246cd77d16 100644 --- a/forms/bg/validation.texy +++ b/forms/bg/validation.texy @@ -38,7 +38,7 @@ Nette разполага с редица вградени правила, чии | `IsNotIn` | стойността не е равна на нито един елемент от масива | `array` | `Valid` | записът преминава валидиране (за [Условие |#Условия]) | - -За контролите `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()` могат да се използват и следните правила: +За елементите `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` могат да се приложат и някои от следните правила: | `MinLength` | минимална дължина на реда `int` | `MaxLength` | максимална дължина на реда `int` diff --git a/forms/cs/controls.texy b/forms/cs/controls.texy index ff382a7ed6..237ef0547f 100644 --- a/forms/cs/controls.texy +++ b/forms/cs/controls.texy @@ -20,7 +20,7 @@ Automaticky validuje UTF-8, ořezává levo- a pravostranné mezery a odstraňuj Maximální délku lze omezit pomocí `setMaxLength()`. Pozměnit uživatelem vloženou hodnotu umožňuje [addFilter()|validation#Úprava vstupu]. -Pomocí `setHtmlType()` lze změnit [charakter|https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] vstupního prvku na `search`, `tel`, `url`, `range`, `date`, `datetime-local`, `month`, `time`, `week`, `color`. Místo typů `number` a `email` doporučujeme použít [#addInteger] a [#addEmail], které disponují validací na straně serveru. +Pomocí `setHtmlType()` lze změnit [charakter|https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] vstupního prvku na `search`, `tel`, `url`, `range`, `datetime-local`, `month`, `time`, `week`, `color`. Místo typů `number` a `email` doporučujeme použít [#addInteger], [#addFloat] a [#addEmail], které disponují validací na straně serveru. ```php $form->addText('color', 'Vyberte barvu:') @@ -58,11 +58,24 @@ addInteger(string|int $name, $label=null): TextInput .[method] Přidá políčko pro zadání celočíselného čísla (třída [TextInput |api:Nette\Forms\Controls\TextInput]). Vrací buď integer, nebo `null`, pokud uživatel nic nezadá. ```php -$form->addInteger('level', 'Úroveň:') +$form->addInteger('year', 'Rok:') + ->addRule($form::Range, 'Rok musí být v rozsahu od %d do %d.', [1900, 2023]); +``` + + +addFloat(string|int $name, $label=null): TextInput .[method]{data-version:3.1.12} +================================================================================= + +Přidá políčko pro zadání desetinného čísla (třída [TextInput |api:Nette\Forms\Controls\TextInput]). Vrací buď float, nebo `null`, pokud uživatel nic nezadá. + +```php +$form->addFloat('level', 'Úroveň:') ->setDefaultValue(0) - ->addRule($form::Range, 'Úroveň musí být v rozsahu mezi %d a %d.', [0, 100]); + ->addRule($form::Range, 'Úroveň musí být v rozsahu od %d do %d.', [0, 100]); ``` +Nette a prohlížeč Chrome akceptují jako oddělovač desetinných míst čárku i tečku. Aby Firefox také akceptoval čárku, je potřeba nastavit odpovídající jazyk v HTML atributu `lang`, a to buď přímo tomuto prvku, nebo kterémukoliv nadřazenému elementu, například ``. + addEmail(string|int $name, $label=null): TextInput .[method] ============================================================ diff --git a/forms/cs/rendering.texy b/forms/cs/rendering.texy index 45963b6a9a..91217dba87 100644 --- a/forms/cs/rendering.texy +++ b/forms/cs/rendering.texy @@ -237,15 +237,15 @@ Blok přitom stačí importovat na jediném místě a to na začátku šablony l Speciální případy ----------------- -Pokud potřebujete vykreslit jen vnitřní část formuláře bez HTML značek `
` & `
`, například při AJAXovém požadavku, můžete formulář otevří a uzavřít do `{formContext} … {/formContext}`. Funguje podobně jako `
` či `{form}` v logickém smyslu, tady umožní používat ostatní značky pro kreslení prvků formuláře, ale přitom nic nevykreslí. +Pokud potřebujete vykreslit jen vnitřní část formuláře bez HTML značek ``, například při posílání snippetů, skryjte je pomocí atributu `n:tag-if`: ```latte -{formContext signForm} +
{inputError username}
-{/formContext} +
``` S vykreslením prvků uvnitř formulářového kontejneru pomůže tag `{formContainer}`. diff --git a/forms/cs/validation.texy b/forms/cs/validation.texy index 39017bbaf4..fd4179c8de 100644 --- a/forms/cs/validation.texy +++ b/forms/cs/validation.texy @@ -38,7 +38,7 @@ U všech prvků můžeme použít tyto pravidla: | `IsNotIn` | hodnota se nerovná žádné položce v poli | `array` | `Valid` | je prvek vyplněn správně? (pro [#podmínky]) | - -U prvků `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()` lze použít i následující pravidla: +U prvků `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` lze použít i některá následující pravidla: | `MinLength` | minimální délka textu | `int` | `MaxLength` | maximální délka textu | `int` diff --git a/forms/de/controls.texy b/forms/de/controls.texy index bc3e9ac752..33f09429bf 100644 --- a/forms/de/controls.texy +++ b/forms/de/controls.texy @@ -20,7 +20,7 @@ Es validiert automatisch UTF-8, schneidet linke und rechte Leerzeichen ab und en Die maximale Länge kann mit `setMaxLength()` begrenzt werden. Mit [addFilter() |validation#Modifying Input Values] können Sie den vom Benutzer eingegebenen Wert ändern. -Verwenden Sie `setHtmlType()`, um das [Zeichen |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] des Eingabeelements in `search`, `tel`, `url`, `range`, `date`, `datetime-local`, `month`, `time`, `week`, `color` zu ändern. Anstelle der Typen `number` und `email` empfehlen wir die Verwendung von [addInteger |#addInteger] und [addEmail |#addEmail], die eine serverseitige Validierung ermöglichen. +Sie können `setHtmlType()` verwenden, um das [Zeichen |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] des Eingabeelements in `search`, `tel`, `url`, `range`, `datetime-local`, `month`, `time`, `week`, `color` zu ändern. Anstelle der Typen `number` und `email` empfehlen wir die Verwendung von [addInteger |#addInteger], [addFloat |#addFloat] und [addEmail |#addEmail], die über eine serverseitige Validierung verfügen. ```php $form->addText('color', 'Choose color:') @@ -58,11 +58,24 @@ addInteger(string|int $name, $label=null): TextInput .[method] Fügt Eingabefeld für Ganzzahl (Klasse [TextInput |api:Nette\Forms\Controls\TextInput]) hinzu. Gibt entweder eine Ganzzahl oder `null` zurück, wenn der Benutzer nichts eingibt. ```php -$form->addInteger('level', 'Level:') +$form->addInteger('Jahr', 'Jahr:') + ->addRule($form::Range, 'Das Jahr muss im Bereich %d bis %d liegen.', [1900, 2023 |1900, 2023]); +``` + + +addFloat(string|int $name, $label=null): TextInput .[method]{data-version:3.1.12} +================================================================================= + +Adds a field for entering a decimal number ([TextInput |api:Nette\Forms\Controls\TextInput] class). Returns either float or `null`, if the user does not specify anything. + +```php +$form->addFloat('Ebene', 'Ebene:') ->setDefaultValue(0) - ->addRule($form::Range, 'Level must be between %d and %d.', [0, 100]); +->addRule($form::Range, 'Das Niveau muss im Bereich %d bis %d liegen.', [0, 100 |0, 100]); ``` +Nette und Chrome akzeptieren sowohl Komma als auch Punkt als Dezimaltrennzeichen. Damit Firefox auch ein Komma akzeptiert, müssen Sie die entsprechende Sprache im HTML-Attribut `lang` setzen, entweder direkt in diesem Element oder in einem übergeordneten Element, zum Beispiel ``. + addEmail(string|int $name, $label=null): TextInput .[method] ============================================================ diff --git a/forms/de/rendering.texy b/forms/de/rendering.texy index bbf6690248..6e17b34c4b 100644 --- a/forms/de/rendering.texy +++ b/forms/de/rendering.texy @@ -237,15 +237,15 @@ Sie brauchen den Block nur noch an einer Stelle zu importieren, nämlich am Anfa Besondere Fälle .[#toc-special-cases] ------------------------------------- -Wenn Sie nur den inneren Inhalt eines Formulars darstellen müssen, ohne `
` & `
` HTML-Tags, z. B. in einer AJAX-Anfrage, können Sie das Formular mit `{formContext} … {/formContext}` öffnen und schließen. Es funktioniert im logischen Sinne ähnlich wie `{form}`, hier erlaubt es Ihnen, andere Tags zu verwenden, um Formularelemente zu zeichnen, aber gleichzeitig zeichnet es nichts. +Wenn Sie nur den inneren Teil des Formulars ohne HTML-Tags darstellen wollen `
`darstellen wollen, z. B. beim Senden von Snippets, blenden Sie diese mit dem Attribut `n:tag-if` aus: ```latte -{formContext signForm} +
{inputError username}
-{/formContext} +
``` Das Tag `formContainer` hilft beim Rendern von Eingaben innerhalb eines Formular-Containers. diff --git a/forms/de/validation.texy b/forms/de/validation.texy index 29dd24e760..ea282ded2f 100644 --- a/forms/de/validation.texy +++ b/forms/de/validation.texy @@ -38,7 +38,7 @@ Wir können die folgenden Regeln für alle Steuerelemente verwenden: | `IsNotIn` | Wert ist nicht gleich einem Element im Array | `array` | `Valid` | Eingabe besteht Validierung (für [Bedingungen |#conditions]) | - -Für die Steuerelemente `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()` können auch die folgenden Regeln verwendet werden: +Für die Elemente `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` können auch einige der folgenden Regeln angewendet werden: | `MinLength` | minimale Stringlänge | `int` | `MaxLength` | maximale Länge der Zeichenkette | `int` diff --git a/forms/el/controls.texy b/forms/el/controls.texy index 978a60c42e..9da47861ef 100644 --- a/forms/el/controls.texy +++ b/forms/el/controls.texy @@ -20,7 +20,7 @@ $form->addText('name', 'Name:') Το μέγιστο μήκος μπορεί να περιοριστεί χρησιμοποιώντας το `setMaxLength()`. Η [addFilter() |validation#Modifying Input Values] σας επιτρέπει να αλλάξετε την τιμή που εισάγει ο χρήστης. -Χρησιμοποιήστε το `setHtmlType()` για να αλλάξετε τον [χαρακτήρα |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] του στοιχείου εισόδου σε `search`, `tel`, `url`, `range`, `date`, `datetime-local`, `month`, `time`, `week`, `color`. Αντί των τύπων `number` και `email`, συνιστούμε τη χρήση των τύπων [addInteger |#addInteger] και [addEmail |#addEmail], οι οποίοι παρέχουν επικύρωση από την πλευρά του διακομιστή. +Μπορείτε να χρησιμοποιήσετε το `setHtmlType()` για να αλλάξετε τον [χαρακτήρα |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] του στοιχείου εισόδου σε `search`, `tel`, `url`, `range`, `datetime-local`, `month`, `time`, `week`, `color`. Αντί των τύπων `number` και `email`, συνιστούμε να χρησιμοποιείτε τους τύπους [addInteger |#addInteger], [addFloat |#addFloat] και [addEmail |#addEmail], οι οποίοι διαθέτουν επικύρωση από την πλευρά του διακομιστή. ```php $form->addText('color', 'Choose color:') @@ -58,11 +58,24 @@ addInteger(string|int $name, $label=null): TextInput .[method] Προσθέτει πεδίο εισόδου για ακέραιο αριθμό (κλάση [TextInput |api:Nette\Forms\Controls\TextInput]). Επιστρέφει είτε έναν ακέραιο είτε το `null` εάν ο χρήστης δεν εισάγει τίποτα. ```php -$form->addInteger('level', 'Level:') +$form->addInteger('year', 'Year:') + ->addRule($form::Range, 'Το έτος πρέπει να βρίσκεται στο εύρος %d έως %d.', [1900, 2023 |1900, 2023]), +``` + + +addFloat(string|int $name, $label=null): TextInput .[method]{data-version:3.1.12} +================================================================================= + +Adds a field for entering a decimal number ([TextInput |api:Nette\Forms\Controls\TextInput] class). Returns either float or `null`, if the user does not specify anything. + +```php +$form->addFloat('level', 'Level:') ->setDefaultValue(0) - ->addRule($form::Range, 'Level must be between %d and %d.', [0, 100]); +->addRule($form::Range, 'Το επίπεδο πρέπει να είναι στο εύρος %d έως %d.', [0, 100 |0, 100]), ``` +Το Nette και το Chrome δέχονται τόσο το κόμμα όσο και την τελεία ως δεκαδικό διαχωριστικό. Για να δέχεται και ο Firefox το κόμμα, πρέπει να ορίσετε την αντίστοιχη γλώσσα στο χαρακτηριστικό HTML `lang`, είτε απευθείας σε αυτό το στοιχείο είτε σε οποιοδήποτε γονικό στοιχείο, για παράδειγμα ``. + addEmail(string|int $name, $label=null): TextInput .[method] ============================================================ diff --git a/forms/el/rendering.texy b/forms/el/rendering.texy index 169c07138f..ada1f1310e 100644 --- a/forms/el/rendering.texy +++ b/forms/el/rendering.texy @@ -237,15 +237,15 @@ protected function createComponentSignInForm(): Form Ειδικές περιπτώσεις .[#toc-special-cases] ----------------------------------------- -Αν χρειάζεται να αποδώσετε μόνο το εσωτερικό περιεχόμενο μιας φόρμας χωρίς `
` & `
` ετικέτες HTML, για παράδειγμα, σε μια αίτηση AJAX, μπορείτε να ανοίξετε και να κλείσετε τη φόρμα με το `{formContext} … {/formContext}`. Λειτουργεί παρόμοια με το `{form}` με μια λογική έννοια, εδώ σας επιτρέπει να χρησιμοποιήσετε άλλες ετικέτες για να σχεδιάσετε στοιχεία της φόρμας, αλλά ταυτόχρονα δεν σχεδιάζει τίποτα. +Αν θέλετε να αποδώσετε μόνο το εσωτερικό μέρος της φόρμας χωρίς ετικέτες HTML `
`, για παράδειγμα κατά την αποστολή αποσπασμάτων, αποκρύψτε τα χρησιμοποιώντας το χαρακτηριστικό `n:tag-if`: ```latte -{formContext signForm} +
{inputError username}
-{/formContext} +
``` Η ετικέτα `formContainer` βοηθά στην απόδοση των εισόδων μέσα σε ένα δοχείο φόρμας. diff --git a/forms/el/validation.texy b/forms/el/validation.texy index 0cee3fe0f0..cfb89effb6 100644 --- a/forms/el/validation.texy +++ b/forms/el/validation.texy @@ -38,7 +38,7 @@ $form->addPassword('password', 'Password:') | `IsNotIn` | η τιμή δεν είναι ίση με κάποιο στοιχείο του πίνακα | `array` | `Valid` | η είσοδος περνάει την επικύρωση (για τις [συνθήκες |#conditions]) | - -Για τα στοιχεία ελέγχου `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()` μπορούν επίσης να χρησιμοποιηθούν οι ακόλουθοι κανόνες: +Για τα στοιχεία `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` μπορούν επίσης να εφαρμοστούν ορισμένοι από τους ακόλουθους κανόνες: | `MinLength` | ελάχιστο μήκος συμβολοσειράς | `int` | `MaxLength` | μέγιστο μήκος συμβολοσειράς | `int` diff --git a/forms/en/controls.texy b/forms/en/controls.texy index 237761d601..dd1a9db0c9 100644 --- a/forms/en/controls.texy +++ b/forms/en/controls.texy @@ -20,7 +20,7 @@ It automatically validates UTF-8, trims left and right whitespaces, and removes The maximum length can be limited using `setMaxLength()`. The [addFilter()|validation#Modifying Input Values] allows you to change the user-entered value. -Use `setHtmlType()` to change the [character|https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] of input element to `search`, `tel`, `url`, `range`, `date`, `datetime-local`, `month`, `time`, `week`, `color`. Instead of the `number` and `email` types, we recommend using [#addInteger] and [#addEmail], which provide server-side validation. +You can use `setHtmlType()` to change the [character |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] of the input element to `search`, `tel`, `url`, `range`, `datetime-local`, `month`, `time`, `week`, `color`. Instead of the `number` and `email` types, we recommend using [addInteger |#addInteger], [addFloat |#addFloat] and [addEmail |#addEmail], which have server-side validation. ```php $form->addText('color', 'Choose color:') @@ -58,11 +58,24 @@ addInteger(string|int $name, $label=null): TextInput .[method] Adds input field for integer (class [TextInput |api:Nette\Forms\Controls\TextInput]). Returns either an integer or `null` if the user does not enter anything. ```php -$form->addInteger('level', 'Level:') +$form->addInteger('year', 'Year:') + ->addRule($form::Range, 'The year must be in the range %d to %d.', [1900, 2023]); +``` + + +addFloat(string|int $name, $label=null): TextInput .[method]{data-version:3.1.12} +================================================================================= + +Adds a field for entering a decimal number ([TextInput |api:Nette\Forms\Controls\TextInput] class). Returns either float or `null`, if the user does not specify anything. + +```php +$form->addFloat('level', 'Level:') ->setDefaultValue(0) - ->addRule($form::Range, 'Level must be between %d and %d.', [0, 100]); + ->addRule($form::Range, 'The level must be in the range %d to %d.', [0, 100]); ``` +Nette and Chrome accept both comma and period as decimal separator. For Firefox to also accept a comma, you need to set the corresponding language in the HTML attribute `lang`, either directly to this element or to any parent element, for example ``. + addEmail(string|int $name, $label=null): TextInput .[method] ============================================================ diff --git a/forms/en/rendering.texy b/forms/en/rendering.texy index 04d433baf8..f9eb21279b 100644 --- a/forms/en/rendering.texy +++ b/forms/en/rendering.texy @@ -237,15 +237,15 @@ You only need to import the block in one place, at the beginning of the layout t Special Cases ------------- -If you only need to render the inner content of a form without `
` & `
` HTML tags, for example, in an AJAX request, you can open and close the form with `{formContext} … {/formContext}`. It works similarly to `{form}` in a logical sense, here it allows you to use other tags to draw form elements, but at the same time it doesn't draw anything. +If you need to render only the inner part of the form without HTML tags `
`, for example when sending snippets, hide them using the `n:tag-if` attribute: ```latte -{formContext signForm} +
{inputError username}
-{/formContext} +
``` Tag `formContainer` helps with rendering of inputs inside a form container. diff --git a/forms/en/validation.texy b/forms/en/validation.texy index 18db69d0e0..58db4d7535 100644 --- a/forms/en/validation.texy +++ b/forms/en/validation.texy @@ -38,7 +38,7 @@ We can use the following rules for all controls: | `IsNotIn` | value does not equal any element in the array | `array` | `Valid` | input passes validation (for [#conditions]) | - -For controls `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()` the following rules can also be used: +For elements `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` some of the following rules can also be applied: | `MinLength` | minimal string length | `int` | `MaxLength` | maximal string length | `int` diff --git a/forms/es/controls.texy b/forms/es/controls.texy index a1ee2d5426..9ea4d7241b 100644 --- a/forms/es/controls.texy +++ b/forms/es/controls.texy @@ -20,7 +20,7 @@ Valida automáticamente UTF-8, recorta los espacios en blanco a izquierda y dere La longitud máxima puede limitarse mediante `setMaxLength()`. La [función addFilter() |validation#Modifying Input Values] permite cambiar el valor introducido por el usuario. -Utilice `setHtmlType()` para cambiar el [carácter |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] del elemento de entrada a `search`, `tel`, `url`, `range`, `date`, `datetime-local`, `month`, `time`, `week`, `color`. En lugar de los tipos `number` y `email`, recomendamos utilizar [addInteger |#addInteger] y [addEmail |#addEmail], que proporcionan validación del lado del servidor. +Puede utilizar `setHtmlType()` para cambiar el [carácter |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] del elemento de entrada a `search`, `tel`, `url`, `range`, `datetime-local`, `month`, `time`, `week`, `color`. En lugar de los tipos `number` y `email`, recomendamos utilizar [addInteger |#addInteger], [addFloat |#addFloat] y [addEmail |#addEmail], que tienen validación del lado del servidor. ```php $form->addText('color', 'Elige color:') @@ -58,11 +58,24 @@ addInteger(string|int $name, $label=null): TextInput .[method] Añade un campo de entrada para números enteros (clase [TextInput |api:Nette\Forms\Controls\TextInput]). Devuelve un entero o `null` si el usuario no introduce nada. ```php -$form->addInteger('level', 'Nivel:') +$form->addInteger('año', 'Año:') + ->addRule($form::Range, 'El año debe estar en el rango %d a %d.', [1900, 2023 |1900, 2023]); +``` + + +addFloat(string|int $name, $label=null): TextInput .[method]{data-version:3.1.12} +================================================================================= + +Adds a field for entering a decimal number ([TextInput |api:Nette\Forms\Controls\TextInput] class). Returns either float or `null`, if the user does not specify anything. + +```php +$form->addFloat('nivel', 'Nivel:') ->setDefaultValue(0) - ->addRule($form::Range, 'El nivel debe estar entre %d y %d.', [0, 100]); +->addRule($form::Range, 'El nivel debe estar en el rango %d a %d.', [0, 100 |0, 100]); ``` +Nette y Chrome aceptan tanto la coma como el punto como separador decimal. Para que Firefox también acepte una coma, es necesario establecer el idioma correspondiente en el atributo HTML `lang`, ya sea directamente en este elemento o en cualquier elemento padre, por ejemplo ``. + addEmail(string|int $name, $label=null): TextInput .[method] ============================================================ diff --git a/forms/es/rendering.texy b/forms/es/rendering.texy index 2039385434..41e2d20681 100644 --- a/forms/es/rendering.texy +++ b/forms/es/rendering.texy @@ -237,15 +237,15 @@ Sólo tendrá que importar el bloque en un lugar, al principio de la plantilla d Casos especiales .[#toc-special-cases] -------------------------------------- -Si sólo necesita renderizar el contenido interno de un formulario sin `
` & `
` por ejemplo, en una petición AJAX, puedes abrir y cerrar el formulario con `{formContext} … {/formContext}`. Funciona de forma similar a `{form}` en un sentido lógico, aquí te permite usar otras etiquetas para dibujar elementos del formulario, pero al mismo tiempo no dibuja nada. +Si necesita mostrar sólo la parte interior del formulario sin etiquetas HTML `
`por ejemplo, al enviar fragmentos, ocúltelos con el atributo `n:tag-if`: ```latte -{formContext signForm} +
{inputError username}
-{/formContext} +
``` La etiqueta `formContainer` ayuda con la representación de entradas dentro de un contenedor de formulario. diff --git a/forms/es/validation.texy b/forms/es/validation.texy index 9b7e35bc31..dee7fac958 100644 --- a/forms/es/validation.texy +++ b/forms/es/validation.texy @@ -38,7 +38,7 @@ Podemos utilizar las siguientes reglas para todos los controles: | `IsNotIn` | El valor no es igual a ningún elemento de la matriz. `array` | `Valid` | la entrada pasa la validación (para [condiciones |#conditions]) | - -Para los controles `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()` también se pueden utilizar las siguientes reglas: +Para los elementos `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` también se pueden aplicar algunas de las siguientes reglas: | `MinLength` | longitud mínima de cadena | `int` | `MaxLength` | longitud máxima de cadena | `int` diff --git a/forms/fr/controls.texy b/forms/fr/controls.texy index 89528a8818..81e0fba99d 100644 --- a/forms/fr/controls.texy +++ b/forms/fr/controls.texy @@ -20,7 +20,7 @@ Il valide automatiquement l'UTF-8, coupe les espaces à gauche et à droite et s La longueur maximale peut être limitée en utilisant `setMaxLength()`. La [fonction addFilter() |validation#Modifying Input Values] permet de modifier la valeur saisie par l'utilisateur. -Utilisez `setHtmlType()` pour changer le [caractère |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] de l'élément d'entrée en `search`, `tel`, `url`, `range`, `date`, `datetime-local`, `month`, `time`, `week`, `color`. Au lieu des types `number` et `email`, nous vous recommandons d'utiliser [addInteger |#addInteger] et [addEmail |#addEmail], qui fournissent une validation côté serveur. +Vous pouvez utiliser `setHtmlType()` pour changer le [caractère de |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] l'élément d'entrée en `search`, `tel`, `url`, `range`, `datetime-local`, `month`, `time`, `week`, `color`. Au lieu des types `number` et `email`, nous vous recommandons d'utiliser [addInteger |#addInteger], [addFloat |#addFloat] et [addEmail |#addEmail], qui ont une validation côté serveur. ```php $form->addText('color', 'Choose color:') @@ -58,11 +58,24 @@ addInteger(string|int $name, $label=null): TextInput .[method] Ajoute un champ de saisie pour un nombre entier (classe [TextInput |api:Nette\Forms\Controls\TextInput]). Renvoie soit un entier, soit `null` si l'utilisateur ne saisit rien. ```php -$form->addInteger('level', 'Level:') +$form->addInteger('year', 'Year:') + ->addRule($form::Range, 'L'année doit être comprise entre %d et %d.', [1900, 2023 |1900, 2023]) ; +``` + + +addFloat(string|int $name, $label=null): TextInput .[method]{data-version:3.1.12} +================================================================================= + +Adds a field for entering a decimal number ([TextInput |api:Nette\Forms\Controls\TextInput] class). Returns either float or `null`, if the user does not specify anything. + +```php +$form->addFloat('niveau', 'Niveau:') ->setDefaultValue(0) - ->addRule($form::Range, 'Level must be between %d and %d.', [0, 100]); +->addRule($form::Range, 'Le niveau doit être compris entre %d et %d.', [0, 100 |0, 100]) ; ``` +Nette et Chrome acceptent à la fois la virgule et le point comme séparateur décimal. Pour que Firefox accepte également la virgule, vous devez définir la langue correspondante dans l'attribut HTML `lang`, soit directement dans cet élément, soit dans un élément parent, par exemple ``. + addEmail(string|int $name, $label=null): TextInput .[method] ============================================================ diff --git a/forms/fr/rendering.texy b/forms/fr/rendering.texy index 5aaa56466a..63b89b61ec 100644 --- a/forms/fr/rendering.texy +++ b/forms/fr/rendering.texy @@ -237,15 +237,15 @@ Vous ne devez importer le bloc qu'à un seul endroit, au début du modèle de mi Cas particuliers .[#toc-special-cases] -------------------------------------- -Si vous avez seulement besoin de rendre le contenu interne d'un formulaire sans `
` & `
` HTML, par exemple dans une requête AJAX, vous pouvez ouvrir et fermer le formulaire à l'aide de `{formContext} … {/formContext}`. Son fonctionnement est similaire à celui de `{form}` d'un point de vue logique, puisqu'il vous permet d'utiliser d'autres balises pour dessiner des éléments de formulaire, mais en même temps, il ne dessine rien. +Si vous devez rendre uniquement la partie intérieure du formulaire sans balises HTML, par exemple lors de l'envoi d'extraits, masquez-les à l'aide de l'attribut . `
`par exemple lors de l'envoi d'extraits, masquez-les à l'aide de l'attribut `n:tag-if`: ```latte -{formContext signForm} +
{inputError username}
-{/formContext} +
``` La balise `formContainer` aide à rendre les entrées à l'intérieur d'un conteneur de formulaire. diff --git a/forms/fr/validation.texy b/forms/fr/validation.texy index 361456d8c7..3ba5a0e0cf 100644 --- a/forms/fr/validation.texy +++ b/forms/fr/validation.texy @@ -38,7 +38,7 @@ Nous pouvons utiliser les règles suivantes pour tous les contrôles : | `IsNotIn` | la valeur n'est égale à aucun élément du tableau | `array` | `Valid` | L'entrée passe la validation (pour les [conditions |#conditions]) | - -Pour les contrôles `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()` les règles suivantes peuvent également être utilisées : +Pour les éléments `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()`, certaines des règles suivantes peuvent également être appliquées : | `MinLength` | longueur minimale de la chaîne | `int` | `MaxLength` | longueur maximale de la chaîne de caractères | `int` diff --git a/forms/hu/controls.texy b/forms/hu/controls.texy index 8c00e73adc..624c32fdac 100644 --- a/forms/hu/controls.texy +++ b/forms/hu/controls.texy @@ -20,7 +20,7 @@ Automatikusan érvényesíti az UTF-8 szabványt, levágja a bal és jobb oldali A maximális hossz a `setMaxLength()` segítségével korlátozható. Az [addFilter() |validation#Modifying Input Values] lehetővé teszi a felhasználó által megadott érték megváltoztatását. -A `setHtmlType()` segítségével a `search`, `tel`, `url`, `range`, `date`, `datetime-local`, `month`, `time`, `week`, `color` beviteli elem [karakterét |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] módosíthatja. A `number` és `email` típusok helyett az [addInteger |#addInteger] és az [addEmail |#addEmail] típusok használatát javasoljuk, amelyek szerveroldali érvényesítést biztosítanak. +A `setHtmlType()` segítségével a bemeneti elem [karakterét |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] megváltoztathatja `search`, `tel`, `url`, `range`, `datetime-local`, `month`, `time`, `week`, `color`. A `number` és `email` típusok helyett az [addInteger |#addInteger], [addFloat |#addFloat] és [addEmail |#addEmail] típusok használatát javasoljuk, amelyek szerveroldali érvényesítéssel rendelkeznek. ```php $form->addText('color', 'Choose color:') @@ -58,11 +58,24 @@ addInteger(string|int $name, $label=null): TextInput .[method] Egész számok beviteli mezőjének hozzáadása ( [TextInput |api:Nette\Forms\Controls\TextInput] osztály). Egész számot vagy a `null` értéket adja vissza, ha a felhasználó nem ad meg semmit. ```php -$form->addInteger('level', 'Level:') +$form->addInteger('year', 'Év:') + ->addRule($form::Range, 'Az évnek a %d és %d közötti tartományban kell lennie.', [1900, 2023 |1900, 2023]); +``` + + +addFloat(string|int $name, $label=null): TextInput .[method]{data-version:3.1.12} +================================================================================= + +Adds a field for entering a decimal number ([TextInput |api:Nette\Forms\Controls\TextInput] class). Returns either float or `null`, if the user does not specify anything. + +```php +$form->addFloat('szint', 'Szint:') ->setDefaultValue(0) - ->addRule($form::Range, 'Level must be between %d and %d.', [0, 100]); +->addRule($form::Range, 'A szintnek a %d és %d közötti tartományban kell lennie.', [0, 100 |0, 100]); ``` +A Nette és a Chrome elfogadja a vesszőt és a pontot is tizedesválasztóként. Ahhoz, hogy a Firefox is elfogadja a vesszőt, be kell állítania a megfelelő nyelvet a `lang` HTML-attribútumban, vagy közvetlenül ehhez az elemhez, vagy bármelyik szülőelemhez, pl. ``. + addEmail(string|int $name, $label=null): TextInput .[method] ============================================================ diff --git a/forms/hu/rendering.texy b/forms/hu/rendering.texy index 783a433b2a..5b81534c50 100644 --- a/forms/hu/rendering.texy +++ b/forms/hu/rendering.texy @@ -237,15 +237,15 @@ A blokkot csak egy helyre kell importálnia, az elrendezési sablon elejére: Speciális esetek .[#toc-special-cases] -------------------------------------- -Ha csak egy űrlap belső tartalmát kell megjelenítenie anélkül, hogy a `
` & `
` HTML-címkéket, például egy AJAX-kérés során, akkor a `{formContext} … {/formContext}` segítségével nyithatja meg és zárhatja be az űrlapot. Logikai értelemben hasonlóan működik, mint a `{form}`, itt lehetővé teszi, hogy más címkéket használjon az űrlapelemek megrajzolásához, ugyanakkor nem rajzol semmit. +Ha csak az űrlap belső részét kell megjelenítenie HTML címkék nélkül `
`, például a snippetek elküldésekor, rejtse el őket a `n:tag-if` attribútummal: ```latte -{formContext signForm} +
{inputError username}
-{/formContext} +
``` A `formContainer` címke az űrlapkonténeren belüli bemenetek megjelenítését segíti. diff --git a/forms/hu/validation.texy b/forms/hu/validation.texy index c75844fbdb..30b92e0171 100644 --- a/forms/hu/validation.texy +++ b/forms/hu/validation.texy @@ -38,7 +38,7 @@ A következő szabályokat használhatjuk az összes vezérlőelemhez: | `IsNotIn` | érték nem egyenlő a tömb egyetlen elemével sem | `array` | `Valid` | a bemenet átmegy az érvényesítésen ( [feltételek |#conditions] esetén) | - -A `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()` vezérlőkhöz a következő szabályok is használhatók: +A `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` elemekre a következő szabályok közül néhányat is lehet alkalmazni: | `MinLength` | minimális karakterlánc-hossz | `int` | `MaxLength` | maximális karakterlánc-hossz | `int` diff --git a/forms/it/controls.texy b/forms/it/controls.texy index a8bd71747e..8664dfb24a 100644 --- a/forms/it/controls.texy +++ b/forms/it/controls.texy @@ -20,7 +20,7 @@ Convalida automaticamente UTF-8, taglia gli spazi bianchi a destra e a sinistra La lunghezza massima può essere limitata utilizzando `setMaxLength()`. Il metodo [addFilter() |validation#Modifying Input Values] consente di modificare il valore inserito dall'utente. -Utilizzare `setHtmlType()` per cambiare il [carattere |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] dell'elemento di input in `search`, `tel`, `url`, `range`, `date`, `datetime-local`, `month`, `time`, `week`, `color`. Al posto dei tipi `number` e `email`, si consiglia di usare [addInteger |#addInteger] e [addEmail |#addEmail], che forniscono una validazione lato server. +Si può usare `setHtmlType()` per cambiare il [carattere |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] dell'elemento di input in `search`, `tel`, `url`, `range`, `datetime-local`, `month`, `time`, `week`, `color`. Al posto dei tipi `number` e `email`, si consiglia di usare [addInteger |#addInteger], [addFloat |#addFloat] e [addEmail |#addEmail], che hanno una validazione lato server. ```php $form->addText('color', 'Choose color:') @@ -58,11 +58,24 @@ addInteger(string|int $name, $label=null): TextInput .[method] Aggiunge un campo di input per numeri interi (classe [TextInput |api:Nette\Forms\Controls\TextInput]). Restituisce un intero o `null` se l'utente non inserisce nulla. ```php -$form->addInteger('level', 'Level:') +$form->addInteger('anno', 'Anno:') + ->addRule($form::Range, 'L'anno deve essere compreso tra %d e %d.', [1900, 2023 |1900, 2023]); +``` + + +addFloat(string|int $name, $label=null): TextInput .[method]{data-version:3.1.12} +================================================================================= + +Adds a field for entering a decimal number ([TextInput |api:Nette\Forms\Controls\TextInput] class). Returns either float or `null`, if the user does not specify anything. + +```php +$form->addFloat('level', 'Level:') ->setDefaultValue(0) - ->addRule($form::Range, 'Level must be between %d and %d.', [0, 100]); +->addRule($form::Range, 'Il livello deve essere compreso tra %d e %d', [0, 100 |0, 100]); ``` +Nette e Chrome accettano sia la virgola che il punto come separatore decimale. Affinché anche Firefox accetti la virgola, è necessario impostare la lingua corrispondente nell'attributo HTML `lang`, direttamente a questo elemento o a qualsiasi elemento padre, ad esempio ``. + addEmail(string|int $name, $label=null): TextInput .[method] ============================================================ diff --git a/forms/it/rendering.texy b/forms/it/rendering.texy index a3b9c9036b..4b009461dc 100644 --- a/forms/it/rendering.texy +++ b/forms/it/rendering.texy @@ -237,15 +237,15 @@ In questo modo sarà un po' più facile da usare: Casi speciali .[#toc-special-cases] ----------------------------------- -Se si ha bisogno di rendere solo il contenuto interno di un modulo senza `
` & `
` HTML, ad esempio in una richiesta AJAX, si può aprire e chiudere il modulo con `{formContext} … {/formContext}`. Funziona in modo simile a `{form}` in senso logico, ma permette di usare altri tag per disegnare gli elementi del modulo, ma allo stesso tempo non disegna nulla. +Se si ha bisogno di rendere solo la parte interna del modulo senza tag HTML `
`ad esempio per l'invio di snippet, è possibile nasconderli utilizzando l'attributo `n:tag-if`: ```latte -{formContext signForm} +
{inputError username}
-{/formContext} +
``` Il tag `formContainer` aiuta a rendere gli input all'interno di un contenitore di form. diff --git a/forms/it/validation.texy b/forms/it/validation.texy index 1602645bce..7de87fa18d 100644 --- a/forms/it/validation.texy +++ b/forms/it/validation.texy @@ -38,7 +38,7 @@ Possiamo utilizzare le seguenti regole per tutti i controlli: | `IsNotIn` | il valore non è uguale a nessun elemento dell'array | `array` | `Valid` | l'input supera la convalida (per le [condizioni |#conditions]) | - -Per i controlli `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()` possono essere utilizzate anche le seguenti regole: +Per gli elementi `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` si possono applicare anche alcune delle seguenti regole: | `MinLength` | lunghezza minima della stringa | `int` | `MaxLength` | lunghezza massima della stringa | `int` diff --git a/forms/pl/controls.texy b/forms/pl/controls.texy index 397c90cc97..4122784d06 100644 --- a/forms/pl/controls.texy +++ b/forms/pl/controls.texy @@ -20,7 +20,7 @@ Automatycznie waliduje UTF-8, obcina lewe i prawe spacje oraz usuwa przerwy w li Maksymalna długość może być ograniczona za pomocą `setMaxLength()`. Modyfikacja wartości wprowadzonej przez użytkownika umożliwia [addFilter() |validation#Modifying-Input-Values]. -Używając `setHtmlType()`, [charakter |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] elementu wejściowego można zmienić na `search`, `tel`, `url`, `range`, `date`, `datetime-local`, `month`, `time`, `week`, `color`. Zalecamy użycie [addInteger |#addInteger] i [addEmail |#addEmail] zamiast typów `number` i `email`, które mają walidację po stronie serwera. +Możesz użyć `setHtmlType()`, aby zmienić [znak |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] elementu wejściowego na `search`, `tel`, `url`, `range`, `datetime-local`, `month`, `time`, `week`, `color`. Zamiast typów `number` i `email` zalecamy użycie [addInteger |#addInteger], [addFloat |#addFloat] i [addEmail |#addEmail], które mają walidację po stronie serwera. ```php $form->addText('color', 'Vyberte barvu:') @@ -58,11 +58,24 @@ addInteger(string|int $name, $label=null): TextInput .[method] Dodaje pole do wprowadzania liczby całkowitej (klasa [TextInput |api:Nette\Forms\Controls\TextInput]). Zwraca liczbę całkowitą lub `null`, jeśli użytkownik nic nie wprowadzi. ```php -$form->addInteger('level', 'Úroveň:') +$form->addInteger('year', 'Year:') + ->addRule($form::Range, 'Rok musi być z zakresu %d do %d.', [1900, 2023 |1900, 2023]); +``` + + +addFloat(string|int $name, $label=null): TextInput .[method]{data-version:3.1.12} +================================================================================= + +Adds a field for entering a decimal number ([TextInput |api:Nette\Forms\Controls\TextInput] class). Returns either float or `null`, if the user does not specify anything. + +```php +$form->addFloat('level', 'Level:') ->setDefaultValue(0) - ->addRule($form::Range, 'Úroveň musí být v rozsahu mezi %d a %d.', [0, 100]); +->addRule($form::Range, 'The level must be in the range %d to %d.', [0, 100 |0, 100]); ``` +Nette i Chrome akceptują zarówno przecinek, jak i kropkę jako separator dziesiętny. Aby Firefox również akceptował przecinek, należy ustawić odpowiedni język w atrybucie HTML `lang`, bezpośrednio w tym elemencie lub w dowolnym elemencie nadrzędnym, na przykład ``. + addEmail(string|int $name, $label=null): TextInput .[method] ============================================================ diff --git a/forms/pl/rendering.texy b/forms/pl/rendering.texy index fc31847b7e..9d0e2fa99f 100644 --- a/forms/pl/rendering.texy +++ b/forms/pl/rendering.texy @@ -237,15 +237,15 @@ Blok wystarczy zaimportować tylko w jednym miejscu, na początku szablonu ukła Szczególne przypadki .[#toc-special-cases] ------------------------------------------ -Jeśli chcesz wyrenderować tylko wewnętrzną część formularza bez znaczników HTML `
` & `
`, na przykład w żądaniu AJAX, możesz otworzyć i zamknąć formularz na `{formContext} … {/formContext}`. Działa to podobnie do `
` lub `{form}` w sensie logicznym, tutaj pozwoli Ci użyć innych znaczników do rysowania elementów formularza, ale jednocześnie nie rysuje niczego. +Jeśli chcesz renderować tylko wewnętrzną część formularza bez znaczników HTML ``na przykład podczas wysyłania fragmentów, ukryj je za pomocą atrybutu `n:tag-if`: ```latte -{formContext signForm} +
{inputError username}
-{/formContext} +
``` Znacznik `{formContainer}` pomoże w rysowaniu elementów wewnątrz kontenera formularza. diff --git a/forms/pl/validation.texy b/forms/pl/validation.texy index 75e7c62d54..1c04ec9a97 100644 --- a/forms/pl/validation.texy +++ b/forms/pl/validation.texy @@ -38,7 +38,7 @@ Zasady te możemy stosować dla wszystkich elementów: | `IsNotIn` | wartość nie jest równa żadnej pozycji w tablicy |. `array` | `Valid` | czy element został wypełniony poprawnie? (dla [warunków |#Conditions]) | - -Poniższe reguły mogą być również stosowane dla elementów `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`: +W przypadku elementów `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` można również zastosować niektóre z poniższych reguł: | `MinLength` | minimalna długość tekstu | `int` | `MaxLength` | maksymalna długość tekstu | `int` diff --git a/forms/pt/controls.texy b/forms/pt/controls.texy index 9dcebf3609..5f26051d84 100644 --- a/forms/pt/controls.texy +++ b/forms/pt/controls.texy @@ -20,7 +20,7 @@ Ela valida automaticamente UTF-8, apara os espaços em branco à esquerda e à d O comprimento máximo pode ser limitado usando `setMaxLength()`. O [addFilter() |validation#Modifying Input Values] permite alterar o valor inserido pelo usuário. -Use `setHtmlType()` para mudar o [caráter |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] do elemento de entrada para `search`, `tel`, `url`, `range`, `date`, `datetime-local`, `month`, `time`, `week`, `color`. Em vez dos tipos `number` e `email`, recomendamos usar [addInteger |#addInteger] e [addEmail |#addEmail], que fornecem validação do lado do servidor. +Você pode usar `setHtmlType()` para alterar o [caractere |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] do elemento de entrada para `search`, `tel`, `url`, `range`, `datetime-local`, `month`, `time`, `week`, `color`. Em vez dos tipos `number` e `email`, recomendamos o uso de [addInteger |#addInteger], [addFloat |#addFloat] e [addEmail |#addEmail], que têm validação no lado do servidor. ```php $form->addText('color', 'Choose color:') @@ -58,11 +58,24 @@ addInteger(string|int $name, $label=null): TextInput .[method] Adiciona campo de entrada para o número inteiro (classe [TextInput |api:Nette\Forms\Controls\TextInput]). Retorna ou um número inteiro ou `null` se o usuário não inserir nada. ```php -$form->addInteger('level', 'Level:') +$form->addInteger('year', 'Year:') + ->addRule($form::Range, 'O ano deve estar no intervalo de %d a %d.', [1900, 2023 |1900, 2023]); +``` + + +addFloat(string|int $name, $label=null): TextInput .[method]{data-version:3.1.12} +================================================================================= + +Adds a field for entering a decimal number ([TextInput |api:Nette\Forms\Controls\TextInput] class). Returns either float or `null`, if the user does not specify anything. + +```php +$form->addFloat('level', 'Level:') ->setDefaultValue(0) - ->addRule($form::Range, 'Level must be between %d and %d.', [0, 100]); +->addRule($form::Range, 'O nível deve estar no intervalo de %d a %d.', [0, 100 |0, 100]); ``` +O Nette e o Chrome aceitam a vírgula e o ponto como separadores decimais. Para que o Firefox também aceite uma vírgula, você precisa definir o idioma correspondente no atributo HTML `lang`, diretamente neste elemento ou em qualquer elemento pai, por exemplo ``. + addEmail(string|int $name, $label=null): TextInput .[method] ============================================================ diff --git a/forms/pt/rendering.texy b/forms/pt/rendering.texy index 11f39bb0d2..6b3ce19566 100644 --- a/forms/pt/rendering.texy +++ b/forms/pt/rendering.texy @@ -237,15 +237,15 @@ Você só precisa importar o bloco em um lugar, no início do modelo de layout: Casos especiais .[#toc-special-cases] ------------------------------------- -Se você precisar apenas renderizar o conteúdo interno de uma forma sem `
` & `
` Tags HTML, por exemplo, em um pedido AJAX, você pode abrir e fechar o formulário com `{formContext} … {/formContext}`. Funciona de forma similar a `{form}` em um sentido lógico, aqui permite que você use outras tags para desenhar elementos do formulário, mas ao mesmo tempo não desenha nada. +Se você precisar renderizar somente a parte interna do formulário sem tags HTML `
`por exemplo, ao enviar snippets, oculte-os usando o atributo `n:tag-if`: ```latte -{formContext signForm} +
{inputError username}
-{/formContext} +
``` A etiqueta `formContainer` ajuda na renderização de entradas dentro de um contêiner de formulário. diff --git a/forms/pt/validation.texy b/forms/pt/validation.texy index fe1ab31f0d..ab9e50be73 100644 --- a/forms/pt/validation.texy +++ b/forms/pt/validation.texy @@ -38,7 +38,7 @@ Podemos utilizar as seguintes regras para todos os controles: | `IsNotIn` | valor não é igual a nenhum elemento da matriz | `array` | `Valid` | validação dos passes de entrada (para [condições |#conditions]) | - -Para os controles `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()` também podem ser usadas as seguintes regras: +Para os elementos `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()`, algumas das regras a seguir também podem ser aplicadas: | `MinLength` | comprimento mínimo das cordas | `int` | `MaxLength` | comprimento máximo das cordas | `int` diff --git a/forms/ro/controls.texy b/forms/ro/controls.texy index e099cf0568..9c3dca2fe9 100644 --- a/forms/ro/controls.texy +++ b/forms/ro/controls.texy @@ -20,7 +20,7 @@ Validează automat UTF-8, taie spațiile albe din stânga și din dreapta și el Lungimea maximă poate fi limitată folosind `setMaxLength()`. [AddFilter() |validation#Modifying Input Values] vă permite să modificați valoarea introdusă de utilizator. -Utilizați `setHtmlType()` pentru a schimba [caracterul |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] elementului de intrare în `search`, `tel`, `url`, `range`, `date`, `datetime-local`, `month`, `time`, `week`, `color`. În locul tipurilor `number` și `email`, vă recomandăm să utilizați [addInteger |#addInteger] și [addEmail |#addEmail], care oferă validare pe server. +Puteți utiliza `setHtmlType()` pentru a schimba [caracterul |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] elementului de intrare în `search`, `tel`, `url`, `range`, , `datetime-local`, `month`, `time`, `week`, `color`. În locul tipurilor `number` și `email`, vă recomandăm să utilizați [addInteger |#addInteger], [addFloat |#addFloat] și [addEmail |#addEmail], care au validare pe server. ```php $form->addText('color', 'Choose color:') @@ -58,11 +58,24 @@ addInteger(string|int $name, $label=null): TextInput .[method] Adaugă un câmp de intrare pentru numere întregi (clasa [TextInput |api:Nette\Forms\Controls\TextInput]). Returnează fie un număr întreg, fie `null` dacă utilizatorul nu introduce nimic. ```php -$form->addInteger('level', 'Level:') +$form->addInteger('an', 'Anul:') + ->addRule($form::Range, 'Anul trebuie să fie cuprins între %d și %d.', [1900, 2023 |1900, 2023]); +``` + + +addFloat(string|int $name, $label=null): TextInput .[method]{data-version:3.1.12} +================================================================================= + +Adds a field for entering a decimal number ([TextInput |api:Nette\Forms\Controls\TextInput] class). Returns either float or `null`, if the user does not specify anything. + +```php +$form->addFloat('level', 'Level:') ->setDefaultValue(0) - ->addRule($form::Range, 'Level must be between %d and %d.', [0, 100]); +->addRule($form::Range, 'Nivelul trebuie să fie cuprins între %d și %d.', [0, 100 |0, 100]); ``` +Nette și Chrome acceptă atât virgula, cât și punctul ca separator zecimal. Pentru ca Firefox să accepte și virgula, trebuie să setați limba corespunzătoare în atributul HTML `lang`, fie direct la acest element, fie la orice element părinte, de exemplu ``. + addEmail(string|int $name, $label=null): TextInput .[method] ============================================================ diff --git a/forms/ro/rendering.texy b/forms/ro/rendering.texy index 0e72098c3c..18eac08c3c 100644 --- a/forms/ro/rendering.texy +++ b/forms/ro/rendering.texy @@ -237,15 +237,15 @@ Trebuie doar să importați blocul într-un singur loc, la începutul modelului Cazuri speciale .[#toc-special-cases] ------------------------------------- -Dacă aveți nevoie doar de redarea conținutului interior al unui formular fără `
` & `
` HTML, de exemplu, într-o solicitare AJAX, puteți deschide și închide formularul cu `{formContext} … {/formContext}`. Funcționează similar cu `{form}` în sens logic, aici vă permite să utilizați alte etichete pentru a desena elementele formularului, dar în același timp nu desenează nimic. +Dacă aveți nevoie să redați doar partea interioară a formularului fără etichete HTML `
`de exemplu, atunci când trimiteți fragmente, ascundeți-le folosind atributul `n:tag-if`: ```latte -{formContext signForm} +
{inputError username}
-{/formContext} +
``` Tag-ul `formContainer` ajută la redarea intrărilor în interiorul unui container de formular. diff --git a/forms/ro/validation.texy b/forms/ro/validation.texy index 87d26482db..b40fd76d8e 100644 --- a/forms/ro/validation.texy +++ b/forms/ro/validation.texy @@ -38,7 +38,7 @@ Putem utiliza următoarele reguli pentru toate controalele: | `IsNotIn` | valoarea nu este egală cu nici un element din matrice | `array` | `Valid` | input passes validation (for [conditions |#conditions]) | - -Pentru controalele `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()` se pot utiliza, de asemenea, următoarele reguli: +Pentru elementele `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` se pot aplica, de asemenea, unele dintre următoarele reguli: | `MinLength` | lungime minimă a șirului de caractere | `int` | `MaxLength` | lungime maximă a șirului de caractere | `int` diff --git a/forms/ru/controls.texy b/forms/ru/controls.texy index 00e30764f1..d2efd260ae 100644 --- a/forms/ru/controls.texy +++ b/forms/ru/controls.texy @@ -20,7 +20,7 @@ $form->addText('name', 'Имя:') Максимальная длина может быть ограничена с помощью `setMaxLength()`. Функция [addFilter()|validation#Modifying-Input-Values] позволяет изменить введенное пользователем значение. -Используйте `setHtmlType()` для изменения [типа|https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] элемента ввода на `search`, `tel`, `url`, `range`, `date`, `datetime-local`, `month`, `time`, `week`, `color`. Вместо типов `number` и `email` мы рекомендуем использовать [#addInteger] и [#addEmail], которые обеспечивают валидацию на стороне сервера. +С помощью `setHtmlType()` можно изменить [символ |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] элемента ввода на `search`, `tel`, `url`, `range`, `datetime-local`, `month`, `time`, `week`, `color`. Вместо типов `number` и `email` рекомендуется использовать [addInteger |#addInteger], [addFloat |#addFloat] и [addEmail |#addEmail], которые имеют валидацию на стороне сервера. ```php $form->addText('color', 'Выберите цвет:') @@ -58,11 +58,24 @@ addInteger(string|int $name, $label=null): TextInput .[method] Добавляет поле ввода для целого числа (класс [TextInput |api:Nette\Forms\Controls\TextInput]). Возвращает либо целое число, либо `null`, если пользователь ничего не ввел. ```php -$form->addInteger('level', 'Уровень:') +$form->addInteger('year', 'Year:') + ->addRule($form::Range, 'Год должен быть в диапазоне от %d до %d.', [1900, 2023 |1900, 2023]); +``` + + +addFloat(string|int $name, $label=null): TextInput .[method]{data-version:3.1.12} +================================================================================= + +Adds a field for entering a decimal number ([TextInput |api:Nette\Forms\Controls\TextInput] class). Returns either float or `null`, if the user does not specify anything. + +```php +$form->addFloat('level', 'Level:') ->setDefaultValue(0) - ->addRule($form::Range, 'Уровень должен быть между %d и %d.', [0, 100]); +->addRule($form::Range, 'Уровень должен находиться в диапазоне от %d до %d.', [0, 100 |0, 100]); ``` +Nette и Chrome принимают в качестве десятичного разделителя как запятую, так и точку. Для того чтобы Firefox также воспринимал запятую, необходимо задать соответствующий язык в HTML-атрибуте `lang`, либо непосредственно этому элементу, либо какому-либо родительскому элементу, например ``. + addEmail(string|int $name, $label=null): TextInput .[method] ============================================================ diff --git a/forms/ru/rendering.texy b/forms/ru/rendering.texy index 5abe127075..1d7ae11cc4 100644 --- a/forms/ru/rendering.texy +++ b/forms/ru/rendering.texy @@ -237,15 +237,15 @@ protected function createComponentSignInForm(): Form Особые случаи .[#toc-special-cases] ----------------------------------- -Если вам нужно отобразить только внутреннее содержимое формы без `
` & `
` HTML тегов, например, в AJAX запросе, вы можете открывать и закрывать форму с помощью `{formContext} … {/formContext}`. Он работает аналогично `{form}` в логическом смысле, здесь он позволяет вам использовать другие теги для рисования элементов формы, но в то же время он ничего не рисует. +Если необходимо отобразить только внутреннюю часть формы без HTML-тегов `
`например, при отправке сниппетов, скройте их с помощью атрибута `n:tag-if`: ```latte -{formContext signForm} +
{inputError username}
-{/formContext} +
``` Тег `formContainer` помогает при отрисовке вводимых данных внутри контейнера формы. diff --git a/forms/ru/validation.texy b/forms/ru/validation.texy index b3f60e1a21..1f7b5c33f1 100644 --- a/forms/ru/validation.texy +++ b/forms/ru/validation.texy @@ -38,7 +38,7 @@ Nette поставляется с рядом встроенных правил, | `IsNotIn` | значение не равно ни одному элементу массива | `array` | `Valid` | ввод проходит валидацию (для [#Условия]) | - -Для элементов управления `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()` также могут быть использованы следующие правила: +Для элементов `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` также могут быть применены некоторые из следующих правил: | `MinLength` | минимальная длина строки | `int` | `MaxLength` | максимальная длина строки | `int` diff --git a/forms/sl/controls.texy b/forms/sl/controls.texy index 4caa6b7f5c..8edc2d797a 100644 --- a/forms/sl/controls.texy +++ b/forms/sl/controls.texy @@ -20,7 +20,7 @@ Samodejno potrdi UTF-8, obreže leve in desne bele prostore ter odstrani prelome Največjo dolžino lahko omejite z uporabo `setMaxLength()`. S funkcijo [addFilter() |validation#Modifying Input Values] lahko spremenite uporabniško vneseno vrednost. -Z uporabo `setHtmlType()` spremenite [znak |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] vhodnega elementa v `search`, `tel`, `url`, `range`, `date`, `datetime-local`, `month`, `time`, `week`, `color`. Namesto tipov `number` in `email` priporočamo uporabo tipov [addInteger |#addInteger] in [addEmail |#addEmail], ki zagotavljata preverjanje na strani strežnika. +Z uporabo `setHtmlType()` lahko spremenite [znak |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] vhodnega elementa v `search`, `tel`, `url`, `range`, `datetime-local`, `month`, `time`, `week`, `color`. Namesto tipov `number` in `email` priporočamo uporabo tipov [addInteger |#addInteger], [addFloat |#addFloat] in [addEmail |#addEmail], ki imajo preverjanje na strani strežnika. ```php $form->addText('color', 'Choose color:') @@ -58,11 +58,24 @@ addInteger(string|int $name, $label=null): TextInput .[method] Doda vnosno polje za celo število (razred [TextInput |api:Nette\Forms\Controls\TextInput]). Vrne celo število ali `null`, če uporabnik ne vnese ničesar. ```php -$form->addInteger('level', 'Level:') +$form->addInteger('leto', 'Leto:') + ->addRule($form::Range, 'Leto mora biti v razponu od %d do %d.', [1900, 2023 |1900, 2023]); +``` + + +addFloat(string|int $name, $label=null): TextInput .[method]{data-version:3.1.12} +================================================================================= + +Adds a field for entering a decimal number ([TextInput |api:Nette\Forms\Controls\TextInput] class). Returns either float or `null`, if the user does not specify anything. + +```php +$form->addFloat('level', 'Stopnja:') ->setDefaultValue(0) - ->addRule($form::Range, 'Level must be between %d and %d.', [0, 100]); +->addRule($form::Range, 'Raven mora biti v razponu od %d do %d.', [0, 100 |0, 100]); ``` +Nette in Chrome kot decimalno ločilo sprejemata tako vejico kot piko. Da bi tudi Firefox sprejemal vejico, morate ustrezni jezik nastaviti v atributu HTML `lang`, in sicer neposredno temu elementu ali kateremu koli nadrejenemu elementu, na primer ``. + addEmail(string|int $name, $label=null): TextInput .[method] ============================================================ diff --git a/forms/sl/rendering.texy b/forms/sl/rendering.texy index 3c6dc0d824..7fa34a0c4e 100644 --- a/forms/sl/rendering.texy +++ b/forms/sl/rendering.texy @@ -237,15 +237,15 @@ Blok morate uvoziti le na enem mestu, na začetku predloge za postavitev: Posebni primeri .[#toc-special-cases] ------------------------------------- -Če morate prikazati samo notranjo vsebino obrazca brez `
` & `
` HTML, na primer v zahtevi AJAX, lahko obrazec odprete in zaprete s `{formContext} … {/formContext}`. V logičnem smislu deluje podobno kot `{form}`, tu vam omogoča uporabo drugih oznak za izris elementov obrazca, vendar hkrati ne izrisuje ničesar. +Če želite prikazati samo notranji del obrazca brez oznak HTML `
`na primer pri pošiljanju izsekov, jih skrijte s pomočjo atributa `n:tag-if`: ```latte -{formContext signForm} +
{inputError username}
-{/formContext} +
``` Oznaka `formContainer` pomaga pri izrisovanju vnosov znotraj vsebnika obrazca. diff --git a/forms/sl/validation.texy b/forms/sl/validation.texy index a1f35438fb..0d141c2fb9 100644 --- a/forms/sl/validation.texy +++ b/forms/sl/validation.texy @@ -38,7 +38,7 @@ Naslednja pravila lahko uporabimo za vse kontrole: | `IsNotIn` | vrednost ni enaka nobenemu elementu v polju | `array` | `Valid` | vhodni podatki so uspešno preverjeni (za [pogoje |#conditions]) | - -Za kontrole `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()` se lahko uporabijo tudi naslednja pravila: +Za elemente `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` se lahko uporabijo tudi nekatera od naslednjih pravil: | `MinLength` | minimalna dolžina niza | `int` | `MaxLength` | največja dolžina niza | `int` diff --git a/forms/tr/controls.texy b/forms/tr/controls.texy index fe5264d994..0db003ff2e 100644 --- a/forms/tr/controls.texy +++ b/forms/tr/controls.texy @@ -20,7 +20,7 @@ UTF-8'i otomatik olarak doğrular, sol ve sağ boşlukları keser ve bir saldır Maksimum uzunluk `setMaxLength()` kullanılarak sınırlandırılabilir. [addFilter() |validation#Modifying Input Values] kullanıcı tarafından girilen değeri değiştirmenize olanak tanır. -Giriş öğesinin [karakterini |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] `search`, `tel`, `url`, `range`, `date`, `datetime-local`, `month`, `time`, `week`, `color` olarak değiştirmek için `setHtmlType()` kullanın. `number` ve `email` türleri yerine, sunucu tarafı doğrulama sağlayan [addInteger |#addInteger] ve [addEmail'i |#addEmail] kullanmanızı öneririz. +Giriş öğesinin [karakterini |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] `search`, `tel`, `url`, `range`, `datetime-local`, `month`, `time`, `week`, `color` olarak değiştirmek için `setHtmlType()` kullanabilirsiniz. `number` ve `email` türleri yerine, sunucu tarafı doğrulaması olan [addInteger |#addInteger], [addFloat |#addFloat] ve [addEmail |#addEmail]'i kullanmanızı öneririz. ```php $form->addText('color', 'Choose color:') @@ -58,11 +58,24 @@ addInteger(string|int $name, $label=null): TextInput .[method] Tamsayı için giriş alanı ekler ( [TextInput |api:Nette\Forms\Controls\TextInput] sınıfı). Kullanıcı hiçbir şey girmezse bir tamsayı veya `null` döndürür. ```php -$form->addInteger('level', 'Level:') +$form->addInteger('year', 'Year:') + ->addRule($form::Range, 'Yıl %d ile %d aralığında olmalıdır.', [1900, 2023 |1900, 2023]); +``` + + +addFloat(string|int $name, $label=null): TextInput .[method]{data-version:3.1.12} +================================================================================= + +Adds a field for entering a decimal number ([TextInput |api:Nette\Forms\Controls\TextInput] class). Returns either float or `null`, if the user does not specify anything. + +```php +$form->addFloat('level', 'Level:') ->setDefaultValue(0) - ->addRule($form::Range, 'Level must be between %d and %d.', [0, 100]); +->addRule($form::Range, 'The level must be in the range %d to %d.', [0, 100 |0, 100]); ``` +Nette ve Chrome ondalık ayırıcı olarak hem virgül hem de noktayı kabul eder. Firefox'un da virgül kabul etmesi için, ilgili dili `lang` HTML niteliğinde, doğrudan bu öğeye veya herhangi bir üst öğeye ayarlamanız gerekir, örneğin ``. + addEmail(string|int $name, $label=null): TextInput .[method] ============================================================ diff --git a/forms/tr/rendering.texy b/forms/tr/rendering.texy index 787bb1e875..69676eca2f 100644 --- a/forms/tr/rendering.texy +++ b/forms/tr/rendering.texy @@ -237,15 +237,15 @@ Bloğu yalnızca bir yerde, düzen şablonunun başında içe aktarmanız gereki Özel Durumlar .[#toc-special-cases] ----------------------------------- -Bir formun yalnızca iç içeriğini oluşturmanız gerekiyorsa `
` & `
` HTML etiketleri, örneğin bir AJAX isteğinde, formu `{formContext} … {/formContext}` ile açıp kapatabilirsiniz. Mantıksal anlamda `{form}` ile benzer şekilde çalışır, burada form öğelerini çizmek için diğer etiketleri kullanmanıza izin verir, ancak aynı zamanda hiçbir şey çizmez. +Formun yalnızca iç kısmını HTML etiketleri olmadan oluşturmanız gerekiyorsa `
`örneğin snippet gönderirken, `n:tag-if` özniteliğini kullanarak bunları gizleyin: ```latte -{formContext signForm} +
{inputError username}
-{/formContext} +
``` Etiket `formContainer` bir form konteyneri içindeki girdilerin oluşturulmasına yardımcı olur. diff --git a/forms/tr/validation.texy b/forms/tr/validation.texy index 2d02efe8a3..ad95289175 100644 --- a/forms/tr/validation.texy +++ b/forms/tr/validation.texy @@ -38,7 +38,7 @@ Tüm kontroller için aşağıdaki kuralları kullanabiliriz: | `IsNotIn` | değer dizideki herhangi bir elemana eşit değil | `array` | `Valid` | girdi doğrulamayı geçer ( [koşullar |#conditions] için) | - -`addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()` denetimleri için aşağıdaki kurallar da kullanılabilir: +`addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` öğeleri için aşağıdaki kurallardan bazıları da uygulanabilir: | `MinLength` | minimum dize uzunluğu | `int` | `MaxLength` | maksimum dize uzunluğu | `int` diff --git a/forms/uk/controls.texy b/forms/uk/controls.texy index 26af421a00..5c8e9804c0 100644 --- a/forms/uk/controls.texy +++ b/forms/uk/controls.texy @@ -20,7 +20,7 @@ $form->addText('name', 'Имя:') Максимальна довжина може бути обмежена за допомогою `setMaxLength()`. Функція [addFilter() |validation#Modifying-Input-Values] дозволяє змінити введене користувачем значення. -Використовуйте `setHtmlType()` для зміни [типу |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] елемента введення на `search`, `tel`, `url`, `range`, `date`, `datetime-local`, `month`, `time`, `week`, `color`. Замість типів `number` і `email` ми рекомендуємо використовувати [addInteger |#addInteger] і [addEmail |#addEmail], які забезпечують валідацію на стороні сервера. +Ви можете використовувати `setHtmlType()` для зміни [символу |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] вхідного елемента на `search`, `tel`, `url`, `range`, `datetime-local`, `month`, `time`, `week`, `color`. Замість типів `number` та `email` ми рекомендуємо використовувати [addInteger |#addInteger], [addFloat |#addFloat] та [addEmail |#addEmail], які мають перевірку на стороні сервера. ```php $form->addText('color', 'Выберите цвет:') @@ -58,11 +58,24 @@ addInteger(string|int $name, $label=null): TextInput .[method] Додає поле введення для цілого числа (клас [TextInput |api:Nette\Forms\Controls\TextInput]). Повертає або ціле число, або `null`, якщо користувач нічого не ввів. ```php -$form->addInteger('level', 'Уровень:') +$form->addInteger('year', 'Year:') + ->addRule($form::Range, 'Рік має бути в діапазоні від %d до %d.', [1900, 2023 |1900, 2023]); +``` + + +addFloat(string|int $name, $label=null): TextInput .[method]{data-version:3.1.12} +================================================================================= + +Adds a field for entering a decimal number ([TextInput |api:Nette\Forms\Controls\TextInput] class). Returns either float or `null`, if the user does not specify anything. + +```php +$form->addFloat('level', 'Level:') ->setDefaultValue(0) - ->addRule($form::Range, 'Уровень должен быть между %d и %d.', [0, 100]); +->addRule($form::Range, 'Рівень повинен бути в діапазоні від %d до %d.', [0, 100 |0, 100]); ``` +Nette і Chrome приймають як кому, так і крапку в якості десяткового роздільника. Щоб Firefox також приймав кому, потрібно задати відповідну мову в HTML-атрибуті `lang` або безпосередньо для цього елемента, або для будь-якого батьківського елемента, наприклад ``. + addEmail(string|int $name, $label=null): TextInput .[method] ============================================================ diff --git a/forms/uk/rendering.texy b/forms/uk/rendering.texy index 6550558c6a..e45ef5d03d 100644 --- a/forms/uk/rendering.texy +++ b/forms/uk/rendering.texy @@ -237,15 +237,15 @@ protected function createComponentSignInForm(): Form Особливі випадки .[#toc-special-cases] -------------------------------------- -Якщо вам потрібно відобразити тільки внутрішній вміст форми без `
` & `
` HTML тегів, наприклад, в AJAX запиті, ви можете відкривати і закривати форму за допомогою `{formContext} … {/formContext}`. Він працює аналогічно `{form}` в логічному сенсі, тут він дозволяє вам використовувати інші теги для малювання елементів форми, але в той же час він нічого не малює. +Якщо вам потрібно відобразити тільки внутрішню частину форми без HTML-тегів `
`наприклад, при надсиланні фрагментів, приховайте їх за допомогою атрибута `n:tag-if`: ```latte -{formContext signForm} +
{inputError username}
-{/formContext} +
``` Тег `formContainer` допомагає при відтворенні даних, що вводяться, всередині контейнера форми. diff --git a/forms/uk/validation.texy b/forms/uk/validation.texy index a9ca94d241..ab69301e99 100644 --- a/forms/uk/validation.texy +++ b/forms/uk/validation.texy @@ -38,7 +38,7 @@ Nette постачається з низкою вбудованих правил | `IsNotIn` | значення не дорівнює жодному елементу масиву | `array` | `Valid` | введення проходить валідацію (для [Умови |#Условия])| - -Для елементів керування `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()` також можуть бути використані такі правила: +Для елементів `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` також можна застосувати деякі з наступних правил: | `MinLength` | мінімальна довжина рядка | `int` | `MaxLength` | максимальна довжина рядка | `int` diff --git a/latte/bg/tags.texy b/latte/bg/tags.texy index 0ab9c59ade..61dc6b378b 100644 --- a/latte/bg/tags.texy +++ b/latte/bg/tags.texy @@ -110,7 +110,6 @@ | `n:name` [активира входния елемент на HTML |forms:rendering#n:name] | `{formPrint}` [генерира чертеж на формата Latte |forms:rendering#formPrint] | `{formPrintClass}` [отпечатва PHP клас за данните от формата |forms:in-presenter#Mapping-to-Classes] -| `{formContext}`... `{/formContext}` | [Частично визуализиране на формата |forms:rendering#special-cases] | `{formContainer}`... `{/formContainer}` | [визуализиране на контейнера за формуляри |forms:rendering#special-cases] diff --git a/latte/cs/tags.texy b/latte/cs/tags.texy index 343ffaa172..8d410cd225 100644 --- a/latte/cs/tags.texy +++ b/latte/cs/tags.texy @@ -110,7 +110,6 @@ Přehled a popis všech tagů (neboli značek či maker) šablonovacího systém | `n:name` | [oživí formulářový prvek |forms:rendering#n:name] | `{formPrint}` | [navrhne Latte kód pro formulář |forms:rendering#formPrint] | `{formPrintClass}` | [navrhne PHP kód třídy s daty formuláře |forms:in-presenter#mapovani-na-tridy] -| `{formContext}` … `{/formContext}` | [částečné kreslení formuláře |forms:rendering#specialni-pripady] | `{formContainer}` … `{/formContainer}` | [kreslení formulářového kontejneru |forms:rendering#specialni-pripady] diff --git a/latte/de/tags.texy b/latte/de/tags.texy index 67e8baecf9..52df4f4ecd 100644 --- a/latte/de/tags.texy +++ b/latte/de/tags.texy @@ -110,7 +110,6 @@ Zusammenfassung und Beschreibung aller in Latte integrierten Tags. | `n:name` | [aktiviert ein HTML-Eingabeelement |forms:rendering#n:name] | `{formPrint}` | [erzeugt einen Latte-Formular-Blaupause |forms:rendering#formPrint] | `{formPrintClass}` | [gibt PHP-Klasse für Formulardaten aus |forms:in-presenter#mapping-to-classes] -| `{formContext}`... `{/formContext}` | [Teilweise Formularwiedergabe |forms:rendering#special-cases] | `{formContainer}`... `{/formContainer}` | [Darstellung des Formular-Containers |forms:rendering#special-cases] diff --git a/latte/el/tags.texy b/latte/el/tags.texy index 80acc64da8..de069be3da 100644 --- a/latte/el/tags.texy +++ b/latte/el/tags.texy @@ -110,7 +110,6 @@ | `n:name` | [ενεργοποιεί ένα στοιχείο εισόδου HTML |forms:rendering#n:name] | `{formPrint}` | [δημιουργεί σχέδιο φόρμας Latte |forms:rendering#formPrint] | `{formPrintClass}` | [εκτυπώνει κλάση PHP για τα δεδομένα της φόρμας |forms:in-presenter#mapping-to-classes] -| `{formContext}`... `{/formContext}` | [μερική απόδοση φόρμας |forms:rendering#special-cases] | `{formContainer}`... `{/formContainer}` | [απόδοση του δοχείου της φόρμας |forms:rendering#special-cases] diff --git a/latte/en/tags.texy b/latte/en/tags.texy index 08f4d516db..2df615fc3a 100644 --- a/latte/en/tags.texy +++ b/latte/en/tags.texy @@ -110,7 +110,6 @@ Summary and description of all Latte built-in tags. | `n:name` | [activates an HTML input element |forms:rendering#n:name] | `{formPrint}` | [generates Latte form blueprint |forms:rendering#formPrint] | `{formPrintClass}` | [prints PHP class for form data |forms:in-presenter#mapping-to-classes] -| `{formContext}` … `{/formContext}` | [partial form rendering |forms:rendering#special-cases] | `{formContainer}` … `{/formContainer}` | [rendering the form container |forms:rendering#special-cases] diff --git a/latte/es/tags.texy b/latte/es/tags.texy index 3e2381c8fe..333de04aa1 100644 --- a/latte/es/tags.texy +++ b/latte/es/tags.texy @@ -110,7 +110,6 @@ Resumen y descripción de todas las etiquetas Latte incorporadas. | `n:name` | [activa un elemento de entrada HTML |forms:rendering#n:name] | `{formPrint}` | [genera un modelo de formulario Latte |forms:rendering#formPrint] | `{formPrintClass}` | [imprime la clase PHP para los datos del formulario |forms:in-presenter#mapping-to-classes] -| `{formContext}`... `{/formContext}` | [renderización parcial del formulario|forms:rendering#special-cases] | `{formContainer}`... `{/formContainer}` | [renderización del contenedor de formularios |forms:rendering#special-cases] diff --git a/latte/fr/tags.texy b/latte/fr/tags.texy index f884a996fd..26c0d42606 100644 --- a/latte/fr/tags.texy +++ b/latte/fr/tags.texy @@ -110,7 +110,6 @@ Résumé et description de toutes les balises intégrées de Latte. | `n:name` | [active un élément de saisie HTML |forms:rendering#n:name] | `{formPrint}` | [génère le plan du formulaire Latte |forms:rendering#formPrint] | `{formPrintClass}` | [imprime la classe PHP pour les données du formulaire |forms:in-presenter#mapping-to-classes] -| `{formContext}`... `{/formContext}` | [rendu partiel du formulaire |forms:rendering#special-cases] | `{formContainer}`... `{/formContainer}` | [rendre le conteneur de formulaire |forms:rendering#special-cases] diff --git a/latte/hu/tags.texy b/latte/hu/tags.texy index ca5930c18c..515ef7aa3c 100644 --- a/latte/hu/tags.texy +++ b/latte/hu/tags.texy @@ -110,7 +110,6 @@ Az összes beépített Latte-címke összefoglalása és leírása. | `n:name` | [HTML beviteli elem aktiválása |forms:rendering#n:name] | `{formPrint}` | [Latte űrlap tervezetet készít |forms:rendering#formPrint] | `{formPrintClass}` | [PHP osztály nyomtatása az űrlap adataihoz |forms:in-presenter#mapping-to-classes] -| `{formContext}`... `{/formContext}` | [részleges űrlap renderelés |forms:rendering#special-cases] | `{formContainer}`... `{/formContainer}` | [az űrlap tárolójának renderelése |forms:rendering#special-cases] diff --git a/latte/it/tags.texy b/latte/it/tags.texy index 8748ff6adc..e41b39e7e0 100644 --- a/latte/it/tags.texy +++ b/latte/it/tags.texy @@ -110,7 +110,6 @@ Riepilogo e descrizione di tutti i tag incorporati di Latte. | `n:name` | [attiva un elemento di input HTML |forms:rendering#n:name] | `{formPrint}` | [genera il blueprint del modulo Latte |forms:rendering#formPrint] | `{formPrintClass}` | [stampa la classe PHP per i dati del modulo |forms:in-presenter#mapping-to-classes] -| `{formContext}`... `{/formContext}` | [rendering parziale del modulo |forms:rendering#special-cases] | `{formContainer}`... `{/formContainer}` | [rendere il contenitore del modulo |forms:rendering#special-cases] diff --git a/latte/ja/tags.texy b/latte/ja/tags.texy index b01cdb18d9..58f2fcab6f 100644 --- a/latte/ja/tags.texy +++ b/latte/ja/tags.texy @@ -110,7 +110,6 @@ Latte内蔵の全タグの概要と説明。 |`n:name` |[HTML入力要素をアクティブにする|forms:en:rendering#n:name] |`{formPrint}` |[ラテ型フォームの青写真を生成する|forms:en:rendering#formPrint] |`{formPrintClass}` |[フォームデータのための PHP クラスを表示する|forms:en:in-presenter#mapping-to-classes] -|`{formContext}`...`{/formContext}` |[フォームの部分的なレンダリング |forms:en:rendering#special-cases] |`{formContainer}`...`{/formContainer}` |[フォームコンテナのレンダリング |forms:en:rendering#special-cases] diff --git a/latte/pl/tags.texy b/latte/pl/tags.texy index 42a72ab36b..427b023b0d 100644 --- a/latte/pl/tags.texy +++ b/latte/pl/tags.texy @@ -110,7 +110,6 @@ Przegląd i opis wszystkich znaczników systemu templatek Latte, które są domy | `n:name` | [animuje element formularza |forms:rendering#n:name] | `{formPrint}` | [projekt kod latte dla formularza |forms:rendering#formPrint] | `{formPrintClass}` | [zaprojektuj kod PHP dla klasy z danymi formularza |forms:in-presenter#Mapping-to-Classes] -| `{formContext}`... `{/formContext}` | [częściowy rysunek formy |forms:rendering#special-cases] | `{formContainer}`... `{/formContainer}` | [renderowanie pojemnika na formularze |forms:rendering#special-cases] diff --git a/latte/pt/tags.texy b/latte/pt/tags.texy index e61802b29a..e75d75442c 100644 --- a/latte/pt/tags.texy +++ b/latte/pt/tags.texy @@ -110,7 +110,6 @@ Resumo e descrição de todas as etiquetas incorporadas no Latte. | `n:name` | [ativa um elemento de entrada HTML |forms:rendering#n:name] | `{formPrint}` | [gera o projeto do formulário Latte |forms:rendering#formPrint] | `{formPrintClass}` | [imprime a classe PHP para dados de formulário |forms:in-presenter#mapping-to-classes] -| `{formContext}`... `{/formContext}` | [versão parcial da forma |forms:rendering#special-cases] | `{formContainer}`... `{/formContainer}` | [tornando o recipiente do formulário |forms:rendering#special-cases] diff --git a/latte/ro/tags.texy b/latte/ro/tags.texy index ca997cafc5..418f96706b 100644 --- a/latte/ro/tags.texy +++ b/latte/ro/tags.texy @@ -110,7 +110,6 @@ Rezumat și descriere a tuturor etichetelor Latte încorporate. | `n:name` | [activează un element de intrare HTML |forms:rendering#n:name] | `{formPrint}` | [generează schița unui formular Latte |forms:rendering#formPrint] | `{formPrintClass}` | [tipărește clasa PHP pentru datele formularului |forms:in-presenter#mapping-to-classes] -| `{formContext}`... `{/formContext}` | [redarea parțială a formularului |forms:rendering#special-cases] | `{formContainer}`... `{/formContainer}` | [redarea formularului container |forms:rendering#special-cases] diff --git a/latte/ru/tags.texy b/latte/ru/tags.texy index 9a1d840b66..bda6db644b 100644 --- a/latte/ru/tags.texy +++ b/latte/ru/tags.texy @@ -110,7 +110,6 @@ | `n:name` | [активирует элемент ввода HTML |forms:rendering#n:name] | `{formPrint}` | [генерирует чертеж формы Latte |forms:rendering#formPrint] | `{formPrintClass}` | [печатает PHP класс для данных формы |forms:in-presenter#Mapping-to-Classes] -| `{formContext}`... `{/formContext}` | [частичный рендеринг формы |forms:rendering#special-cases] | `{formContainer}`... `{/formContainer}` | [рендеринг контейнера формы |forms:rendering#special-cases] diff --git a/latte/sl/tags.texy b/latte/sl/tags.texy index 1e52d9acf5..a28be54aa9 100644 --- a/latte/sl/tags.texy +++ b/latte/sl/tags.texy @@ -110,7 +110,6 @@ Povzetek in opis vseh vgrajenih oznak Latte. | `n:name` | [aktivira vnosni element HTML |forms:rendering#n:name] | `{formPrint}` | [ustvari načrt obrazca Latte |forms:rendering#formPrint] | `{formPrintClass}` | [izpiše razred PHP za podatke obrazca |forms:in-presenter#mapping-to-classes] -| `{formContext}`... `{/formContext}` | [delni prikaz obrazca |forms:rendering#special-cases] | `{formContainer}`... `{/formContainer}` | [upodabljanje vsebnika obrazca |forms:rendering#special-cases] diff --git a/latte/tr/tags.texy b/latte/tr/tags.texy index 9639ca566a..d7154073d0 100644 --- a/latte/tr/tags.texy +++ b/latte/tr/tags.texy @@ -110,7 +110,6 @@ Tüm Latte yerleşik etiketlerinin özeti ve açıklaması. | `n:name` | [bir HTML giriş öğesini etkinleştirir |forms:rendering#n:name] | `{formPrint}` | [Latte form planını oluşturur |forms:rendering#formPrint] | `{formPrintClass}` | [form verileri için PHP sınıfını yazdırır |forms:in-presenter#mapping-to-classes] -| `{formContext}`... `{/formContext}` | [kısmi form oluşturma |forms:rendering#special-cases] | `{formContainer}`... `{/formContainer}` | [form kapsayıcısını oluşturma |forms:rendering#special-cases] diff --git a/latte/uk/tags.texy b/latte/uk/tags.texy index 5904f30aa8..fdf8ed737c 100644 --- a/latte/uk/tags.texy +++ b/latte/uk/tags.texy @@ -110,7 +110,6 @@ | `n:name` | [активує елемент введення HTML |forms:rendering#n:name] | `{formPrint}` | [генерує креслення форми Latte |forms:rendering#formPrint] | `{formPrintClass}` | [друкує PHP клас для даних форми |forms:in-presenter#Mapping-to-Classes] -| `{formContext}`... `{/formContext}` | [частковий рендеринг форми |forms:rendering#special-cases] | `{formContainer}`... `{/formContainer}` | [рендеринг контейнера форми |forms:rendering#special-cases] From ef84794e09f8876024a0aa68f25b86d76c9784cb Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 11 Oct 2023 14:08:47 +0200 Subject: [PATCH 021/137] latte 3.0.10 --- latte/bg/functions.texy | 12 ++++++++++++ latte/bg/template-inheritance.texy | 8 ++++++++ latte/cs/functions.texy | 12 ++++++++++++ latte/cs/template-inheritance.texy | 8 ++++++++ latte/de/functions.texy | 12 ++++++++++++ latte/de/template-inheritance.texy | 8 ++++++++ latte/el/functions.texy | 12 ++++++++++++ latte/el/template-inheritance.texy | 8 ++++++++ latte/en/functions.texy | 12 ++++++++++++ latte/en/template-inheritance.texy | 8 ++++++++ latte/es/functions.texy | 12 ++++++++++++ latte/es/template-inheritance.texy | 8 ++++++++ latte/fr/functions.texy | 12 ++++++++++++ latte/fr/template-inheritance.texy | 8 ++++++++ latte/hu/functions.texy | 12 ++++++++++++ latte/hu/template-inheritance.texy | 8 ++++++++ latte/it/functions.texy | 12 ++++++++++++ latte/it/template-inheritance.texy | 8 ++++++++ latte/ja/functions.texy | 12 ++++++++++++ latte/ja/template-inheritance.texy | 8 ++++++++ latte/pl/functions.texy | 12 ++++++++++++ latte/pl/template-inheritance.texy | 8 ++++++++ latte/pt/functions.texy | 12 ++++++++++++ latte/pt/template-inheritance.texy | 8 ++++++++ latte/ro/functions.texy | 12 ++++++++++++ latte/ro/template-inheritance.texy | 8 ++++++++ latte/ru/functions.texy | 12 ++++++++++++ latte/ru/template-inheritance.texy | 8 ++++++++ latte/sl/functions.texy | 12 ++++++++++++ latte/sl/template-inheritance.texy | 8 ++++++++ latte/tr/functions.texy | 12 ++++++++++++ latte/tr/template-inheritance.texy | 8 ++++++++ latte/uk/functions.texy | 12 ++++++++++++ latte/uk/template-inheritance.texy | 8 ++++++++ 34 files changed, 340 insertions(+) diff --git a/latte/bg/functions.texy b/latte/bg/functions.texy index 7a0a686c97..d6f282356a 100644 --- a/latte/bg/functions.texy +++ b/latte/bg/functions.texy @@ -9,6 +9,7 @@ | `divisibleBy`| [проверява дали дадена променлива се дели на дадено число |#divisibleBy] | `even` | [проверява дали дадено число е четно число|#even] | `first` | [връща първия елемент на масив или символен низ |#first] +| `hasBlock` | [открива съществуването на блок |#hasBlock] | `last` | [връща последния елемент на масив или символен низ|#last] | `odd` | [проверява дали числото е нечетно |#odd] | `slice` | [извлича фрагмент от масив или низ |#slice] @@ -85,6 +86,17 @@ first(string|array $value): mixed .[method] Вижте също [последно |#last], [първо филтриране |filters#first]. +hasBlock(string $name): bool .[method]{data-version:3.0.10} +----------------------------------------------------------- +Проверява дали блокът със зададеното име съществува: + +```latte +{if hasBlock(header)} ... {/if} +``` + +Вижте също [проверка на съществуването на блока |template-inheritance#Checking Block Existence]. + + last(string|array $value): mixed .[method] ------------------------------------------ Връща последния елемент на масив или символен низ: diff --git a/latte/bg/template-inheritance.texy b/latte/bg/template-inheritance.texy index 300e571bf1..029d5cf9b3 100644 --- a/latte/bg/template-inheritance.texy +++ b/latte/bg/template-inheritance.texy @@ -396,6 +396,14 @@ Hi, I am Mary. {/ifset} ``` +Съществуването на блокове се връща и от функцията [`hasBlock()` |functions#hasBlock]: + +```latte +{if hasBlock(header) || hasBlock(footer)} + ... +{/if} +``` + Съвети .[#toc-tips] ------------------- diff --git a/latte/cs/functions.texy b/latte/cs/functions.texy index 1235964104..b7f9854aa5 100644 --- a/latte/cs/functions.texy +++ b/latte/cs/functions.texy @@ -9,6 +9,7 @@ V šablonách můžeme kromě běžných PHP funkcí používat i tyto další. | `divisibleBy`| [zkontroluje, zda je proměnná dělitelná číslem |#divisibleBy] | `even` | [zkontroluje, zda je dané číslo sudé |#even] | `first` | [vrací první prvek pole nebo znak řetězce |#first] +| `hasBlock` | [zjistí existenci bloku |#hasBlock] | `last` | [vrací poslední prvek pole nebo znak řetězce |#last] | `odd` | [zkontroluje, zda je dané číslo liché |#odd] | `slice` | [extrahuje část pole nebo řetězce |#slice] @@ -85,6 +86,17 @@ Vrací první prvek pole nebo znak řetězce: Viz také [#last], [filtr first|filters#first]. +hasBlock(string $name): bool .[method]{data-version:3.0.10} +----------------------------------------------------------- +Zjistí, zda blok uvedeného jména existuje: + +```latte +{if hasBlock(header)} ... {/if} +``` + +Viz také [kontrola existence bloků|template-inheritance#Kontrola existence bloků]. + + last(string|array $value): mixed .[method] ------------------------------------------ Vrací poslední prvek pole nebo znak řetězce: diff --git a/latte/cs/template-inheritance.texy b/latte/cs/template-inheritance.texy index 6d3c2bf2c0..ab6e030bdb 100644 --- a/latte/cs/template-inheritance.texy +++ b/latte/cs/template-inheritance.texy @@ -396,6 +396,14 @@ Jako název bloku lze použít proměnnou nebo jakýkoli výraz v PHP. V takové {/ifset} ``` +Existenci bloků ověřuje také funkce [`hasBlock()` |functions#hasBlock]: + +```latte +{if hasBlock(header) || hasBlock(footer)} + ... +{/if} +``` + Tipy ---- diff --git a/latte/de/functions.texy b/latte/de/functions.texy index a60ad676db..32592eb4b1 100644 --- a/latte/de/functions.texy +++ b/latte/de/functions.texy @@ -9,6 +9,7 @@ Zusätzlich zu den üblichen PHP-Funktionen können Sie diese auch in Vorlagen v | `divisibleBy`| [prüft ob eine Variable durch eine Zahl teilbar ist |#divisibleBy] | `even` | [prüft ob die angegebene Zahl gerade ist |#even] | `first` | [gibt das erste Element eines Arrays oder ein Zeichen einer Zeichenkette zurück |#first] +| `hasBlock` | [erkennt das Vorhandensein eines Blocks |#hasBlock] | `last` | [gibt das letzte Element eines Arrays oder ein Zeichen einer Zeichenkette zurück |#last] | `odd` | [prüft ob die angegebene Zahl ungerade ist |#odd] | `slice` | [extrahiert einen Ausschnitt aus einem Array oder einer Zeichenkette|#slice] @@ -85,6 +86,17 @@ Gibt das erste Element eines Arrays oder ein Zeichen einer Zeichenkette zurück: Siehe auch [last |#last], [filter first |filters#first]. +hasBlock(string $name): bool .[method]{data-version:3.0.10} +----------------------------------------------------------- +Prüft, ob der Block mit dem angegebenen Namen existiert: + +```latte +{if hasBlock(header)} ... {/if} +``` + +Siehe auch [Blockexistenzprüfung |template-inheritance#Checking Block Existence]. + + last(string|array $value): mixed .[method] ------------------------------------------ Gibt das letzte Element eines Arrays oder ein Zeichen einer Zeichenkette zurück: diff --git a/latte/de/template-inheritance.texy b/latte/de/template-inheritance.texy index 4e365c106f..1741888e5e 100644 --- a/latte/de/template-inheritance.texy +++ b/latte/de/template-inheritance.texy @@ -396,6 +396,14 @@ Sie können eine Variable oder einen beliebigen Ausdruck in PHP als Blocknamen v {/ifset} ``` +Die Existenz von Blöcken wird auch von der Funktion [`hasBlock()` |functions#hasBlock]: + +```latte +{if hasBlock(header) || hasBlock(footer)} + ... +{/if} +``` + Tipps .[#toc-tips] ------------------ diff --git a/latte/el/functions.texy b/latte/el/functions.texy index 3ff01d6318..908cab947f 100644 --- a/latte/el/functions.texy +++ b/latte/el/functions.texy @@ -9,6 +9,7 @@ | `divisibleBy`| [ελέγχει αν μια μεταβλητή διαιρείται με έναν αριθμό |#divisibleBy] | `even` | [ελέγχει αν ο δεδομένος αριθμός είναι ζυγός |#even] | `first` | [επιστρέφει το πρώτο στοιχείο του πίνακα ή τον χαρακτήρα της συμβολοσειράς |#first] +| `hasBlock` | [ανιχνεύει την ύπαρξη ενός μπλοκ |#hasBlock] | `last` | [επιστρέφει το τελευταίο στοιχείο του πίνακα ή τον χαρακτήρα της συμβολοσειράς |#last] | `odd` | [ελέγχει αν ο δεδομένος αριθμός είναι περιττός |#odd] | `slice` | [εξάγει ένα τμήμα ενός πίνακα ή μιας συμβολοσειράς |#slice] @@ -85,6 +86,17 @@ first(string|array $value): mixed .[method] Βλέπε επίσης [last |#last], [filter first |filters#first]. +hasBlock(string $name): bool .[method]{data-version:3.0.10} +----------------------------------------------------------- +Ελέγχει αν υπάρχει το μπλοκ με το καθορισμένο όνομα: + +```latte +{if hasBlock(header)} ... {/if} +``` + +Δείτε επίσης τον [έλεγχο ύπαρξης μπλοκ |template-inheritance#Checking Block Existence]. + + last(string|array $value): mixed .[method] ------------------------------------------ Επιστρέφει το τελευταίο στοιχείο του πίνακα ή τον τελευταίο χαρακτήρα της συμβολοσειράς: diff --git a/latte/el/template-inheritance.texy b/latte/el/template-inheritance.texy index ce4a48716e..1c544fdb1b 100644 --- a/latte/el/template-inheritance.texy +++ b/latte/el/template-inheritance.texy @@ -396,6 +396,14 @@ Hi, I am Mary. {/ifset} ``` +Η ύπαρξη μπλοκ επιστρέφεται επίσης από τη συνάρτηση [`hasBlock()` |functions#hasBlock]: + +```latte +{if hasBlock(header) || hasBlock(footer)} + ... +{/if} +``` + Συμβουλές .[#toc-tips] ---------------------- diff --git a/latte/en/functions.texy b/latte/en/functions.texy index 0e4708c341..10b3c7e2c4 100644 --- a/latte/en/functions.texy +++ b/latte/en/functions.texy @@ -9,6 +9,7 @@ In addition to the common PHP functions, you can also use these in templates. | `divisibleBy`| [checks if a variable is divisible by a number |#divisibleBy] | `even` | [checks if the given number is even |#even] | `first` | [returns first element of array or character of string |#first] +| `hasBlock` | [detects the existence of a block |#hasBlock] | `last` | [returns last element of array or character of string |#last] | `odd` | [checks if the given number is odd |#odd] | `slice` | [extracts a slice of an array or a string |#slice] @@ -85,6 +86,17 @@ Returns the first element of array or character of string: See also [#last], [filter first|filters#first]. +hasBlock(string $name): bool .[method]{data-version:3.0.10} +----------------------------------------------------------- +Checks if the block of the specified name exists: + +```latte +{if hasBlock(header)} ... {/if} +``` + +See also [block existence check |template-inheritance#Checking Block Existence]. + + last(string|array $value): mixed .[method] ------------------------------------------ Returns the last element of array or character of string: diff --git a/latte/en/template-inheritance.texy b/latte/en/template-inheritance.texy index e9eeeaa226..682e8ed475 100644 --- a/latte/en/template-inheritance.texy +++ b/latte/en/template-inheritance.texy @@ -396,6 +396,14 @@ You can use a variable or any expression in PHP as the block name. In this case, {/ifset} ``` +The existence of blocks is also returned by the function [`hasBlock()` |functions#hasBlock]: + +```latte +{if hasBlock(header) || hasBlock(footer)} + ... +{/if} +``` + Tips ---- diff --git a/latte/es/functions.texy b/latte/es/functions.texy index 84ce9d3a17..bae266fb15 100644 --- a/latte/es/functions.texy +++ b/latte/es/functions.texy @@ -9,6 +9,7 @@ Además de las funciones comunes de PHP, también puede utilizarlas en plantilla | `divisibleBy`| [comprueba si una variable es divisible por un número |#divisibleBy] | `even` | [comprueba si el número dado es par |#even] | `first` | [devuelve el primer elemento de una matriz o un carácter de una cadena |#first] +| `hasBlock` | [detecta la existencia de un bloque |#hasBlock] | `last` | [devuelve el último elemento de la matriz o carácter de la cadena|#last] | `odd` | [comprueba si el número dado es impar|#odd] | `slice` | [extrae un trozo de una matriz o de una cadena |#slice] @@ -85,6 +86,17 @@ Devuelve el primer elemento de un array o carácter de una cadena: Véase también [last |#last], [filter first |filters#first]. +hasBlock(string $name): bool .[method]{data-version:3.0.10} +----------------------------------------------------------- +Comprueba si existe el bloque del nombre especificado: + +```latte +{if hasBlock(header)} ... {/if} +``` + +Véase también [comprobación |template-inheritance#Checking Block Existence] de existencia de bloque. + + last(string|array $value): mixed .[method] ------------------------------------------ Devuelve el último elemento del array o carácter de la cadena: diff --git a/latte/es/template-inheritance.texy b/latte/es/template-inheritance.texy index 3e9e0c3f62..61607723aa 100644 --- a/latte/es/template-inheritance.texy +++ b/latte/es/template-inheritance.texy @@ -396,6 +396,14 @@ Puede utilizar una variable o cualquier expresión en PHP como nombre del bloque {/ifset} ``` +La existencia de bloques también se devuelve mediante la función [`hasBlock()` |functions#hasBlock]: + +```latte +{if hasBlock(header) || hasBlock(footer)} + ... +{/if} +``` + Consejos .[#toc-tips] --------------------- diff --git a/latte/fr/functions.texy b/latte/fr/functions.texy index 9d2d9e0ba8..f00ed89d47 100644 --- a/latte/fr/functions.texy +++ b/latte/fr/functions.texy @@ -9,6 +9,7 @@ Outre les fonctions PHP courantes, vous pouvez également les utiliser dans les | `divisibleBy`| [vérifie si une variable est divisible par un nombre |#divisibleBy] | `even` | [vérifie si le nombre donné est pair |#even] | `first` | [renvoie le premier élément d'un tableau ou un caractère d'une chaîne de caractères |#first] +| `hasBlock` | [détecte l'existence d'un bloc |#hasBlock] | `last` | [renvoie le dernier élément d'un tableau ou un caractère d'une chaîne de caractères |#last] | `odd` | [vérifie si le nombre donné est impair |#odd] | `slice` | [extrait une tranche d'un tableau ou d'une chaîne de caractères |#slice] @@ -85,6 +86,17 @@ Retourne le premier élément d'un tableau ou le premier caractère d'une chaîn Voir aussi [last |#last], [filter first |filters#first]. +hasBlock(string $name): bool .[method]{data-version:3.0.10} +----------------------------------------------------------- +Vérifie si le bloc du nom spécifié existe : + +```latte +{if hasBlock(header)} ... {/if} +``` + +Voir aussi [vérification de l'existence du bloc |template-inheritance#Checking Block Existence]. + + last(string|array $value): mixed .[method] ------------------------------------------ Renvoie le dernier élément du tableau ou le dernier caractère de la chaîne : diff --git a/latte/fr/template-inheritance.texy b/latte/fr/template-inheritance.texy index 3c14000ecc..d0b17c5615 100644 --- a/latte/fr/template-inheritance.texy +++ b/latte/fr/template-inheritance.texy @@ -396,6 +396,14 @@ Vous pouvez utiliser une variable ou toute expression en PHP comme nom de bloc. {/ifset} ``` +L'existence de blocs est également renvoyée par la fonction [`hasBlock()` |functions#hasBlock]: + +```latte +{if hasBlock(header) || hasBlock(footer)} + ... +{/if} +``` + Conseils .[#toc-tips] --------------------- diff --git a/latte/hu/functions.texy b/latte/hu/functions.texy index be9120f389..8968e7ea58 100644 --- a/latte/hu/functions.texy +++ b/latte/hu/functions.texy @@ -9,6 +9,7 @@ Az általános PHP-funkciók mellett ezeket is használhatod a sablonokban. | `divisibleBy`| [ellenőrzi, hogy egy változó osztható-e egy számmal |#divisibleBy] | `even` | [ellenőrzi, hogy a megadott szám páros-e |#even] | `first` | [visszaadja a tömb első elemét vagy a karakterlánc első karakterét |#first]. +| `hasBlock` | [érzékeli egy blokk létezését |#hasBlock]. | `last` | [visszaadja a tömb utolsó elemét vagy a karakterlánc utolsó karakterét |#last]. | `odd` | [ellenőrzi, hogy az adott szám páratlan-e |#odd]. | `slice` | [kivonja egy tömb vagy egy karakterlánc egy szeletét |#slice]. @@ -85,6 +86,17 @@ Visszaadja a tömb első elemét vagy a karakterlánc első karakterét: Lásd még [last |#last], [filter first |filters#first]. +hasBlock(string $name): bool .[method]{data-version:3.0.10} +----------------------------------------------------------- +Ellenőrzi, hogy a megadott nevű blokk létezik-e: + +```latte +{if hasBlock(header)} ... {/if} +``` + +Lásd még a [blokk létezésének ellenőrzése |template-inheritance#Checking Block Existence]. + + last(string|array $value): mixed .[method] ------------------------------------------ A tömb utolsó elemét vagy a karakterlánc utolsó karakterét adja vissza: diff --git a/latte/hu/template-inheritance.texy b/latte/hu/template-inheritance.texy index d0575b7cae..eee1de2384 100644 --- a/latte/hu/template-inheritance.texy +++ b/latte/hu/template-inheritance.texy @@ -396,6 +396,14 @@ A blokk neveként használhat egy változót vagy bármely PHP kifejezését. Eb {/ifset} ``` +A blokkok meglétét szintén a [`hasBlock()` |functions#hasBlock]: + +```latte +{if hasBlock(header) || hasBlock(footer)} + ... +{/if} +``` + Tippek .[#toc-tips] ------------------- diff --git a/latte/it/functions.texy b/latte/it/functions.texy index 987cf7618d..8a3b2bd8c6 100644 --- a/latte/it/functions.texy +++ b/latte/it/functions.texy @@ -9,6 +9,7 @@ Oltre alle comuni funzioni PHP, è possibile utilizzarle anche nei template. | `divisibleBy`| [controlla se una variabile è divisibile per un numero |#divisibleBy] | `even` | [controlla se il numero dato è pari |#even] | `first` | [restituisce il primo elemento di un array o un carattere di una stringa |#first] +| `hasBlock` | [rileva l'esistenza di un blocco |#hasBlock] | `last` | [restituisce l'ultimo elemento di un array o un carattere di una stringa |#last] | `odd` | [controlla se il numero dato è dispari |#odd] | `slice` | [estrae una fetta di un array o di una stringa |#slice] @@ -85,6 +86,17 @@ Restituisce il primo elemento di una matrice o un carattere di una stringa: Vedere anche [last |#last], [filter first |filters#first]. +hasBlock(string $name): bool .[method]{data-version:3.0.10} +----------------------------------------------------------- +Controlla se il blocco con il nome specificato esiste: + +```latte +{if hasBlock(header)} ... {/if} +``` + +Si veda anche il [controllo dell'esistenza del blocco |template-inheritance#Checking Block Existence]. + + last(string|array $value): mixed .[method] ------------------------------------------ Restituisce l'ultimo elemento della matrice o il carattere della stringa: diff --git a/latte/it/template-inheritance.texy b/latte/it/template-inheritance.texy index b7023338f1..ede86caa3c 100644 --- a/latte/it/template-inheritance.texy +++ b/latte/it/template-inheritance.texy @@ -396,6 +396,14 @@ Si può usare una variabile o qualsiasi espressione in PHP come nome del blocco. {/ifset} ``` +L'esistenza di blocchi viene restituita anche dalla funzione [`hasBlock()` |functions#hasBlock]: + +```latte +{if hasBlock(header) || hasBlock(footer)} + ... +{/if} +``` + Suggerimenti .[#toc-tips] ------------------------- diff --git a/latte/ja/functions.texy b/latte/ja/functions.texy index 6adc243ba1..ddc615545c 100644 --- a/latte/ja/functions.texy +++ b/latte/ja/functions.texy @@ -9,6 +9,7 @@ PHPの一般的な関数に加え、テンプレートでも使用すること |`divisibleBy`|[ある変数がある数値で割り切れるかどうかをチェックします|#divisibleBy] |`even` |[与えられた数値が偶数かどうかをチェックします|#even] |`first` | [配列の最初の要素または文字列の文字を返します|#first] +|`hasBlock` |[ブロックの存在を検出する |#hasBlock] |`last` | [配列の最後の要素、または文字列の文字を返す|#last] |`odd` | [与えられた数が奇数かどうかをチェックする|#odd] |`slice` | [配列または文字列のスライスを抽出します|#slice] @@ -85,6 +86,17 @@ first(string|array $value): mixed .[method] [last |#last],[filter first |filters#first] も参照してください。 +hasBlock(string $name): bool .[method]{data-version:3.0.10} +----------------------------------------------------------- +指定された名前のブロックが存在するかどうかをチェックする: + +```latte +{if hasBlock(header)} ... {/if} +``` + +[ブロック存在チェックも |template-inheritance#Checking Block Existence]参照のこと。 + + last(string|array $value): mixed .[method] ------------------------------------------ 配列の最後の要素または文字列の文字を返します。 diff --git a/latte/ja/template-inheritance.texy b/latte/ja/template-inheritance.texy index cbdf021eeb..a1fb0e9823 100644 --- a/latte/ja/template-inheritance.texy +++ b/latte/ja/template-inheritance.texy @@ -396,6 +396,14 @@ Hi, I am Mary. {/ifset} ``` +ブロックの存在は、関数 [`hasBlock()` |functions#hasBlock]: + +```latte +{if hasBlock(header) || hasBlock(footer)} + ... +{/if} +``` + ヒント .[#toc-tips] ---------------- diff --git a/latte/pl/functions.texy b/latte/pl/functions.texy index 982fd3cd98..f84579a8cf 100644 --- a/latte/pl/functions.texy +++ b/latte/pl/functions.texy @@ -9,6 +9,7 @@ Oprócz zwykłych funkcji PHP, w szablonach możemy używać także następując | `divisibleBy`| [sprawdza, czy zmienna jest podzielna przez liczbę |#divisibleBy] | `even` | [sprawdza, czy podana liczba jest parzysta |#even] | `first` | [zwraca pierwszy element tablicy lub znak łańcucha|#first] +| `hasBlock` | [wykrywa istnienie bloku |#hasBlock] | `last` | [zwraca ostatni element tablicy lub znak łańcucha|#last] | `odd` | [sprawdza, czy podana liczba jest nieparzysta |#odd] | `slice` | [wyciąga część tablicy lubłańcucha |#slice] @@ -85,6 +86,17 @@ Zwraca pierwszy element tablicy lub znak łańcucha: Zobacz także [last |#last], [filter first |filters#first]. +hasBlock(string $name): bool .[method]{data-version:3.0.10} +----------------------------------------------------------- +Sprawdza, czy blok o podanej nazwie istnieje: + +```latte +{if hasBlock(header)} ... {/if} +``` + +Zobacz także [sprawdzanie istnienia |template-inheritance#Checking Block Existence] bloku. + + last(string|array $value): mixed .[method] ------------------------------------------ Zwraca ostatni element tablicy lub znak łańcucha: diff --git a/latte/pl/template-inheritance.texy b/latte/pl/template-inheritance.texy index 6e7ef1a424..2488266e2b 100644 --- a/latte/pl/template-inheritance.texy +++ b/latte/pl/template-inheritance.texy @@ -396,6 +396,14 @@ Nazwa bloku może być zmienną lub dowolnym wyrażeniem PHP. W tym przypadku do {/ifset} ``` +Istnienie bloków jest również zwracane przez funkcję [`hasBlock()` |functions#hasBlock]: + +```latte +{if hasBlock(header) || hasBlock(footer)} + ... +{/if} +``` + Porady .[#toc-tips] ------------------- diff --git a/latte/pt/functions.texy b/latte/pt/functions.texy index bd63907721..bfd206883b 100644 --- a/latte/pt/functions.texy +++ b/latte/pt/functions.texy @@ -9,6 +9,7 @@ Além das funções comuns do PHP, você também pode usá-las em modelos. | `divisibleBy`| [verifica se uma variável é divisível por um número |#divisibleBy] | `even` | [verifica se o número dado é igual |#even] | `first` | [devolve o primeiro elemento de matriz ou caráter de cadeia |#first] +| `hasBlock` | [detecta a existência de um bloco |#hasBlock] | `last` | [retorna o último elemento de matriz ou caráter de cadeia |#last] | `odd` | [verifica se o número dado é ímpar |#odd] | `slice` | [extrai uma fatia de uma matriz ou um fio |#slice] @@ -85,6 +86,17 @@ Devolve o primeiro elemento de matriz ou caráter de corda: Ver também [por último |#last], [filtrar primeiro |filters#first]. +hasBlock(string $name): bool .[method]{data-version:3.0.10} +----------------------------------------------------------- +Verifica se o bloco com o nome especificado existe: + +```latte +{if hasBlock(header)} ... {/if} +``` + +Consulte também [verificação de existência de bloco |template-inheritance#Checking Block Existence]. + + last(string|array $value): mixed .[method] ------------------------------------------ Retorna o último elemento de matriz ou caráter de corda: diff --git a/latte/pt/template-inheritance.texy b/latte/pt/template-inheritance.texy index 387f5a8b90..2a426f0cd7 100644 --- a/latte/pt/template-inheritance.texy +++ b/latte/pt/template-inheritance.texy @@ -396,6 +396,14 @@ Você pode usar uma variável ou qualquer expressão em PHP como o nome do bloco {/ifset} ``` +A existência de blocos também é retornada pela função [`hasBlock()` |functions#hasBlock]: + +```latte +{if hasBlock(header) || hasBlock(footer)} + ... +{/if} +``` + Dicas .[#toc-tips] ------------------ diff --git a/latte/ro/functions.texy b/latte/ro/functions.texy index 66b2446f2a..df509a269a 100644 --- a/latte/ro/functions.texy +++ b/latte/ro/functions.texy @@ -9,6 +9,7 @@ Funcții Latte | `divisibleBy`| [verifică dacă o variabilă este divizibilă cu un număr |#divisibleBy] | `even` | [verifică dacă numărul dat este par |#even] | `first` | [returnează primul element al unui array sau caracterul unui șir de caractere|#first] +| `hasBlock` | [detectează existența unui bloc |#hasBlock] | `last` | [returnează ultimul element al unui array sau caracter al unui șir de caractere|#last] | `odd` | [verifică dacă numărul dat este impar |#odd] | `slice` | [extrage o porțiune dintr-un tablou sau un șir de caractere |#slice] @@ -85,6 +86,17 @@ Returnează primul element al unui tablou sau caracterul unui șir de caractere: A se vedea, de asemenea, [last |#last], [filter first |filters#first]. +hasBlock(string $name): bool .[method]{data-version:3.0.10} +----------------------------------------------------------- +Verifică dacă blocul cu numele specificat există: + +```latte +{if hasBlock(header)} ... {/if} +``` + +A se vedea, de asemenea, [verificarea existenței blocului |template-inheritance#Checking Block Existence]. + + last(string|array $value): mixed .[method] ------------------------------------------ Returnează ultimul element al unui array sau caracter al unui șir de caractere: diff --git a/latte/ro/template-inheritance.texy b/latte/ro/template-inheritance.texy index 07ed567969..77075ed241 100644 --- a/latte/ro/template-inheritance.texy +++ b/latte/ro/template-inheritance.texy @@ -396,6 +396,14 @@ Puteți utiliza o variabilă sau orice expresie din PHP ca nume de bloc. În ace {/ifset} ``` +Existența blocurilor este, de asemenea, returnată de funcția [`hasBlock()` |functions#hasBlock]: + +```latte +{if hasBlock(header) || hasBlock(footer)} + ... +{/if} +``` + Sfaturi .[#toc-tips] -------------------- diff --git a/latte/ru/functions.texy b/latte/ru/functions.texy index 27cbf161a6..a7a60b6dd0 100644 --- a/latte/ru/functions.texy +++ b/latte/ru/functions.texy @@ -9,6 +9,7 @@ | `divisibleBy`| [проверяет, делится ли переменная на число |#divisibleBy] | `even` | [проверяет, является ли данное число четным |#even] | `first` | [возвращает первый элемент массива или символ строки |#first] +| `hasBlock` | [обнаруживает существование блока |#hasBlock] | `last` | [возвращает последний элемент массива или символ строки |#last] | `odd` | [проверяет, является ли данное число нечетным |#odd] | `slice` | [извлекает фрагмент массива или строки |#slice] @@ -85,6 +86,17 @@ first(string|array $value): mixed .[method] См. также [last |#last], [filter first |filters#first]. +hasBlock(string $name): bool .[method]{data-version:3.0.10} +----------------------------------------------------------- +Проверяет, существует ли блок с указанным именем: + +```latte +{if hasBlock(header)} ... {/if} +``` + +См. также [Проверка существования блока |template-inheritance#Checking Block Existence]. + + last(string|array $value): mixed .[method] ------------------------------------------ Возвращает последний элемент массива или символ строки: diff --git a/latte/ru/template-inheritance.texy b/latte/ru/template-inheritance.texy index e229486d33..bc728af54a 100644 --- a/latte/ru/template-inheritance.texy +++ b/latte/ru/template-inheritance.texy @@ -396,6 +396,14 @@ Hi, I am Mary. {/ifset} ``` +Информация о существовании блоков также возвращается функцией [`hasBlock()` |functions#hasBlock]: + +```latte +{if hasBlock(header) || hasBlock(footer)} + ... +{/if} +``` + Советы .[#toc-tips] ------------------- diff --git a/latte/sl/functions.texy b/latte/sl/functions.texy index f37f7176f4..27deaca0b0 100644 --- a/latte/sl/functions.texy +++ b/latte/sl/functions.texy @@ -9,6 +9,7 @@ Poleg običajnih funkcij PHP lahko v predlogah uporabljate tudi te. | `divisibleBy`| [preveri, ali je spremenljivka deljiva s številom |#divisibleBy] | `even` | [preveri, ali je dano število sodo |#even] | `first` | [vrne prvi element polja ali znak niza |#first] +| `hasBlock` | [zazna obstoj bloka |#hasBlock] | `last` | [vrne zadnji element polja ali znak niza |#last] | `odd` | [preveri, ali je podano število liho |#odd] | `slice` | [izvleče rezino polja ali niza |#slice] @@ -85,6 +86,17 @@ Vrne prvi element polja ali znak niza: Glej tudi [last |#last], [filter first |filters#first]. +hasBlock(string $name): bool .[method]{data-version:3.0.10} +----------------------------------------------------------- +Preveri, ali obstaja blok z navedenim imenom: + +```latte +{if hasBlock(header)} ... {/if} +``` + +Glej tudi [preverjanje obstoja bloka |template-inheritance#Checking Block Existence]. + + last(string|array $value): mixed .[method] ------------------------------------------ Vrne zadnji element polja ali znak niza: diff --git a/latte/sl/template-inheritance.texy b/latte/sl/template-inheritance.texy index 1962057513..e5b6da9144 100644 --- a/latte/sl/template-inheritance.texy +++ b/latte/sl/template-inheritance.texy @@ -396,6 +396,14 @@ Kot ime bloka lahko uporabite spremenljivko ali kateri koli izraz v jeziku PHP. {/ifset} ``` +Obstoj blokov vrne tudi funkcija [`hasBlock()` |functions#hasBlock]: + +```latte +{if hasBlock(header) || hasBlock(footer)} + ... +{/if} +``` + Nasveti .[#toc-tips] -------------------- diff --git a/latte/tr/functions.texy b/latte/tr/functions.texy index 5cef94e584..7f5a577996 100644 --- a/latte/tr/functions.texy +++ b/latte/tr/functions.texy @@ -9,6 +9,7 @@ Yaygın PHP işlevlerine ek olarak, bunları şablonlarda da kullanabilirsiniz. | `divisibleBy`| [bir değişkenin bir sayıya bölünebilir olup olmadığını kontroleder|#divisibleBy] | `even` | [verilen sayının çift olup olmadığını kontroleder |#even] | `first` | [dizinin ilk elemanını veya karakter dizisini döndürür |#first] +| `hasBlock` | [bir bloğun varlığını tespit |#hasBlock] eder | `last` | [dizinin son elemanını veya karakter dizisini döndürür |#last] | `odd` | [verilen sayının tek olup olmadığını kontroleder |#odd] | `slice` | [bir dizi veya dizenin bir dilimini çıkarır |#slice] @@ -85,6 +86,17 @@ Dizinin ilk elemanını veya karakter dizisini döndürür: Ayrıca bkz. [last |#last], [filter first |filters#first]. +hasBlock(string $name): bool .[method]{data-version:3.0.10} +----------------------------------------------------------- +Belirtilen addaki bloğun var olup olmadığını kontrol eder: + +```latte +{if hasBlock(header)} ... {/if} +``` + +Ayrıca bkz. [blok varlık kontrolü |template-inheritance#Checking Block Existence]. + + last(string|array $value): mixed .[method] ------------------------------------------ Dizinin son elemanını veya karakter dizisini döndürür: diff --git a/latte/tr/template-inheritance.texy b/latte/tr/template-inheritance.texy index 8356a88f6f..92db9e8c6c 100644 --- a/latte/tr/template-inheritance.texy +++ b/latte/tr/template-inheritance.texy @@ -396,6 +396,14 @@ PHP'de blok adı olarak bir değişken veya herhangi bir ifade kullanabilirsiniz {/ifset} ``` +Blokların varlığı da fonksiyon tarafından döndürülür [`hasBlock()` |functions#hasBlock]: + +```latte +{if hasBlock(header) || hasBlock(footer)} + ... +{/if} +``` + İpuçları .[#toc-tips] --------------------- diff --git a/latte/uk/functions.texy b/latte/uk/functions.texy index dcd6d83ca4..f7966a08b9 100644 --- a/latte/uk/functions.texy +++ b/latte/uk/functions.texy @@ -9,6 +9,7 @@ | `divisibleBy`| [перевіряє, чи ділиться змінна на число |#divisibleBy] | `even` | [перевіряє, чи є дане число парним |#even] | `first` | [повертає перший елемент масиву або символ рядка |#first] +| `hasBlock` | [виявляє наявність блоку |#hasBlock] | `last` | [pповертає останній елемент масиву або символ рядка |#last] | `odd` | [перевіряє, чи є дане число непарним |#odd] | `slice` | [витягує фрагмент масиву або рядка |#slice] @@ -85,6 +86,17 @@ first(string|array $value): mixed .[method] Див. також [last |#last], [filter first |filters#first]. +hasBlock(string $name): bool .[method]{data-version:3.0.10} +----------------------------------------------------------- +Перевіряє, чи існує блок з вказаною назвою: + +```latte +{if hasBlock(header)} ... {/if} +``` + +Див. також [перевірка існування блоку |template-inheritance#Checking Block Existence]. + + last(string|array $value): mixed .[method] ------------------------------------------ Повертає останній елемент масиву або символ рядка: diff --git a/latte/uk/template-inheritance.texy b/latte/uk/template-inheritance.texy index 3563a28690..0db6e1062e 100644 --- a/latte/uk/template-inheritance.texy +++ b/latte/uk/template-inheritance.texy @@ -396,6 +396,14 @@ Hi, I am Mary. {/ifset} ``` +Існування блоків також повертається функцією [`hasBlock()` |functions#hasBlock]: + +```latte +{if hasBlock(header) || hasBlock(footer)} + ... +{/if} +``` + Поради .[#toc-tips] ------------------- From 12e2d549cba7d9bbc61c3555b7a82a7d2eee7e88 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sat, 14 Oct 2023 00:09:13 +0200 Subject: [PATCH 022/137] services: improved text --- dependency-injection/bg/services.texy | 376 ++++++++++++------------- dependency-injection/cs/services.texy | 350 +++++++++++------------ dependency-injection/de/services.texy | 372 ++++++++++++------------- dependency-injection/el/services.texy | 378 ++++++++++++------------- dependency-injection/en/services.texy | 368 ++++++++++++------------ dependency-injection/es/services.texy | 372 ++++++++++++------------- dependency-injection/fr/services.texy | 372 ++++++++++++------------- dependency-injection/hu/services.texy | 374 ++++++++++++------------- dependency-injection/it/services.texy | 376 ++++++++++++------------- dependency-injection/ja/services.texy | 374 ++++++++++++------------- dependency-injection/pl/services.texy | 384 +++++++++++++------------- dependency-injection/pt/services.texy | 384 +++++++++++++------------- dependency-injection/ro/services.texy | 366 ++++++++++++------------ dependency-injection/ru/services.texy | 382 ++++++++++++------------- dependency-injection/sl/services.texy | 370 ++++++++++++------------- dependency-injection/tr/services.texy | 368 ++++++++++++------------ dependency-injection/uk/services.texy | 382 ++++++++++++------------- 17 files changed, 3055 insertions(+), 3293 deletions(-) diff --git a/dependency-injection/bg/services.texy b/dependency-injection/bg/services.texy index ad35504555..4a706d4a28 100644 --- a/dependency-injection/bg/services.texy +++ b/dependency-injection/bg/services.texy @@ -2,32 +2,32 @@ ********************* .[perex] -Конфигурацията е мястото, където поставяме дефинициите на потребителските услуги. Това е направено в раздела `services`. +Конфигурацията е мястото, където даваме указания на контейнера DI как да сглобява отделните услуги и как да ги свързва с други зависимости. Nette предоставя много ясен и елегантен начин за постигане на това. -Например, така създаваме услуга с име `database`, която ще бъде инстанция на класа `PDO`: +Разделът `services` в конфигурационния файл NEON е мястото, където дефинираме нашите потребителски услуги и техните конфигурации. Нека разгледаме прост пример за дефиниране на услуга с име `database`, която представлява инстанция на класа `PDO`: ```neon services: database: PDO('sqlite::memory:') ``` -Наименованията на услугите се използват, за да можем да [се обръщаме към |#Referencing-Services] тях. Ако услугата не се споменава, не е необходимо да ѝ давате име. Затова просто използваме двоеточие вместо име: +Тази конфигурация води до следния фабричен метод в [контейнера DI |container]: -```neon -services: - - PDO('sqlite::memory:') # анонимный сервис +```php +public function createServiceDatabase(): PDO +{ + return new PDO('sqlite::memory:'); +} ``` -Запис на един ред може да бъде разделен на няколко реда, за да се позволи добавянето на допълнителни клавиши, напр. за [настройка |#setup]. Псевдонимът на ключа `create:` е `factory:`. +Имената на услугите ни позволяват да се позоваваме на тях в други части на конфигурационния файл, като използваме формата `@serviceName`. Ако няма нужда да даваме име на услугата, можем просто да използваме точка: ```neon services: - database: - create: PDO('sqlite::memory:') - setup: ... + - PDO('sqlite::memory:') ``` -След това извличаме услугата от контейнера DI, като използваме метода `getService()` по име или още по-добре - метода `getByType()` по тип: +За да извлечем услуга от контейнера DI, можем да използваме метода `getService()` с името на услугата като параметър или метода `getByType()` с типа на услугата: ```php $database = $container->getService('database'); @@ -35,236 +35,114 @@ $database = $container->getByType(PDO::class); ``` -Създаване на услуга .[#toc-creating-a-service] -============================================== +Създаване на услуги .[#toc-service-creation] +============================================ -В повечето случаи създаваме услуга, като просто създаваме инстанция на класа: +Най-често създаваме услуга, като просто инстанцираме определен клас. Например: ```neon services: database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` -Което ще създаде фабричен метод в [DI-контейнера |container]: - -```php -public function createServiceDatabase(): PDO -{ - return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret'); -} -``` - -Алтернативно, ключът `arguments` може да се използва за предаване на [аргументи |#Arguments]: +Ако трябва да разширим конфигурацията с допълнителни ключове, дефиницията може да се разшири на няколко реда: ```neon services: database: - create: PDO - arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] -``` - -Статичен метод също може да създаде услуга: - -```neon -services: - database: My\Database::create(root, secret) + create: PDO('sqlite::memory:') + setup: ... ``` -Това е еквивалентно на код на PHP: +Ключът `create` има псевдоним `factory`, като и двете версии са често срещани в практиката. Въпреки това препоръчваме да използвате `create`. -```php -public function createServiceDatabase(): PDO -{ - return My\Database::create('root', 'secret'); -} -``` - -Предполага се, че статичният метод `My\Database::create()` има определена връщана стойност, която контейнерът DI трябва да знае. Ако няма такъв, записваме типа в конфигурацията: +Аргументите на конструктора или методът за създаване могат алтернативно да бъдат записани в ключа `arguments`: ```neon services: database: - create: My\Database::create(root, secret) - type: PDO + create: PDO + arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] ``` -Nette DI ви предоставя изключително мощни инструменти за изразяване, които ви позволяват да пишете почти всичко. Например за [препращане към |#Referencing-Services] друга услуга и извикване на нейния метод. За улеснение се използва `::` вместо `->`. +Не е задължително услугите да се създават само чрез просто инстанциране на клас; те могат да се създават и в резултат на извикване на статични методи или методи на други услуги: ```neon services: - routerFactory: App\Router\Factory + database: DatabaseFactory::create() router: @routerFactory::create() ``` -Това е еквивалентно на код на PHP: +Обърнете внимание, че за опростяване вместо `->`, използваме `::`, вж. [изразните средства |#expression means]. Тези фабрични методи се генерират: ```php -public function createServiceRouterFactory(): App\Router\Factory +public function createServiceDatabase(): PDO { - return new App\Router\Factory; + return DatabaseFactory::create(); } -public function createServiceRouter(): Router +public function createServiceRouter(): RouteList { return $this->getService('routerFactory')->create(); } ``` -Извикванията на методи могат да бъдат верижно свързани, както в PHP: +Контейнерът DI трябва да знае типа на създадената услуга. Ако създаваме услуга с помощта на метод, който няма определен тип на връщане, трябва изрично да споменем този тип в конфигурацията: ```neon services: - foo: FooFactory::build()::get() -``` - -Това е еквивалентно на код на PHP: - -```php -public function createServiceFoo() -{ - return FooFactory::build()->get(); -} + database: + create: DatabaseFactory::create() + type: PDO ``` Аргументи .[#toc-arguments] =========================== -Именуваните параметри могат да се използват и за предаване на аргументи: +Предаването на аргументи към конструкторите и методите става по начин, много подобен на този в обикновения PHP: ```neon services: - database: PDO( - 'mysql:host=127.0.0.1;dbname=test' # позиционен - username: root # named - password: secret # named - ) -``` - -Използването на запетаи не е задължително, когато аргументите се разделят на няколко реда. - -Разбира се, можем да използваме и [други услуги |#Referencing-Services] или [параметри |configuration#Parameters] като аргументи: - -```neon -services: - - Foo(@anotherService, %appDir%) -``` - -Съответства на кода на PHP: - -```php -public function createService01(): Foo -{ - return new Foo($this->getService('anotherService'), '...'); -} + database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` -Ако първият аргумент е [автоматично монтиран |autowiring] и искате да посочите втория аргумент, пропуснете първия, като използвате `_`, например `Foo(_, %appDir%)`. Или, още по-добре, предайте само втория аргумент като именуван параметър, например: `Foo(path: %appDir%)`. - -Nette DI и форматът NEON ви дават изключително мощно средство за изразяване, което ви позволява да напишете почти всичко. По този начин аргументът може да бъде новосъздаден обект, можете да извикате статични методи, методи от други услуги или дори глобални функции, като използвате специална нотация: +За по-добра четимост можем да изписваме аргументите на отделни редове. В този формат използването на запетаи не е задължително: ```neon services: - analyser: My\Analyser( - FilesystemIterator(%appDir%) # създаване на обект - DateTime::createFromFormat('Y-m-d') # извикване на статичен метод - @anotherService # предаване на друга услуга - @http.request::getRemoteAddress() # извикване на друг метод на услугата - ::getenv(NetteMode) # извикване на глобална функция + database: PDO( + 'mysql:host=127.0.0.1;dbname=test' + root + secret ) ``` -Съответства на кода на PHP: - -```php -public function createServiceAnalyser(): My\Analyser -{ - return new My\Analyser( - new FilesystemIterator('...'), - DateTime::createFromFormat('Y-m-d'), - $this->getService('anotherService'), - $this->getService('http.request')->getRemoteAddress(), - getenv('NetteMode') - ); -} -``` - - -Специални функции .[#toc-special-functions] -------------------------------------------- - -Можете също така да използвате специални функции в аргументите, за да изравнявате или отричате стойности: - -- `not(%arg%)` отрицание -- `bool(%arg%)` преобразуване на bool без загуби -- `int(%arg%)` преобразуване на int без загуби -- `float(%arg%)` преобразуване на плаващо състояние без загуби -- `string(%arg%)` преобразуване на низове без загуби +Можете също така да назовете аргументите, което ви позволява да не се притеснявате за реда им: ```neon services: - - Foo( - id: int(::getenv('ProjectId')) - productionMode: not(%debugMode%) + database: PDO( + username: root + password: secret + dsn: 'mysql:host=127.0.0.1;dbname=test' ) ``` -Презаписването без загуби се различава от нормалното презаписване в PHP, например с помощта на `(int)`, по това, че хвърля изключение за нецифрови стойности. - -Като аргументи могат да бъдат подадени няколко услуги. Масив от всички услуги от определен тип (т.е. клас или интерфейс) може да бъде създаден чрез функцията `typed()`. Функцията ще пропусне услуги, при които автоматичното свързване е забранено, и могат да бъдат зададени няколко типа, разделени със запетая. +Ако желаете да пропуснете някои аргументи и да използвате стойностите им по подразбиране или да вмъкнете услуга чрез [автоматично свързване |autowiring], използвайте долна черта: ```neon services: - - BarsDependent( typed(Bar) ) -``` - -Можете също така да предадете масив от услуги автоматично, като използвате [автоматично свързване |autowiring#Collection-of-Services]. - -Чрез функцията `tagged()` се създава масив от всички услуги с определен [етикет |#Tags]. Можете да посочите няколко тага, разделени със запетая. - -```neon -services: - - LoggersDependent( tagged(logger) ) + foo: Foo(_, %appDir%) ``` - -Връзки към услуги .[#toc-referencing-services] -============================================== - -Връзките към отделните услуги се използват със символа `@` и имени, например `@database`: - -```neon -services: - - create: Foo(@database) - setup: - - setCacheStorage(@cache.storage) -``` - -Съответства на кода на PHP: - -```php -public function createService01(): Foo -{ - $service = new Foo($this->getService('database')); - $service->setCacheStorage($this->getService('cache.storage')); - return $service; -} -``` - -Дори към анонимни услуги може да се направи препратка чрез обратно извикване, като вместо името им се посочи техният тип (клас или интерфейс). Това обаче обикновено не е необходимо поради [автоматичното препращане |autowiring]. - -```neon -services: - - create: Foo(@Nette\Database\Connection) - setup: - - setCacheStorage(@cache.storage) -``` +Аргументите могат да бъдат услуги, параметри и много други, вижте [изразни средства |#expression means]. Настройка .[#toc-setup] ======================= -В раздела `setup` са изброени методите, които ще бъдат извикани при създаването на услугата: +В раздела `setup` дефинираме методите, които трябва да се извикат при създаването на услугата. ```neon services: @@ -274,7 +152,7 @@ services: - setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) ``` -Съответства на кода на PHP: +В PHP това би изглеждало така: ```php public function createServiceDatabase(): PDO @@ -285,8 +163,7 @@ public function createServiceDatabase(): PDO } ``` -Могат да се задават и свойства. Добавянето на елемент в масив също се поддържа и трябва да се запише в кавички, за да не противоречи на синтаксиса на NEON: - +В допълнение към извикването на методи, можете също така да предавате стойности на свойствата. Добавянето на елемент към масив също се поддържа, но трябва да го оградите в кавички, за да избегнете колизия със синтаксиса на NEON: ```neon services: @@ -297,7 +174,7 @@ services: - '$onClick[]' = [@bar, clickHandler] ``` -Съответства на кода на PHP: +В PHP това ще се преведе като: ```php public function createServiceFoo(): Foo @@ -309,8 +186,7 @@ public function createServiceFoo(): Foo } ``` -В конфигурацията обаче могат да се извикват и статични методи или методи на други услуги. Ние им предаваме действителната услуга като `@self`: - +В настройката можете също така да извиквате статични методи или методи на други услуги. Ако трябва да предадете текущата услуга като аргумент, използвайте `@self`: ```neon services: @@ -321,7 +197,7 @@ services: - @anotherService::setFoo(@self) ``` -Съответства на кода на PHP: +Обърнете внимание, че за опростяване вместо `->`, използваме `::`, вижте [изразните средства |#expression means]. Това генерира следния фабричен метод: ```php public function createServiceFoo(): Foo @@ -334,23 +210,133 @@ public function createServiceFoo(): Foo ``` -Автоматично обвързване .[#toc-autowiring] -========================================= +Средства за изразяване .[#toc-expression-means] +=============================================== + +Nette DI ни предоставя изключително богати възможности за изразяване, което ни позволява да изразим почти всичко. В конфигурационните файлове можем да използваме [параметри |configuration#parameters]: + +```neon +# параметър +%wwwDir% + +# стойност под ключ на параметър +%mailer.user% + +# параметър в рамките на низ +'%wwwDir%/images' +``` + +Можем също така да създаваме обекти, да извикваме методи и функции: + +```neon +# създаване на обект +DateTime() + +# извикване на статичен метод +Collator::create(%locale%) + +# извикване на функция на PHP +::getenv(DB_USER) +``` + +Услугите се наричат по име или по тип: + +```neon +# услуга по име +@database + +# услуга по тип +@Nette\Database\Connection +``` + +Използвайте константи: + +```neon +# клас константа +FilesystemIterator::SKIP_DOTS + +# глобална константа, получена чрез PHP функцията constant() +::constant(PHP_VERSION) +``` + +Извикванията на методите могат да бъдат верижно свързани, точно както в PHP. За улеснение, вместо `->`, използваме `::`: + +```neon +DateTime()::format('Y-m-d') +# PHP: (new DateTime())->format('Y-m-d') + +@http.request::getUrl()::getHost() +# PHP: $this->getService('http.request')->getUrl()->getHost() +``` + +Тези изрази могат да се използват навсякъде при [създаване на услуги |#Service Creation], в [аргументи |#Arguments], в секцията за [настройка |#setup] или в [параметри |configuration#parameters]: + +```neon +parameters: + ipAddress: @http.request::getRemoteAddress() + +services: + database: + create: DatabaseFactory::create( @anotherService::getDsn() ) + setup: + - initialize( ::getenv('DB_USER') ) +``` + + +Специални функции .[#toc-special-functions] +------------------------------------------- + +В рамките на конфигурационните файлове можете да използвате тези специални функции: + +- `not()` за отричане на стойности +- `bool()`, `int()`, `float()`, `string()` за привеждане на типове без загуби +- `typed()` за генериране на масив от всички услуги от определен тип +- `tagged()` за създаване на масив от всички услуги с даден етикет + +```neon +services: + - Foo( + id: int(::getenv('ProjectId')) + productionMode: not(%debugMode%) + ) +``` + +В сравнение с конвенционалното типизиране в PHP, като например `(int)`, типизирането без загуби ще хвърля изключение за нецифрови стойности. + +Функцията `typed()` създава масив от всички услуги от определен тип (клас или интерфейс). Тя изключва услуги с изключено автоматично свързване. Могат да бъдат зададени няколко типа, разделени със запетаи. + +```neon +services: + - BarsDependent( typed(Bar) ) +``` + +Можете също така автоматично да подадете масив от услуги от определен тип като аргумент, като използвате [автоподразбиране |autowiring#Collection of Services]. + +Функцията `tagged()` създава масив от всички услуги с определен етикет. Могат да бъдат изброени няколко тага, разделени със запетаи. + +```neon +services: + - LoggersDependent( tagged(logger) ) +``` + + +Автоматично окабеляване .[#toc-autowiring] +========================================== -Ключът `autowired` може да се използва за изключване на услуга от автоматично свързване или за повлияване на нейното поведение. За повече информация вижте глава [Автоматично обвързване |autowiring]. +Ключът `autowired` ви позволява да променяте поведението на автоматичното свързване за определена услуга. За повече подробности вижте [главата за автоматичното свързване |autowiring]. ```neon services: foo: create: Foo - autowired: false # foo е премахнат от автовръзката + autowired: false # услугата foo е изключена от автоматичното свързване ``` Етикети .[#toc-tags] ==================== -Информацията за потребителя може да бъде добавена към отделните услуги под формата на тагове: +Етикетите се използват за добавяне на допълнителна информация към услугите. Можете да зададете един или повече тагове на услуга: ```neon services: @@ -360,7 +346,7 @@ services: - cached ``` -Етикетите също могат да бъдат значими: +Таговете могат да носят и стойности: ```neon services: @@ -370,26 +356,26 @@ services: logger: monolog.logger.event ``` -Масив от услуги с дефинирани тагове може да бъде предаден като аргумент с помощта на функцията `tagged()`. Могат да бъдат зададени и няколко тага, разделени със запетая. +За извличане на всички услуги с определени тагове можете да използвате функцията `tagged()`: ```neon services: - LoggersDependent( tagged(logger) ) ``` -Имената на услугите могат да бъдат получени от контейнера DI чрез метода `findByTag()`: +В контейнера DI можете да получите имената на всички услуги с определен таг, като използвате метода `findByTag()`: ```php $names = $container->findByTag('logger'); // $names е масив, съдържащ името на услугата и стойността на тага -// например ['foo' => 'monolog.logger.event', ...] +// напр. ['foo' => 'monolog.logger.event', ...] ``` -Режим на изпълнение .[#toc-inject-mode] -======================================= +Режим на инжектиране .[#toc-inject-mode] +======================================== -Флагът `inject: true` се използва за активиране на прехвърлянето на зависимости чрез публични променливи с помощта на анотацията [inject |best-practices:inject-method-attribute#Inject Attributes] и методите [inject*() |best-practices:inject-method-attribute#inject Methods]. +Използването на флага `inject: true` активира предаването на зависимости чрез публични променливи с анотацията [inject |best-practices:inject-method-attribute#Inject Attributes] и методите [inject*() |best-practices:inject-method-attribute#inject Methods]. ```neon services: @@ -398,13 +384,13 @@ services: inject: true ``` -По подразбиране `inject` е активиран само за предварително засяване. +По подразбиране `inject` е активиран само за презентатори. -Промяна на услугите .[#toc-modification-of-services] -==================================================== +Промени в услугата .[#toc-service-modifications] +================================================ -В контейнера DI има редица услуги, които са добавени от вграденото или [вашето разширение |#di-extension]. Дефинициите на тези услуги могат да се променят в конфигурацията. Например за услугата `application.application`, която по подразбиране е обектът `Nette\Application\Application`, можем да променим класа: +Контейнерът DI съдържа много услуги, добавени чрез вградени или [потребителски разширения |#extensions]. Можете да променяте дефинициите на тези услуги директно в конфигурацията. Например, можете да промените класа на услугата `application.application`, която традиционно е `Nette\Application\Application`, на нещо друго: ```neon services: @@ -415,7 +401,7 @@ services: Флагът `alteration` е информативен и показва, че просто модифицираме съществуваща услуга. -Можем да добавим и `setup`: +Можем също така да допълним настройката: ```neon services: @@ -426,7 +412,7 @@ services: - '$onStartup[]' = [@resource, init] ``` -При пренаписване на услугата можем да изтрием първоначалните аргументи, елементи на `setup` или тагове, за които е `reset`: +Когато презаписвате услуга, може да искате да премахнете оригиналните аргументи, елементи на настройката или тагове, което е мястото, където `reset` е полезен: ```neon services: @@ -439,7 +425,7 @@ services: - tags ``` -Услуга, добавена от разширение, може също да бъде премахната от контейнера: +Ако искате да премахнете услуга, добавена от разширение, можете да го направите по следния начин: ```neon services: diff --git a/dependency-injection/cs/services.texy b/dependency-injection/cs/services.texy index 2bb322dff7..d01aacec4e 100644 --- a/dependency-injection/cs/services.texy +++ b/dependency-injection/cs/services.texy @@ -2,32 +2,32 @@ Definování služeb ***************** .[perex] -Konfigurace je místem, kam umísťujeme definice vlastních služeb. Slouží k tomu sekce `services`. +Konfigurace je místem, kde učíme DI kontejner, jak má sestavovat jednotlivé služby a jak je propojovat s dalšími závislostmi. Nette poskytuje velice přehledný a elegantní způsob, jak toho dosáhnout. -Například takto vytvoříme službu pojmenovanou `database`, což bude instance třídy `PDO`: +Sekce `services` v konfiguračním souboru formátu NEON je místem, kde definujeme vlastní služby a jejich konfigurace. Podívejme se na jednoduchý příklad definice služby pojmenované `database`, která reprezentuje instanci třídy `PDO`: ```neon services: database: PDO('sqlite::memory:') ``` -Pojmenování služeb slouží k tomu, abychom se na ně mohli [odkazovat|#Odkazování na služby]. Pokud na službu není odkazováno, není ji potřeba pojmenovávat. Místo názvu tak použijeme jen odrážku: +Uvedená konfigurace vyústí v následující tovární metodu v [DI kontejneru|container]: -```neon -services: - - PDO('sqlite::memory:') # anonymní služba +```php +public function createServiceDatabase(): PDO +{ + return new PDO('sqlite::memory:'); +} ``` -Jednořádkový zápis lze rozepsat do více řádků a tak umožnit přidání dalších klíčů, jako je například [#setup]. Aliasem pro klíč `create:` je `factory:`. +Názvy služeb nám umožňují odkazovat se na ně v dalších částech konfiguračního souboru, a to ve formátu `@nazevSluzby`. Pokud není potřeba službu pojmenovávat, můžeme jednoduše použít pouze odrážku: ```neon services: - database: - create: PDO('sqlite::memory:') - setup: ... + - PDO('sqlite::memory:') ``` -Službu poté získáme z DI kontejneru metodou `getService()` podle názvu, nebo ještě lépe metodou `getByType()` podle typu: +Pro získání služby z DI kontejneru můžeme využít metodu `getService()` s názvem služby jako parametrem, nebo metodu `getByType()` s typem služby: ```php $database = $container->getService('database'); @@ -38,233 +38,111 @@ $database = $container->getByType(PDO::class); Vytvoření služby ================ -Nejčastěji službu vytváříme prostým vytvořením instance určité třídy: +Většinou vytváříme službu jednoduše tím, že vytvoříme instanci určité třídy. Například: ```neon services: database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` -Což vygeneruje tovární metodu v [DI kontejneru|container]: - -```php -public function createServiceDatabase(): PDO -{ - return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret'); -} -``` - -Pro předání [argumentů|#Argumenty] lze alternativně použít i klíč `arguments`: +Pokud potřebujeme konfiguraci rozšířit o další klíče, lze definici rozepsat do více řádků: ```neon services: database: - create: PDO - arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] -``` - -Službu může vytvořit také statická metoda: - -```neon -services: - database: My\Database::create(root, secret) + create: PDO('sqlite::memory:') + setup: ... ``` -Odpovídá PHP kódu: +Klíč `create` má alias `factory`, obě varianty jsou v praxi běžné. Nicméně doporučujeme používat `create`. -```php -public function createServiceDatabase(): PDO -{ - return My\Database::create('root', 'secret'); -} -``` - -Předpokládá se, statická metoda `My\Database::create()` má definovanou návratovou hodnotu, kterou DI kontejner potřebuje znát. Pokud ji nemá, zapíšeme typ do konfigurace: +Argumenty konstruktoru nebo vytvářecí metody mohou být alternativně zapsány v klíči `arguments`: ```neon services: database: - create: My\Database::create(root, secret) - type: PDO + create: PDO + arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] ``` -Nette DI nám dává mimořádně silné výrazové prostředky, pomocí kterých můžete zapsat téměř cokoliv. Například se [odkázat|#Odkazování na služby] na jinou službu a zavolat její metodu. Pro jednoduchost se místo `->` používá `::` +Služby nemusí být vytvářeny jen prostým vytvořením instance třídy, mohou být také výsledkem volání statických metod nebo metod jiných služeb: ```neon services: - routerFactory: App\Router\Factory + database: DatabaseFactory::create() router: @routerFactory::create() ``` -Odpovídá PHP kódu: +Všimněte si, že pro jednoduchost se místo `->` používá `::`, viz [#výrazové prostředky]. Vygenerují se tyto tovární metody: ```php -public function createServiceRouterFactory(): App\Router\Factory +public function createServiceDatabase(): PDO { - return new App\Router\Factory; + return DatabaseFactory::create(); } -public function createServiceRouter(): Router +public function createServiceRouter(): RouteList { return $this->getService('routerFactory')->create(); } ``` -Volání metod lze řetězit za sebe stejně jako v PHP: +DI kontejner potřebuje znát typ vytvořené služby. Pokud vytváříme službu pomocí metody, která nemá specifikovaný návratový typ, musíme tento typ explicitně uvést v konfiguraci: ```neon services: - foo: FooFactory::build()::get() -``` - -Odpovídá PHP kódu: - -```php -public function createServiceFoo() -{ - return FooFactory::build()->get(); -} + database: + create: DatabaseFactory::create() + type: PDO ``` Argumenty ========= -Pro předání argumentů lze používat i pojmenované parametry: +Do konstruktoru a metod předáváme argumenty způsobem velmi podobným jako v samotném PHP: ```neon services: - database: PDO( - 'mysql:host=127.0.0.1;dbname=test' # poziční - username: root # pojmenovaný - password: secret # pojmenovaný - ) -``` - -Při rozepsání argumentů do více řádků je používání čárek volitelné. - -Jako argumenty můžeme samozřejmě použít i [jiné služby|#Odkazování na služby] nebo [parametry|configuration#parametry]: - -```neon -services: - - Foo(@anotherService, %appDir%) -``` - -Odpovídá PHP kódu: - -```php -public function createService01(): Foo -{ - return new Foo($this->getService('anotherService'), '...'); -} + database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` -Pokud se má první argument [autowirovat|autowiring] a chceme přitom uvést argument druhý, vynecháme první znakem `_`, tedy např. `Foo(_, %appDir%)`. Nebo ještě lépe předáme jen druhý argument jako pojmenovaný parametr, např. `Foo(path: %appDir%)`. - -Nette DI a formát NEON nám dává mimořádně silné výrazové prostředky, pomocí kterých můžete zapsat téměř cokoliv. Argumentem tak může být nově vytvořený objekt, lze volat statické metody, metody jiných služeb, nebo pomocí speciálního zápisu i globální funkce: +Pro lepší čitelnost můžeme argumenty rozepsat do samostatných řádků. V takovém případě je používání čárek volitelné: ```neon services: - analyser: My\Analyser( - FilesystemIterator(%appDir%) # vytvoření objektu - DateTime::createFromFormat('Y-m-d') # volání statické metody - @anotherService # předání jiné služby - @http.request::getRemoteAddress() # volání metody jiné služby - ::getenv(NetteMode) # volání globální funkce + database: PDO( + 'mysql:host=127.0.0.1;dbname=test' + root + secret ) ``` -Odpovídá PHP kódu: - -```php -public function createServiceAnalyser(): My\Analyser -{ - return new My\Analyser( - new FilesystemIterator('...'), - DateTime::createFromFormat('Y-m-d'), - $this->getService('anotherService'), - $this->getService('http.request')->getRemoteAddress(), - getenv('NetteMode') - ); -} -``` - - -Speciální funkce ----------------- - -V argumentech lze také používat speciální funkce pro přetypování nebo negaci hodnot: - -- `not(%arg%)` negace -- `bool(%arg%)` bezeztrátové přetypování na bool -- `int(%arg%)` bezeztrátové přetypování na int -- `float(%arg%)` bezeztrátové přetypování na float -- `string(%arg%)` bezeztrátové přetypování na string +Argumenty můžete také pojmenovat a nemusíte se pak starat o jejich pořadí: ```neon services: - - Foo( - id: int(::getenv('ProjectId')) - productionMode: not(%debugMode%) + database: PDO( + username: root + password: secret + dsn: 'mysql:host=127.0.0.1;dbname=test' ) ``` -Bezztrátové přetypování se od běžného přetypování v PHP např. pomocí `(int)` liší v tom, že pro nečíselné hodnoty vyhodí výjimku. - -Jako argument lze předávat i více služeb. Pole všech služeb určitého typu (tj. třídy nebo rozhraní) vytvoří funkce `typed()`. Funkce vynechá služby, které mají vypnutý autowiring a lze uvést i více typů oddělených čárkou. +Pokud chcete některé argumenty vynechat a použít jejich výchozí hodnotu nebo dosadit službu pomocí [autowiringu|autowiring], použijte podtržítko: ```neon services: - - BarsDependent( typed(Bar) ) -``` - -Předávat pole služeb můžete i automaticky pomocí [autowiringu|autowiring#Pole služeb]. - -Pole všech služeb s určitým [tagem|#tagy] vytvoří funkce `tagged()`. Lze uvést i více tagů oddělených čárkou. - -```neon -services: - - LoggersDependent( tagged(logger) ) + foo: Foo(_, %appDir%) ``` - -Odkazování na služby -==================== - -Na jednotlivé služby se odkazuje pomocí zavináče a názvu služby, takže například `@database`: - -```neon -services: - - create: Foo(@database) - setup: - - setCacheStorage(@cache.storage) -``` - -Odpovídá PHP kódu: - -```php -public function createService01(): Foo -{ - $service = new Foo($this->getService('database')); - $service->setCacheStorage($this->getService('cache.storage')); - return $service; -} -``` - -I na anonymní služby se lze odkazovat přes zavináč, jen místo názvu uvedeme jejich typ (třídu nebo rozhraní). Tohle ovšem obvykle není potřeba dělat díky [autowiringu|autowiring]. - -```neon -services: - - create: Foo(@Nette\Database\Connection) - setup: - - setCacheStorage(@cache.storage) -``` +Jako argumenty lze předávat služby, používat parametry a mnohem více, viz [#výrazové prostředky]. Setup ===== -V sekci setup uvádíme metody, které se mají zavolat při vytváření služby: +V sekci `setup` definujeme metody, které se mají volat při vytváření služby. ```neon services: @@ -274,7 +152,7 @@ services: - setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) ``` -Odpovídá PHP kódu: +To by v PHP vypadalo takto: ```php public function createServiceDatabase(): PDO @@ -285,8 +163,7 @@ public function createServiceDatabase(): PDO } ``` -Lze také nastavovat hodnoty proměnných. Podporováno je i přidání prvku do pole, které je potřeba zapsat v uvozovkách, aby nekolidovalo se syntaxí NEON: - +Kromě volání metod lze také předávat hodnoty do properties. Podporováno je i přidání prvku do pole, které je potřeba zapsat v uvozovkách, aby nekolidovalo se syntaxí NEON: ```neon services: @@ -297,7 +174,7 @@ services: - '$onClick[]' = [@bar, clickHandler] ``` -Odpovídá PHP kódu: +Což by v PHP kódu vypadalo následovně: ```php public function createServiceFoo(): Foo @@ -309,8 +186,7 @@ public function createServiceFoo(): Foo } ``` -V setupu lze však volat i statické metody nebo metod jiných služeb. Aktuální službu jim předáme jako `@self`: - +V setupu lze však volat i statické metody nebo metody jiných služeb. Pokud potřebujete předat jako argument aktuální službu, uveďte ji jako `@self`: ```neon services: @@ -321,7 +197,7 @@ services: - @anotherService::setFoo(@self) ``` -Odpovídá PHP kódu: +Všimněte si, že pro jednoduchost se místo `->` používá `::`, viz [#výrazové prostředky]. Vygeneruje se taková tovární metoda: ```php public function createServiceFoo(): Foo @@ -334,10 +210,120 @@ public function createServiceFoo(): Foo ``` +Výrazové prostředky +=================== + +Nette DI nám dává mimořádně bohaté výrazové prostředky, pomocí kterých můžeme zapsat téměř cokoliv. V konfiguračních souborech tak můžeme využívat [parametry|configuration#parametry]: + +```neon +# parametr +%wwwDir% + +# hodnota parametru pod klíčem +%mailer.user% + +# parametr uvnitř řetězce +'%wwwDir%/images' +``` + +Dále vytvářet objekty, volat metody a funkce: + +```neon +# vytvoření objektu +DateTime() + +# volání statické metody +Collator::create(%locale%) + +# volání PHP funkce +::getenv(DB_USER) +``` + +Odkazovat se na služby buď jejich jménem nebo pomocí typu: + +```neon +# služba dle názvu +@database + +# služba dle typu +@Nette\Database\Connection +``` + +Používat konstanty: + +```neon +# konstanta třídy +FilesystemIterator::SKIP_DOTS + +# globální konstantu získáme PHP funkcí constant() +::constant(PHP_VERSION) +``` + +Volání metod lze řetězit stejně jako v PHP. Jen pro jednoduchost se místo `->` používá `::`: + +```neon +DateTime()::format('Y-m-d') +# PHP: (new DateTime())->format('Y-m-d') + +@http.request::getUrl()::getHost() +# PHP: $this->getService('http.request')->getUrl()->getHost() +``` + +Tyto výrazy můžete používat kdekoliv, při [vytváření služeb |#Vytvoření služby], v [argumentech |#Argumenty], v sekci [#setup] nebo [parametrech|configuration#parametry]: + +```neon +parameters: + ipAddress: @http.request::getRemoteAddress() + +services: + database: + create: DatabaseFactory::create( @anotherService::getDsn() ) + setup: + - initialize( ::getenv('DB_USER') ) +``` + + +Speciální funkce +---------------- + +V konfiguračních souborech můžete používa tyto speciální funkce: + +- `not()` negace hodnoty +- `bool()`, `int()`, `float()`, `string()` bezeztrátové přetypování na daný typ +- `typed()` vytvoří pole všech služeb specifikovaného typu +- `tagged()` vytvoření pole všech služeb s daným tagem + +```neon +services: + - Foo( + id: int(::getenv('ProjectId')) + productionMode: not(%debugMode%) + ) +``` + +Oproti klasickému přetypování v PHP, jako je např. `(int)`, bezeztrátové přetypování vyhodí výjimku pro nečíselné hodnoty. + +Funkce `typed()` vytvoří pole všech služeb daného typu (třída nebo rozhraní). Vynechá služby, které mají vypnutý autowiring. Lze uvést i více typů oddělených čárkou. + +```neon +services: + - BarsDependent( typed(Bar) ) +``` + +Pole služeb určitého typu můžete předávat jako argument také automaticky pomocí [autowiringu|autowiring#Pole služeb]. + +Funkce `tagged()` pak vytváří pole všech služeb s určitým tagem. I zde můžete specifikovat více tagů oddělených čárkou. + +```neon +services: + - LoggersDependent( tagged(logger) ) +``` + + Autowiring ========== -Pomocí klíče autowired lze službu vyřadit z autowiringu nebo jeho chování ovlivnit. Více v [kapitole o autowiringu|autowiring]. +Klíč `autowired` umožňuje ovlivnit chování autowiringu pro konkrétní službu. Pro detaily viz [kapitola o autowiringu|autowiring]. ```neon services: @@ -350,7 +336,7 @@ services: Tagy ==== -Jednotlivým službám lze přidávat uživatelské informace v podobě tzv. tagů: +Tagy slouží k přidání doplňujících informací k službám. Službě můžete přidat jeden nebo více tagů: ```neon services: @@ -360,7 +346,7 @@ services: - cached ``` -Tagy mohou mít i hodnotu: +Tagy mohou také nést hodnoty: ```neon services: @@ -370,14 +356,14 @@ services: logger: monolog.logger.event ``` -Pole služeb s určitými tagy lze předat jako argument pomocí funkce `tagged()`. Lze uvést i více tagů oddělených čárkou. +Aby jste získali všechny služby s určitými tagy, můžete použít funkci `tagged()`: ```neon services: - LoggersDependent( tagged(logger) ) ``` -Názvy služeb lze získat z DI kontejneru metodou `findByTag()`: +V DI kontejneru můžete získat názvy všech služeb s určitým tagem pomocí metody `findByTag()`: ```php $names = $container->findByTag('logger'); @@ -398,13 +384,13 @@ services: inject: true ``` -V základním nastavení je `inject` aktivováno pouze pro presentery. +Ve výchozím nastavení je `inject` aktivováno pouze pro presentery. Modifikace služeb ================= -V DI kontejneru je řada služeb, které přidaly vestavěné nebo [vaše rozšíření|#rozšíření]. Definice těchto služeb lze v konfiguraci pozměnit. Třeba u služby `application.application`, což je standardně objekt `Nette\Application\Application`, můžeme změnit třídu: +DI kontejner obsahuje mnoho služeb, které byly přidány prostřednictvím vestavěného nebo [uživatelského rozšíření|#rozšíření]. Můžete upravit definice těchto služeb přímo v konfiguraci. Například můžete změnit třídu služby `application.application`, což je standardně `Nette\Application\Application`, na jinou: ```neon services: @@ -439,7 +425,7 @@ services: - tags ``` -Službu přidanou rozšířením lze také z kontejneru odstranit: +Pokud chcete odstranit službu přidanou rozšířením, můžete to udělat takto: ```neon services: diff --git a/dependency-injection/de/services.texy b/dependency-injection/de/services.texy index 466afd7d30..5268e28378 100644 --- a/dependency-injection/de/services.texy +++ b/dependency-injection/de/services.texy @@ -2,32 +2,32 @@ Dienst-Definitionen ******************* .[perex] -In der Konfiguration werden die Definitionen der benutzerdefinierten Dienste abgelegt. Dies geschieht im Abschnitt `services`. +Die Konfiguration ist der Ort, an dem wir den DI-Container anweisen, wie er die einzelnen Dienste zusammenstellen und mit anderen Abhängigkeiten verbinden soll. Nette bietet eine sehr klare und elegante Möglichkeit, dies zu erreichen. -So erstellen wir zum Beispiel einen Dienst namens `database`, der eine Instanz der Klasse `PDO` sein wird: +Der Abschnitt `services` in der NEON-Konfigurationsdatei ist der Ort, an dem wir unsere benutzerdefinierten Dienste und deren Konfigurationen definieren. Schauen wir uns ein einfaches Beispiel für die Definition eines Dienstes namens `database` an, der eine Instanz der Klasse `PDO` darstellt: ```neon services: database: PDO('sqlite::memory:') ``` -Die Benennung von Diensten dient dazu, dass wir auf sie [verweisen |#Referencing Services] können. Wenn ein Dienst nicht referenziert wird, ist es nicht notwendig, ihn zu benennen. Wir verwenden also einfach einen Aufzählungspunkt anstelle eines Namens: +Diese Konfiguration führt zu der folgenden Fabrikmethode im [DI-Container |container]: -```neon -services: - - PDO('sqlite::memory:') # anonymer Dienst +```php +public function createServiceDatabase(): PDO +{ + return new PDO('sqlite::memory:'); +} ``` -Ein einzeiliger Eintrag kann in mehrere Zeilen aufgeteilt werden, um weitere Schlüssel hinzuzufügen, wie z. B. [setup |#setup]. Der Alias für die Taste `create:` lautet `factory:`. +Dienstnamen ermöglichen es uns, in anderen Teilen der Konfigurationsdatei auf sie zu verweisen, indem wir das Format `@serviceName` verwenden. Wenn es nicht notwendig ist, den Dienst zu benennen, können wir einfach einen Aufzählungspunkt verwenden: ```neon services: - database: - create: PDO('sqlite::memory:') - setup: ... + - PDO('sqlite::memory:') ``` -Anschließend rufen wir den Dienst aus dem DI-Container mit der Methode `getService()` nach dem Namen oder besser noch mit der Methode `getByType()` nach dem Typ ab: +Um einen Dienst aus dem DI-Container abzurufen, können wir die Methode `getService()` mit dem Dienstnamen als Parameter oder die Methode `getByType()` mit dem Diensttyp verwenden: ```php $database = $container->getService('database'); @@ -35,236 +35,114 @@ $database = $container->getByType(PDO::class); ``` -Erstellen eines Dienstes .[#toc-creating-a-service] -=================================================== +Erstellung von Diensten .[#toc-service-creation] +================================================ -Meistens erstellen wir einen Dienst, indem wir einfach eine Instanz einer Klasse erstellen: +In den meisten Fällen wird ein Dienst einfach durch die Instanziierung einer bestimmten Klasse erstellt. Zum Beispiel: ```neon services: database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` -Dadurch wird eine Fabrikmethode im [DI-Container |container] erzeugt: - -```php -public function createServiceDatabase(): PDO -{ - return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret'); -} -``` - -Alternativ kann auch ein Schlüssel `arguments` verwendet werden, um [Argumente |#Arguments] zu übergeben: +Wenn wir die Konfiguration um zusätzliche Schlüssel erweitern müssen, kann die Definition in mehrere Zeilen aufgeteilt werden: ```neon services: database: - create: PDO - arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] -``` - -Eine statische Methode kann auch einen Dienst erstellen: - -```neon -services: - database: My\Database::create(root, secret) + create: PDO('sqlite::memory:') + setup: ... ``` -Entspricht dem PHP-Code: +Der Schlüssel `create` hat einen Alias `factory`, beide Versionen sind in der Praxis üblich. Wir empfehlen jedoch die Verwendung von `create`. -```php -public function createServiceDatabase(): PDO -{ - return My\Database::create('root', 'secret'); -} -``` - -Bei einer statischen Methode `My\Database::create()` wird davon ausgegangen, dass sie einen definierten Rückgabewert hat, den der DI-Container kennen muss. Ist dies nicht der Fall, schreiben wir den Typ in die Konfiguration: +Konstruktorargumente oder die Erstellungsmethode können alternativ in den Schlüssel `arguments` geschrieben werden: ```neon services: database: - create: My\Database::create(root, secret) - type: PDO + create: PDO + arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] ``` -Nette DI gibt Ihnen extrem leistungsfähige Ausdrucksmöglichkeiten, um fast alles zu schreiben. Zum Beispiel, um auf einen anderen Dienst zu [verweisen |#Referencing Services] und seine Methode aufzurufen. Der Einfachheit halber wird `::` anstelle von `->` verwendet. +Dienste müssen nicht nur durch einfache Instanziierung einer Klasse erzeugt werden, sondern können auch durch den Aufruf statischer Methoden oder Methoden anderer Dienste entstehen: ```neon services: - routerFactory: App\Router\Factory + database: DatabaseFactory::create() router: @routerFactory::create() ``` -Entspricht dem PHP-Code: +Beachten Sie, dass wir der Einfachheit halber anstelle von `->` `::` verwenden, siehe [Ausdrucksmittel |#expression means]. Diese Fabrikmethoden werden generiert: ```php -public function createServiceRouterFactory(): App\Router\Factory +public function createServiceDatabase(): PDO { - return new App\Router\Factory; + return DatabaseFactory::create(); } -public function createServiceRouter(): Router +public function createServiceRouter(): RouteList { return $this->getService('routerFactory')->create(); } ``` -Methodenaufrufe können wie in PHP aneinandergereiht werden: +Der DI-Container muss den Typ des erzeugten Dienstes kennen. Wenn wir einen Dienst mit einer Methode erstellen, die keinen bestimmten Rückgabetyp hat, müssen wir diesen Typ in der Konfiguration explizit angeben: ```neon services: - foo: FooFactory::build()::get() -``` - -Entspricht dem PHP-Code: - -```php -public function createServiceFoo() -{ - return FooFactory::build()->get(); -} + database: + create: DatabaseFactory::create() + type: PDO ``` Argumente .[#toc-arguments] =========================== -Benannte Parameter können auch zur Übergabe von Argumenten verwendet werden: +Wir übergeben Argumente an Konstruktoren und Methoden auf eine Weise, die der von PHP sehr ähnlich ist: ```neon services: - database: PDO( - 'mysql:host=127.0.0.1;dbname=test' # positional - username: root # named - password: secret # named - ) -``` - -Die Verwendung von Kommas ist optional, wenn Argumente in mehrere Zeilen aufgeteilt werden. - -Natürlich können wir auch [andere Dienste |#Referencing Services] oder [Parameter |configuration#parameters] als Argumente verwenden: - -```neon -services: - - Foo(@anotherService, %appDir%) -``` - -Entspricht dem PHP-Code: - -```php -public function createService01(): Foo -{ - return new Foo($this->getService('anotherService'), '...'); -} + database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` -Wenn das erste Argument [autowired |autowiring] ist und Sie das zweite angeben wollen, lassen Sie das erste mit `_` character, for example `Foo(_, %appDir%)` weg. Oder noch besser, übergeben Sie nur das zweite Argument als benannten Parameter, z. B. `Foo(path: %appDir%)`. - -Nette DI und das NEON-Format geben Ihnen extrem leistungsfähige Ausdrucksmöglichkeiten, um fast alles zu schreiben. So kann ein Argument ein neu erstelltes Objekt sein, Sie können statische Methoden, Methoden anderer Dienste oder sogar globale Funktionen unter Verwendung einer speziellen Notation aufrufen: +Zur besseren Lesbarkeit können wir die Argumente in separaten Zeilen auflisten. In diesem Format ist die Verwendung von Kommas optional: ```neon services: - analyser: My\Analyser( - FilesystemIterator(%appDir%) # Objekt erstellen - DateTime::createFromFormat('Y-m-d') # statische Methode aufrufen - @anotherService # Übergabe eines anderen Dienstes - @http.request::getRemoteAddress() # Aufruf einer anderen Dienstmethode - ::getenv(NetteMode) # Aufruf einer globalen Funktion + database: PDO( + 'mysql:host=127.0.0.1;dbname=test' + root + secret ) ``` -Entspricht dem PHP-Code: - -```php -public function createServiceAnalyser(): My\Analyser -{ - return new My\Analyser( - new FilesystemIterator('...'), - DateTime::createFromFormat('Y-m-d'), - $this->getService('anotherService'), - $this->getService('http.request')->getRemoteAddress(), - getenv('NetteMode') - ); -} -``` - - -Spezielle Funktionen .[#toc-special-functions] ----------------------------------------------- - -Sie können auch spezielle Funktionen in Argumenten verwenden, um Werte zu casten oder zu negieren: - -- `not(%arg%)` negation -- `bool(%arg%)` verlustfreie Umwandlung in bool -- `int(%arg%)` verlustfreie Umwandlung in int -- `float(%arg%)` verlustfreie Umwandlung in float -- `string(%arg%)` lossless cast to string +Sie können die Argumente auch benennen, dann brauchen Sie sich nicht um ihre Reihenfolge zu kümmern: ```neon services: - - Foo( - id: int(::getenv('ProjectId')) - productionMode: not(%debugMode%) + database: PDO( + username: root + password: secret + dsn: 'mysql:host=127.0.0.1;dbname=test' ) ``` -Verlustfreies Rewriting unterscheidet sich von normalem PHP Rewriting, z.B. mit `(int)`, dadurch, dass es eine Ausnahme für nicht-numerische Werte auslöst. - -Es können mehrere Dienste als Argumente übergeben werden. Ein Array mit allen Diensten eines bestimmten Typs (d.h. Klasse oder Schnittstelle) wird von der Funktion `typed()` erstellt. Die Funktion lässt Dienste aus, bei denen die automatische Verdrahtung deaktiviert ist, und es können mehrere Typen durch ein Komma getrennt angegeben werden. +Wenn Sie bestimmte Argumente auslassen und ihre Standardwerte verwenden oder einen Dienst über die [automatische Verdrahtung |autowiring] einfügen möchten, verwenden Sie einen Unterstrich: ```neon services: - - BarsDependent( typed(Bar) ) -``` - -Sie können ein Array von Diensten auch automatisch mit [Autowiring |autowiring#Collection of Services] übergeben. - -Ein Array mit allen Diensten mit einem bestimmten [Tag |#tags] wird mit der Funktion `tagged()` erstellt. Es können mehrere Tags durch ein Komma getrennt angegeben werden. - -```neon -services: - - LoggersDependent( tagged(logger) ) + foo: Foo(_, %appDir%) ``` - -Referenzierungsdienste .[#toc-referencing-services] -=================================================== - -Die einzelnen Dienste werden mit dem Zeichen `@` and name, so for example `@database` referenziert: - -```neon -services: - - create: Foo(@database) - setup: - - setCacheStorage(@cache.storage) -``` - -Entspricht dem PHP-Code: - -```php -public function createService01(): Foo -{ - $service = new Foo($this->getService('database')); - $service->setCacheStorage($this->getService('cache.storage')); - return $service; -} -``` - -Auch anonyme Dienste können über einen Callback referenziert werden, man muss nur ihren Typ (Klasse oder Schnittstelle) anstelle ihres Namens angeben. Dies ist jedoch aufgrund der [automatischen Verdrahtung |autowiring] normalerweise nicht erforderlich. - -```neon -services: - - create: Foo(@Nette\Database\Connection) - setup: - - setCacheStorage(@cache.storage) -``` +Argumente können Dienste, Parameter und vieles mehr sein, siehe [Ausdrucksmittel |#expression means]. Einrichtung .[#toc-setup] ========================= -Im Abschnitt "Setup" werden die Methoden aufgeführt, die bei der Erstellung des Dienstes aufgerufen werden müssen: +Im Abschnitt `setup` definieren wir die Methoden, die bei der Erstellung des Dienstes aufgerufen werden sollen. ```neon services: @@ -274,7 +152,7 @@ services: - setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) ``` -Entspricht dem PHP-Code: +In PHP würde dies wie folgt aussehen: ```php public function createServiceDatabase(): PDO @@ -285,8 +163,7 @@ public function createServiceDatabase(): PDO } ``` -Properites können auch gesetzt werden. Das Hinzufügen eines Elements zu einem Array wird ebenfalls unterstützt und sollte in Anführungszeichen geschrieben werden, um nicht mit der NEON-Syntax in Konflikt zu geraten: - +Zusätzlich zu Methodenaufrufen können Sie auch Werte an Eigenschaften übergeben. Das Hinzufügen eines Elements zu einem Array wird ebenfalls unterstützt, aber Sie müssen es in Anführungszeichen setzen, um Kollisionen mit der NEON-Syntax zu vermeiden: ```neon services: @@ -297,7 +174,7 @@ services: - '$onClick[]' = [@bar, clickHandler] ``` -Entspricht dem PHP-Code: +In PHP würde dies bedeuten: ```php public function createServiceFoo(): Foo @@ -309,8 +186,7 @@ public function createServiceFoo(): Foo } ``` -Es können aber auch statische Methoden oder Methoden anderer Dienste im Setup aufgerufen werden. Wir übergeben ihnen den eigentlichen Dienst als `@self`: - +Im Setup können Sie auch statische Methoden oder Methoden von anderen Diensten aufrufen. Wenn Sie den aktuellen Dienst als Argument übergeben müssen, verwenden Sie `@self`: ```neon services: @@ -321,7 +197,7 @@ services: - @anotherService::setFoo(@self) ``` -Entspricht dem PHP-Code: +Beachten Sie, dass wir der Einfachheit halber anstelle von `->` `::` verwenden, siehe [Ausdrucksmittel |#expression means]. Dies erzeugt die folgende Fabrikmethode: ```php public function createServiceFoo(): Foo @@ -334,23 +210,133 @@ public function createServiceFoo(): Foo ``` -Autowiring .[#toc-autowiring] -============================= +Ausdrucksmittel .[#toc-expression-means] +======================================== + +Nette DI bietet uns außergewöhnlich reichhaltige Ausdrucksmöglichkeiten, die es uns erlauben, fast alles zu artikulieren. In Konfigurationsdateien können wir [Parameter |configuration#parameters] verwenden: + +```neon +# Parameter +%wwwDir% + +# Wert unter einem Parameterschlüssel +%mailer.user% + +# Parameter innerhalb einer Zeichenkette +'%wwwDir%/images' +``` + +Wir können auch Objekte erstellen, Methoden und Funktionen aufrufen: + +```neon +# ein Objekt erstellen +DateTime() + +# eine statische Methode aufrufen +Collator::create(%locale%) + +# eine PHP-Funktion aufrufen +::getenv(DB_USER) +``` + +Beziehen Sie sich auf Dienste entweder durch ihren Namen oder durch ihren Typ: + +```neon +# Dienst nach Name +@database + +# Dienst nach Typ +@Nette\Database\Connection +``` + +Verwenden Sie Konstanten: + +```neon +# Klassenkonstante +FilesystemIterator::SKIP_DOTS + +# globale Konstante, die mit der PHP-Funktion constant() ermittelt wird +::constant(PHP_VERSION) +``` + +Methodenaufrufe können, genau wie in PHP, verkettet werden. Der Einfachheit halber verwenden wir anstelle von `->` `::` : + +```neon +DateTime()::format('Y-m-d') +# PHP: (new DateTime())->format('Y-m-d') + +@http.request::getUrl()::getHost() +# PHP: $this->getService('http.request')->getUrl()->getHost() +``` + +Diese Ausdrücke können bei der [Erstellung von Diensten |#Service Creation] überall verwendet werden, in [Argumenten |#Arguments], im [Setup-Abschnitt |#setup] oder in [Parametern |configuration#parameters]: + +```neon +parameters: + ipAddress: @http.request::getRemoteAddress() + +services: + database: + create: DatabaseFactory::create( @anotherService::getDsn() ) + setup: + - initialize( ::getenv('DB_USER') ) +``` + + +Besondere Funktionen .[#toc-special-functions] +---------------------------------------------- + +Innerhalb von Konfigurationsdateien können Sie diese speziellen Funktionen verwenden: + +- `not()` für die Negation von Werten +- `bool()`, `int()`, `float()`, `string()` für verlustfreies Type Casting +- `typed()` um ein Array mit allen Diensten eines bestimmten Typs zu erzeugen +- `tagged()`, um ein Array aller Dienste mit einem bestimmten Tag zu erzeugen + +```neon +services: + - Foo( + id: int(::getenv('ProjectId')) + productionMode: not(%debugMode%) + ) +``` + +Im Vergleich zum konventionellen Typecasting in PHP, wie z.B. `(int)`, wird beim verlustfreien Typecasting eine Exception für nicht-numerische Werte geworfen. + +Die Funktion `typed()` erstellt ein Array mit allen Diensten eines bestimmten Typs (Klasse oder Schnittstelle). Sie schließt Dienste mit ausgeschaltetem Autowiring aus. Es können mehrere Typen angegeben werden, getrennt durch Kommas. + +```neon +services: + - BarsDependent( typed(Bar) ) +``` + +Sie können auch automatisch ein Array von Diensten eines bestimmten Typs als Argument übergeben, indem Sie [autowiring |autowiring#Collection of Services] verwenden. + +Die Funktion `tagged()` erstellt ein Array mit allen Diensten mit einem bestimmten Tag. Es können mehrere Tags aufgelistet werden, getrennt durch Kommas. + +```neon +services: + - LoggersDependent( tagged(logger) ) +``` + + +Fahrzeugverkabelung .[#toc-autowiring] +====================================== -Der Autowiring-Schlüssel kann verwendet werden, um einen Dienst vom Autowiring auszuschließen oder um sein Verhalten zu beeinflussen. Weitere Informationen finden Sie im [Kapitel über Autowiring |autowiring]. +Mit der Taste `autowired` können Sie das Autowiring-Verhalten für einen bestimmten Dienst ändern. Weitere Einzelheiten finden Sie im [Kapitel über die automatische Verdrahtung |autowiring]. ```neon services: foo: create: Foo - autowired: false # foo wird aus der automatischen Verdrahtung entfernt + autowired: false # der Foo-Dienst ist vom Autowiring ausgeschlossen ``` Tags .[#toc-tags] ================= -Benutzerinformationen können den einzelnen Diensten in Form von Tags hinzugefügt werden: +Tags werden verwendet, um zusätzliche Informationen zu Diensten hinzuzufügen. Sie können einem Dienst ein oder mehrere Tags zuweisen: ```neon services: @@ -360,7 +346,7 @@ services: - cached ``` -Tags können auch einen Wert haben: +Tags können auch Werte enthalten: ```neon services: @@ -370,26 +356,26 @@ services: logger: monolog.logger.event ``` -Ein Array von Diensten mit bestimmten Tags kann mit der Funktion `tagged()` als Argument übergeben werden. Es können auch mehrere Tags durch ein Komma getrennt angegeben werden. +Um alle Dienste mit bestimmten Tags abzurufen, können Sie die Funktion `tagged()` verwenden: ```neon services: - LoggersDependent( tagged(logger) ) ``` -Dienstnamen können mit der Methode `findByTag()` aus dem DI-Container bezogen werden: +Im DI-Container können Sie mit der Methode `findByTag()` die Namen aller Dienste mit einem bestimmten Tag abrufen: ```php $names = $container->findByTag('logger'); // $names ist ein Array, das den Dienstnamen und den Tag-Wert enthält -// d.h. ['foo' => 'monolog.logger.event', ...] +// z.B. ['foo' => 'monolog.logger.event', ...] ``` Injektionsmodus .[#toc-inject-mode] =================================== -Das Flag `inject: true` wird verwendet, um die Übergabe von Abhängigkeiten über öffentliche Variablen mit der [inject-Annotation |best-practices:inject-method-attribute#Inject Attributes] und den [inject*() |best-practices:inject-method-attribute#inject Methods] -Methoden zu aktivieren. +Mit dem Flag `inject: true` wird die Übergabe von Abhängigkeiten über öffentliche Variablen mit der [inject-Annotation |best-practices:inject-method-attribute#Inject Attributes] und den [inject*() |best-practices:inject-method-attribute#inject Methods] -Methoden aktiviert. ```neon services: @@ -401,10 +387,10 @@ services: Standardmäßig ist `inject` nur für Präsentatoren aktiviert. -Modifikation der Dienste .[#toc-modification-of-services] -========================================================= +Änderungen am Dienst .[#toc-service-modifications] +================================================== -Es gibt eine Reihe von Diensten im DI-Container, die durch eine eingebaute oder [Ihre Erweiterung |#di-extensions] hinzugefügt wurden. Die Definitionen dieser Dienste können in der Konfiguration geändert werden. Zum Beispiel kann für den Dienst `application.application`, der standardmäßig ein Objekt `Nette\Application\Application` ist, die Klasse geändert werden: +Der DI-Container enthält viele Dienste, die entweder durch eingebaute oder [durch Benutzererweiterungen |#extensions] hinzugefügt wurden. Sie können die Definitionen dieser Dienste direkt in der Konfiguration ändern. So können Sie beispielsweise die Klasse des Dienstes `application.application`, die üblicherweise `Nette\Application\Application` lautet, in eine andere ändern: ```neon services: @@ -413,9 +399,9 @@ services: alteration: true ``` -Das Kennzeichen `alteration` ist informativ und besagt, dass wir nur einen bestehenden Dienst ändern. +Das Kennzeichen `alteration` ist informativ und zeigt an, dass es sich lediglich um eine Änderung eines bestehenden Dienstes handelt. -Wir können auch eine Einrichtung hinzufügen: +Wir können die Einrichtung auch ergänzen: ```neon services: @@ -426,7 +412,7 @@ services: - '$onStartup[]' = [@resource, init] ``` -Wenn wir einen Dienst neu schreiben, möchten wir vielleicht die ursprünglichen Argumente, Setup-Elemente oder Tags entfernen. Dafür ist `reset` gedacht: +Wenn Sie einen Dienst überschreiben, möchten Sie vielleicht die ursprünglichen Argumente, Einrichtungselemente oder Tags entfernen, und hier kommt `reset` ins Spiel: ```neon services: @@ -439,7 +425,7 @@ services: - tags ``` -Ein durch eine Erweiterung hinzugefügter Dienst kann auch aus dem Container entfernt werden: +Wenn Sie einen Dienst, der von einer Erweiterung hinzugefügt wurde, entfernen möchten, können Sie dies wie folgt tun: ```neon services: diff --git a/dependency-injection/el/services.texy b/dependency-injection/el/services.texy index 88990590c5..2d958a373c 100644 --- a/dependency-injection/el/services.texy +++ b/dependency-injection/el/services.texy @@ -2,32 +2,32 @@ ***************** .[perex] -Η διαμόρφωση είναι το σημείο όπου τοποθετούμε τους ορισμούς των προσαρμοσμένων υπηρεσιών. Αυτό γίνεται στην ενότητα `services`. +Η διαμόρφωση είναι το μέρος όπου δίνουμε οδηγίες στο DI container για το πώς να συναρμολογήσει τις επιμέρους υπηρεσίες και πώς να τις συνδέσει με άλλες εξαρτήσεις. Η Nette παρέχει έναν πολύ σαφή και κομψό τρόπο για να το επιτύχουμε αυτό. -Για παράδειγμα, έτσι δημιουργούμε μια υπηρεσία με το όνομα `database`, η οποία θα είναι μια περίπτωση της κλάσης `PDO`: +Η ενότητα `services` στο αρχείο ρυθμίσεων NEON είναι το σημείο όπου ορίζουμε τις προσαρμοσμένες υπηρεσίες μας και τις διαμορφώσεις τους. Ας δούμε ένα απλό παράδειγμα ορισμού μιας υπηρεσίας με το όνομα `database`, η οποία αντιπροσωπεύει μια περίπτωση της κλάσης `PDO`: ```neon services: database: PDO('sqlite::memory:') ``` -Η ονοματοδοσία των υπηρεσιών χρησιμοποιείται για να μας επιτρέπει να τις [αναφέρουμε |#Referencing Services]. Εάν μια υπηρεσία δεν αναφέρεται, δεν υπάρχει λόγος να την ονομάσουμε. Έτσι, αντί για όνομα χρησιμοποιούμε απλώς ένα σημείο αναφοράς: +Αυτή η διαμόρφωση έχει ως αποτέλεσμα την ακόλουθη εργοστασιακή μέθοδο στο [δοχείο DI |container]: -```neon -services: - - PDO('sqlite::memory:') # ανώνυμη υπηρεσία +```php +public function createServiceDatabase(): PDO +{ + return new PDO('sqlite::memory:'); +} ``` -Μια καταχώρηση μιας γραμμής μπορεί να σπάσει σε πολλές γραμμές για να επιτραπεί η προσθήκη πρόσθετων κλειδιών, όπως το [setup |#setup]. Το ψευδώνυμο για το κλειδί `create:` είναι `factory:`. +Τα ονόματα υπηρεσιών μας επιτρέπουν να τα αναφέρουμε σε άλλα μέρη του αρχείου διαμόρφωσης, χρησιμοποιώντας τη μορφή `@serviceName`. Εάν δεν υπάρχει ανάγκη να δώσουμε όνομα στην υπηρεσία, μπορούμε απλά να χρησιμοποιήσουμε ένα σημείο αναφοράς: ```neon services: - database: - create: PDO('sqlite::memory:') - setup: ... + - PDO('sqlite::memory:') ``` -Στη συνέχεια, ανακτούμε την υπηρεσία από το δοχείο DI χρησιμοποιώντας τη μέθοδο `getService()` με βάση το όνομα ή, ακόμα καλύτερα, τη μέθοδο `getByType()` με βάση τον τύπο: +Για να ανακτήσουμε μια υπηρεσία από το δοχείο DI, μπορούμε να χρησιμοποιήσουμε τη μέθοδο `getService()` με το όνομα της υπηρεσίας ως παράμετρο ή τη μέθοδο `getByType()` με τον τύπο της υπηρεσίας: ```php $database = $container->getService('database'); @@ -35,236 +35,114 @@ $database = $container->getByType(PDO::class); ``` -Δημιουργία υπηρεσίας .[#toc-creating-a-service] -=============================================== +Δημιουργία υπηρεσιών .[#toc-service-creation] +============================================= -Τις περισσότερες φορές, δημιουργούμε μια υπηρεσία με την απλή δημιουργία μιας περίπτωσης μιας κλάσης: +Συνήθως, δημιουργούμε μια υπηρεσία απλά με την ενσάρκωση μιας συγκεκριμένης κλάσης. Για παράδειγμα: ```neon services: database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` -Η οποία θα δημιουργήσει μια μέθοδο εργοστασίου στο [DI |container] container: - -```php -public function createServiceDatabase(): PDO -{ - return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret'); -} -``` - -Εναλλακτικά, ένα κλειδί `arguments` μπορεί να χρησιμοποιηθεί για να περάσει [ορίσματα |#Arguments]: +Εάν χρειάζεται να επεκτείνουμε τη διαμόρφωση με πρόσθετα κλειδιά, ο ορισμός μπορεί να επεκταθεί σε πολλές γραμμές: ```neon services: database: - create: PDO - arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] -``` - -Μια στατική μέθοδος μπορεί επίσης να δημιουργήσει μια υπηρεσία: - -```neon -services: - database: My\Database::create(root, secret) + create: PDO('sqlite::memory:') + setup: ... ``` -Αντιστοιχεί στον κώδικα PHP: +Το κλειδί `create` έχει το ψευδώνυμο `factory`, και οι δύο εκδοχές είναι κοινές στην πράξη. Ωστόσο, συνιστούμε τη χρήση του κλειδιού `create`. -```php -public function createServiceDatabase(): PDO -{ - return My\Database::create('root', 'secret'); -} -``` - -Μια στατική μέθοδος `My\Database::create()` θεωρείται ότι έχει καθορισμένη τιμή επιστροφής που πρέπει να γνωρίζει ο περιέκτης DI. Εάν δεν την έχει, γράφουμε τον τύπο στη διαμόρφωση: +Τα ορίσματα του κατασκευαστή ή η μέθοδος δημιουργίας μπορούν εναλλακτικά να γραφτούν στο κλειδί `arguments`: ```neon services: database: - create: My\Database::create(root, secret) - type: PDO + create: PDO + arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] ``` -Η Nette DI σας δίνει εξαιρετικά ισχυρές δυνατότητες έκφρασης για να γράψετε σχεδόν οτιδήποτε. Για παράδειγμα, για να [αναφερθούμε |#Referencing Services] σε μια άλλη υπηρεσία και να καλέσουμε τη μέθοδό της. Για λόγους απλότητας, χρησιμοποιείται το `::` αντί του `->`. +Οι υπηρεσίες δεν χρειάζεται να δημιουργούνται μόνο με απλή ενσάρκωση μιας κλάσης- μπορούν επίσης να προκύψουν από την κλήση στατικών μεθόδων ή μεθόδων άλλων υπηρεσιών: ```neon services: - routerFactory: App\Router\Factory + database: DatabaseFactory::create() router: @routerFactory::create() ``` -Αντιστοιχεί σε κώδικα PHP: +Σημειώστε ότι για λόγους απλότητας, αντί για `->`, χρησιμοποιούμε `::`, βλέπε [μέσα έκφρασης |#expression means]. Αυτές οι εργοστασιακές μέθοδοι δημιουργούνται: ```php -public function createServiceRouterFactory(): App\Router\Factory +public function createServiceDatabase(): PDO { - return new App\Router\Factory; + return DatabaseFactory::create(); } -public function createServiceRouter(): Router +public function createServiceRouter(): RouteList { return $this->getService('routerFactory')->create(); } ``` -Οι κλήσεις μεθόδων μπορούν να συνδεθούν αλυσιδωτά όπως στην PHP: +Ο περιέκτης DI πρέπει να γνωρίζει τον τύπο της δημιουργούμενης υπηρεσίας. Αν δημιουργήσουμε μια υπηρεσία χρησιμοποιώντας μια μέθοδο που δεν έχει καθορισμένο τύπο επιστροφής, πρέπει να αναφέρουμε ρητά αυτόν τον τύπο στη διαμόρφωση: ```neon services: - foo: FooFactory::build()::get() -``` - -Αντιστοιχεί στον κώδικα PHP: - -```php -public function createServiceFoo() -{ - return FooFactory::build()->get(); -} + database: + create: DatabaseFactory::create() + type: PDO ``` Επιχειρήματα .[#toc-arguments] ============================== -Οι ονομαστικές παράμετροι μπορούν επίσης να χρησιμοποιηθούν για τη μετάδοση επιχειρημάτων: +Παραδίδουμε ορίσματα σε κατασκευαστές και μεθόδους με τρόπο που μοιάζει πολύ με την κανονική PHP: ```neon services: - database: PDO( - 'mysql:host=127.0.0.1;dbname=test' # θέση - username: root # όνομα - password: secret # named - ) -``` - -Η χρήση των κομμάτων είναι προαιρετική όταν τα ορίσματα χωρίζονται σε πολλές γραμμές. - -Φυσικά, μπορούμε επίσης να χρησιμοποιήσουμε [άλλες υπηρεσίες |#Referencing Services] ή [παραμέτρους |configuration#parameters] ως ορίσματα: - -```neon -services: - - Foo(@anotherService, %appDir%) -``` - -Αντιστοιχεί στον κώδικα PHP: - -```php -public function createService01(): Foo -{ - return new Foo($this->getService('anotherService'), '...'); -} + database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` - `_` character, for example `Foo(_, %appDir%)`Ή ακόμα καλύτερα, περάστε μόνο το δεύτερο όρισμα ως ονομαστική παράμετρο, π.χ. `Foo(path: %appDir%)`. - -Το Nette DI και η μορφή NEON σας δίνουν εξαιρετικά ισχυρές εκφραστικές δυνατότητες για να γράψετε σχεδόν οτιδήποτε. Έτσι, ένα όρισμα μπορεί να είναι ένα νεοδημιουργημένο αντικείμενο, μπορείτε να καλέσετε στατικές μεθόδους, μεθόδους άλλων υπηρεσιών ή ακόμη και παγκόσμιες συναρτήσεις χρησιμοποιώντας ειδικό συμβολισμό: +Για καλύτερη αναγνωσιμότητα, μπορούμε να απαριθμήσουμε τα ορίσματα σε ξεχωριστές γραμμές. Σε αυτή τη μορφή, η χρήση των κομμάτων είναι προαιρετική: ```neon services: - analyser: My\Analyser( - FilesystemIterator(%appDir%) # δημιουργία αντικειμένου - DateTime::createFromFormat('Y-m-d') # κλήση στατικής μεθόδου - @anotherService # περνώντας μια άλλη υπηρεσία - @http.request::getRemoteAddress() # κλήση άλλης μεθόδου υπηρεσίας - ::getenv(NetteMode) # κλήση παγκόσμιας συνάρτησης + database: PDO( + 'mysql:host=127.0.0.1;dbname=test' + root + secret ) ``` -Αντιστοιχεί στον κώδικα PHP: - -```php -public function createServiceAnalyser(): My\Analyser -{ - return new My\Analyser( - new FilesystemIterator('...'), - DateTime::createFromFormat('Y-m-d'), - $this->getService('anotherService'), - $this->getService('http.request')->getRemoteAddress(), - getenv('NetteMode') - ); -} -``` - - -PHP: Ειδικές λειτουργίες .[#toc-special-functions] --------------------------------------------------- - -Μπορείτε επίσης να χρησιμοποιήσετε ειδικές συναρτήσεις σε ορίσματα για να ρίξετε ή να αναιρέσετε τιμές: - -- `not(%arg%)` negation -- `bool(%arg%)` cast χωρίς απώλειες σε bool -- `int(%arg%)` cast χωρίς απώλειες σε int -- `float(%arg%)` lossless cast to float -- `string(%arg%)` lossless cast to string +Μπορείτε επίσης να ονομάσετε τα ορίσματα, γεγονός που σας επιτρέπει τότε να μην ανησυχείτε για τη σειρά τους: ```neon services: - - Foo( - id: int(::getenv('ProjectId')) - productionMode: not(%debugMode%) + database: PDO( + username: root + password: secret + dsn: 'mysql:host=127.0.0.1;dbname=test' ) ``` -Η αναδιαγραφή χωρίς απώλειες διαφέρει από την κανονική αναδιαγραφή της PHP, π.χ. με τη χρήση του `(int)`, στο ότι πετάει μια εξαίρεση για μη αριθμητικές τιμές. - -Πολλαπλές υπηρεσίες μπορούν να περάσουν ως ορίσματα. Ένας πίνακας όλων των υπηρεσιών ενός συγκεκριμένου τύπου (δηλ. κλάσης ή διεπαφής) δημιουργείται από τη συνάρτηση `typed()`. Η συνάρτηση θα παραλείψει τις υπηρεσίες που έχουν απενεργοποιήσει την αυτόματη καλωδίωση και μπορούν να καθοριστούν πολλαπλοί τύποι που χωρίζονται με κόμμα. - -```neon -services: - - BarsDependent( typed(Bar) ) -``` - -Μπορείτε επίσης να περάσετε έναν πίνακα υπηρεσιών αυτόματα χρησιμοποιώντας [την αυτόματη καλωδίωση |autowiring#Collection of Services]. - -Ένας πίνακας όλων των υπηρεσιών με μια συγκεκριμένη [ετικέτα |#tags] δημιουργείται από τη συνάρτηση `tagged()`. Μπορούν να καθοριστούν πολλαπλές ετικέτες που χωρίζονται με κόμμα. - -```neon -services: - - LoggersDependent( tagged(logger) ) -``` - - -Αναφορά σε υπηρεσίες .[#toc-referencing-services] -================================================= - -Η αναφορά σε μεμονωμένες υπηρεσίες γίνεται με τη χρήση των χαρακτήρων `@` and name, so for example `@database`: +Αν θέλετε να παραλείψετε ορισμένα ορίσματα και να χρησιμοποιήσετε τις προεπιλεγμένες τιμές τους ή να εισαγάγετε μια υπηρεσία μέσω [αυτόματης καλωδίωσης |autowiring], χρησιμοποιήστε μια υπογράμμιση: ```neon services: - - create: Foo(@database) - setup: - - setCacheStorage(@cache.storage) + foo: Foo(_, %appDir%) ``` -Αντιστοιχεί στον κώδικα PHP: +Τα επιχειρήματα μπορεί να είναι υπηρεσίες, παράμετροι και πολλά άλλα, δείτε τα [μέσα έκφρασης |#expression means]. -```php -public function createService01(): Foo -{ - $service = new Foo($this->getService('database')); - $service->setCacheStorage($this->getService('cache.storage')); - return $service; -} -``` -Ακόμα και ανώνυμες υπηρεσίες μπορούν να αναφερθούν χρησιμοποιώντας μια επανάκληση, απλά καθορίστε τον τύπο τους (κλάση ή διεπαφή) αντί για το όνομά τους. Ωστόσο, αυτό συνήθως δεν είναι απαραίτητο λόγω της [αυτόματης καλωδίωσης |autowiring]. - -```neon -services: - - create: Foo(@Nette\Database\Connection) - setup: - - setCacheStorage(@cache.storage) -``` +Εγκατάσταση .[#toc-setup] +========================= - -Ρύθμιση .[#toc-setup] -===================== - -Στην ενότητα setup παραθέτουμε τις μεθόδους που θα κληθούν κατά τη δημιουργία της υπηρεσίας: +Στην ενότητα `setup`, ορίζουμε τις μεθόδους που πρέπει να κληθούν κατά τη δημιουργία της υπηρεσίας. ```neon services: @@ -274,7 +152,7 @@ services: - setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) ``` -Αντιστοιχεί στον κώδικα PHP: +Σε PHP, αυτό θα έμοιαζε ως εξής: ```php public function createServiceDatabase(): PDO @@ -285,8 +163,7 @@ public function createServiceDatabase(): PDO } ``` -Properites μπορεί επίσης να οριστεί. Η προσθήκη ενός στοιχείου σε έναν πίνακα υποστηρίζεται επίσης, και θα πρέπει να γράφεται σε εισαγωγικά για να μην έρχεται σε σύγκρουση με τη σύνταξη του NEON: - +Εκτός από τις κλήσεις μεθόδων, μπορείτε επίσης να μεταβιβάζετε τιμές σε ιδιότητες. Η προσθήκη ενός στοιχείου σε έναν πίνακα υποστηρίζεται επίσης, αλλά πρέπει να το περικλείσετε σε εισαγωγικά για να αποφύγετε τη σύγκρουση με τη σύνταξη NEON: ```neon services: @@ -297,7 +174,7 @@ services: - '$onClick[]' = [@bar, clickHandler] ``` -Αντιστοιχεί στον κώδικα PHP: +Στην PHP, αυτό θα μεταφραζόταν ως εξής: ```php public function createServiceFoo(): Foo @@ -309,8 +186,7 @@ public function createServiceFoo(): Foo } ``` -Ωστόσο, οι στατικές μέθοδοι ή οι μέθοδοι άλλων υπηρεσιών μπορούν επίσης να κληθούν στη ρύθμιση. Τους περνάμε την πραγματική υπηρεσία ως `@self`: - +Στην εγκατάσταση, μπορείτε επίσης να καλέσετε στατικές μεθόδους ή μεθόδους άλλων υπηρεσιών. Αν πρέπει να περάσετε την τρέχουσα υπηρεσία ως όρισμα, χρησιμοποιήστε το `@self`: ```neon services: @@ -321,7 +197,7 @@ services: - @anotherService::setFoo(@self) ``` -Αντιστοιχεί στον κώδικα PHP: +Σημειώστε ότι για λόγους απλότητας, αντί για `->`, χρησιμοποιούμε `::`, βλέπε [μέσα έκφρασης |#expression means]. Αυτό δημιουργεί την ακόλουθη εργοστασιακή μέθοδο: ```php public function createServiceFoo(): Foo @@ -334,23 +210,133 @@ public function createServiceFoo(): Foo ``` -Autowiring .[#toc-autowiring] -============================= +Έκφραση Μέσα .[#toc-expression-means] +===================================== + +Το Nette DI μας παρέχει εξαιρετικά πλούσιες δυνατότητες έκφρασης, επιτρέποντάς μας να εκφράσουμε σχεδόν τα πάντα. Στα αρχεία ρυθμίσεων, μπορούμε να χρησιμοποιούμε [παραμέτρους |configuration#parameters]: + +```neon +# παράμετρος +%wwwDir% + +# τιμή κάτω από ένα κλειδί παραμέτρου +%mailer.user% + +# παράμετρος μέσα σε μια συμβολοσειρά +'%wwwDir%/images' +``` + +Μπορούμε επίσης να δημιουργήσουμε αντικείμενα, να καλέσουμε μεθόδους και συναρτήσεις: + +```neon +# δημιουργήστε ένα αντικείμενο +DateTime() + +# κλήση μιας στατικής μεθόδου +Collator::create(%locale%) + +# κλήση μιας συνάρτησης PHP +::getenv(DB_USER) +``` + +Να αναφερόμαστε σε υπηρεσίες είτε με το όνομά τους είτε με τον τύπο τους: + +```neon +# υπηρεσία με όνομα +@database + +# υπηρεσία ανά τύπο +@Nette\Database\Connection +``` + +Χρήση σταθερών: + +```neon +# σταθερά κατηγορίας +FilesystemIterator::SKIP_DOTS + +# παγκόσμια σταθερά που λαμβάνεται από τη συνάρτηση constant() της PHP +::constant(PHP_VERSION) +``` + +όπως ακριβώς και στην PHP. Για λόγους απλότητας, αντί του `->`, χρησιμοποιούμε το `::`: + +```neon +DateTime()::format('Y-m-d') +# PHP: (new DateTime())->format('Y-m-d') + +@http.request::getUrl()::getHost() +# PHP: http.request')->getUrl()->getHost() +``` + +Αυτές οι εκφράσεις μπορούν να χρησιμοποιηθούν οπουδήποτε κατά τη [δημιουργία υπηρεσιών |#Service Creation], σε [ορίσματα |#Arguments], στο τμήμα [εγκατάστασης |#setup] ή σε [παραμέτρους |configuration#parameters]: + +```neon +parameters: + ipAddress: @http.request::getRemoteAddress() + +services: + database: + create: DatabaseFactory::create( @anotherService::getDsn() ) + setup: + - initialize( ::getenv('DB_USER') ) +``` + + +Ειδικές λειτουργίες .[#toc-special-functions] +--------------------------------------------- + +Μέσα σε αρχεία ρυθμίσεων, μπορείτε να χρησιμοποιήσετε αυτές τις ειδικές λειτουργίες: + +- `not()` για άρνηση τιμών +- `bool()`, `int()`, `float()`, `string()` για μετατροπή τύπου χωρίς απώλειες +- `typed()` για τη δημιουργία ενός πίνακα όλων των υπηρεσιών ενός συγκεκριμένου τύπου +- `tagged()` για τη δημιουργία ενός πίνακα όλων των υπηρεσιών με μια συγκεκριμένη ετικέτα + +```neon +services: + - Foo( + id: int(::getenv('ProjectId')) + productionMode: not(%debugMode%) + ) +``` + +Σε σύγκριση με το συμβατικό typecasting στην PHP, όπως το `(int)`, το lossless type casting θα πετάξει μια εξαίρεση για μη αριθμητικές τιμές. + +Η συνάρτηση `typed()` δημιουργεί έναν πίνακα όλων των υπηρεσιών ενός συγκεκριμένου τύπου (κλάση ή διεπαφή). Εξαιρεί τις υπηρεσίες με απενεργοποιημένη την αυτόματη σύνδεση. Μπορούν να καθοριστούν πολλαπλοί τύποι, χωρισμένοι με κόμμα. + +```neon +services: + - BarsDependent( typed(Bar) ) +``` + +Μπορείτε επίσης να περάσετε αυτόματα έναν πίνακα υπηρεσιών ενός συγκεκριμένου τύπου ως όρισμα χρησιμοποιώντας την [αυτόματη καλωδίωση |autowiring#Collection of Services]. + +Η συνάρτηση `tagged()` δημιουργεί έναν πίνακα όλων των υπηρεσιών με μια καθορισμένη ετικέτα. Μπορούν να παρατίθενται πολλαπλές ετικέτες, διαχωρισμένες με κόμμα. + +```neon +services: + - LoggersDependent( tagged(logger) ) +``` + + +Αυτόματη καλωδίωση .[#toc-autowiring] +===================================== -Το κλειδί autowired μπορεί να χρησιμοποιηθεί για να αποκλείσει μια υπηρεσία από την αυτόματη σύνδεση ή για να επηρεάσει τη συμπεριφορά της. Για περισσότερες πληροφορίες, ανατρέξτε στο [κεφάλαιο σχετικά με την αυτόματη σύνδεση |autowiring]. +Το κλειδί `autowired` σας επιτρέπει να τροποποιήσετε τη συμπεριφορά αυτόματης καλωδίωσης για μια συγκεκριμένη υπηρεσία. Για περισσότερες λεπτομέρειες, ανατρέξτε [στο κεφάλαιο αυτόματη σύνδεση |autowiring]. ```neon services: foo: create: Foo - autowired: false # Το foo αφαιρείται από την αυτόματη καλωδίωση + autowired: false # η υπηρεσία foo αποκλείεται από την αυτόματη καλωδίωση ``` Ετικέτες .[#toc-tags] ===================== -Οι πληροφορίες χρήστη μπορούν να προστεθούν σε μεμονωμένες υπηρεσίες με τη μορφή ετικετών: +Οι ετικέτες χρησιμοποιούνται για την προσθήκη συμπληρωματικών πληροφοριών στις υπηρεσίες. Μπορείτε να αντιστοιχίσετε μία ή περισσότερες ετικέτες σε μια υπηρεσία: ```neon services: @@ -360,7 +346,7 @@ services: - cached ``` -Οι ετικέτες μπορούν επίσης να έχουν μια τιμή: +Οι ετικέτες μπορούν επίσης να φέρουν τιμές: ```neon services: @@ -370,14 +356,14 @@ services: logger: monolog.logger.event ``` -Ένας πίνακας υπηρεσιών με συγκεκριμένες ετικέτες μπορεί να περάσει ως όρισμα χρησιμοποιώντας τη συνάρτηση `tagged()`. Μπορούν επίσης να καθοριστούν πολλαπλές ετικέτες που χωρίζονται με κόμμα. +Για να ανακτήσετε όλες τις υπηρεσίες με συγκεκριμένες ετικέτες, μπορείτε να χρησιμοποιήσετε τη λειτουργία `tagged()`: ```neon services: - LoggersDependent( tagged(logger) ) ``` -Τα ονόματα των υπηρεσιών μπορούν να ληφθούν από το δοχείο DI χρησιμοποιώντας τη μέθοδο `findByTag()`: +Στο δοχείο DI, μπορείτε να λάβετε τα ονόματα όλων των υπηρεσιών με μια συγκεκριμένη ετικέτα χρησιμοποιώντας τη μέθοδο `findByTag()`: ```php $names = $container->findByTag('logger'); @@ -386,10 +372,10 @@ $names = $container->findByTag('logger'); ``` -Inject Mode .[#toc-inject-mode] -=============================== +Λειτουργία έγχυσης .[#toc-inject-mode] +====================================== -Η σημαία `inject: true` χρησιμοποιείται για την ενεργοποίηση του περάσματος εξαρτήσεων μέσω δημόσιων μεταβλητών με τον σχολιασμό [inject |best-practices:inject-method-attribute#Inject Attributes] και τις μεθόδους [inject*() |best-practices:inject-method-attribute#inject Methods]. +Η χρήση της σημαίας `inject: true` ενεργοποιεί τη μεταβίβαση εξαρτήσεων μέσω δημόσιων μεταβλητών με το σχόλιο [inject |best-practices:inject-method-attribute#Inject Attributes] και τις μεθόδους [inject*() |best-practices:inject-method-attribute#inject Methods]. ```neon services: @@ -401,10 +387,10 @@ services: Από προεπιλογή, το `inject` είναι ενεργοποιημένο μόνο για τους παρουσιαστές. -Τροποποίηση των υπηρεσιών .[#toc-modification-of-services] -========================================================== +Τροποποιήσεις υπηρεσιών .[#toc-service-modifications] +===================================================== -Υπάρχει ένας αριθμός υπηρεσιών στο δοχείο DI που έχουν προστεθεί από ενσωματωμένο ή από [την επέκτασή σας |#di-extensions]. Οι ορισμοί αυτών των υπηρεσιών μπορούν να τροποποιηθούν στη διαμόρφωση. Για παράδειγμα, για την υπηρεσία `application.application`, η οποία είναι εξ ορισμού ένα αντικείμενο `Nette\Application\Application`, μπορούμε να αλλάξουμε την κλάση: +Ο περιέκτης DI περιέχει πολλές υπηρεσίες που προστίθενται είτε από ενσωματωμένες είτε από [επεκτάσεις χρηστών |#extensions]. Μπορείτε να τροποποιήσετε τους ορισμούς αυτών των υπηρεσιών απευθείας στη διαμόρφωση. Για παράδειγμα, μπορείτε να αλλάξετε την κλάση της υπηρεσίας `application.application`, η οποία είναι συμβατικά `Nette\Application\Application`, σε κάτι άλλο: ```neon services: @@ -413,9 +399,9 @@ services: alteration: true ``` -Η σημαία `alteration` είναι πληροφοριακή και δηλώνει ότι απλώς τροποποιούμε μια υπάρχουσα υπηρεσία. +Η σημαία `alteration` είναι πληροφοριακή, υποδεικνύοντας ότι απλώς τροποποιούμε μια υπάρχουσα υπηρεσία. -Μπορούμε επίσης να προσθέσουμε μια ρύθμιση: +Μπορούμε επίσης να συμπληρώσουμε τη ρύθμιση: ```neon services: @@ -426,7 +412,7 @@ services: - '$onStartup[]' = [@resource, init] ``` -Γι' αυτό υπάρχει το `reset`: +Εδώ είναι που το `reset` είναι χρήσιμο: ```neon services: @@ -439,7 +425,7 @@ services: - tags ``` -Μια υπηρεσία που προστίθεται με επέκταση μπορεί επίσης να αφαιρεθεί από το δοχείο: +Αν θέλετε να αφαιρέσετε μια υπηρεσία που προστέθηκε από μια επέκταση, μπορείτε να το κάνετε ως εξής: ```neon services: diff --git a/dependency-injection/en/services.texy b/dependency-injection/en/services.texy index ce393350eb..32fac58212 100644 --- a/dependency-injection/en/services.texy +++ b/dependency-injection/en/services.texy @@ -2,32 +2,32 @@ Service Definitions ******************* .[perex] -Configuration is where we place the definitions of custom services. This is done in section `services`. +Configuration is the place where we instruct the DI container on how to assemble individual services and how to connect them with other dependencies. Nette provides a very clear and elegant way to achieve this. -For example, this is how we create a service named `database`, which will be an instance of class `PDO`: +The `services` section in the NEON configuration file is where we define our custom services and their configurations. Let's look at a simple example of defining a service named `database`, which represents an instance of the `PDO` class: ```neon services: database: PDO('sqlite::memory:') ``` -The naming of services is used to allow us to [reference|#Referencing Services] them. If a service is not referenced, there is no need to name it. So we just use a bullet point instead of a name: +This configuration results in the following factory method in the [DI container|container]: -```neon -services: - - PDO('sqlite::memory:') # anonymous service +```php +public function createServiceDatabase(): PDO +{ + return new PDO('sqlite::memory:'); +} ``` -A one-line entry can be broken up into multiple lines to allow additional keys to be added, such as [#setup]. The alias for the `create:` key is `factory:`. +Service names allow us to reference them in other parts of the configuration file, using the format `@serviceName`. If there's no need to name the service, we can simply use a bullet point: ```neon services: - database: - create: PDO('sqlite::memory:') - setup: ... + - PDO('sqlite::memory:') ``` -We then retrieve the service from the DI container using the method `getService()` by name, or better yet, the method `getByType()` by type: +To retrieve a service from the DI container, we can use the `getService()` method with the service name as a parameter, or the `getByType()` method with the service type: ```php $database = $container->getService('database'); @@ -35,236 +35,114 @@ $database = $container->getByType(PDO::class); ``` -Creating a Service -================== +Service Creation +================ -Most often, we create a service by simply creating an instance of a class: +Most commonly, we create a service simply by instantiating a specific class. For example: ```neon services: database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` -Which will generate a factory method in [DI container|container]: - -```php -public function createServiceDatabase(): PDO -{ - return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret'); -} -``` - -Alternatively, a key `arguments` can be used to pass [arguments|#Arguments]: +If we need to expand the configuration with additional keys, the definition can be expanded into multiple lines: ```neon services: database: - create: PDO - arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] -``` - -A static method can also create a service: - -```neon -services: - database: My\Database::create(root, secret) + create: PDO('sqlite::memory:') + setup: ... ``` -Corresponds to PHP code: +The `create` key has an alias `factory`, both versions are common in practice. However, we recommend using `create`. -```php -public function createServiceDatabase(): PDO -{ - return My\Database::create('root', 'secret'); -} -``` - -A static method `My\Database::create()` is assumed to have a defined return value that the DI container needs to know. If it does not have it, we write the type to the configuration: +Constructor arguments or the creation method can alternatively be written in the `arguments` key: ```neon services: database: - create: My\Database::create(root, secret) - type: PDO + create: PDO + arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] ``` -Nette DI gives you extremely powerful expression facilities to write almost anything. For example, to [refer|#Referencing Services] to another service and call its method. For simplicity, `::` is used instead of `->`. +Services don't have to be created just by simple instantiation of a class; they can also result from calling static methods or methods of other services: ```neon services: - routerFactory: App\Router\Factory + database: DatabaseFactory::create() router: @routerFactory::create() ``` -Corresponds to PHP code: +Note that for simplicity, instead of `->`, we use `::`, see [#expression means]. These factory methods are generated: ```php -public function createServiceRouterFactory(): App\Router\Factory +public function createServiceDatabase(): PDO { - return new App\Router\Factory; + return DatabaseFactory::create(); } -public function createServiceRouter(): Router +public function createServiceRouter(): RouteList { return $this->getService('routerFactory')->create(); } ``` -Method calls can be chained together as in PHP: +The DI container needs to know the type of the created service. If we create a service using a method that doesn't have a specified return type, we must explicitly mention this type in the configuration: ```neon services: - foo: FooFactory::build()::get() -``` - -Corresponds to PHP code: - -```php -public function createServiceFoo() -{ - return FooFactory::build()->get(); -} + database: + create: DatabaseFactory::create() + type: PDO ``` Arguments ========= -Named parameters can also be used to pass arguments: +We pass arguments to constructors and methods in a manner very similar to regular PHP: ```neon services: - database: PDO( - 'mysql:host=127.0.0.1;dbname=test' # positional - username: root # named - password: secret # named - ) -``` - -The use of commas is optional when breaking arguments into multiple lines. - -Of course, we can also use [other services|#Referencing Services] or [parameters|configuration#parameters] as arguments: - -```neon -services: - - Foo(@anotherService, %appDir%) -``` - -Corresponds to PHP code: - -```php -public function createService01(): Foo -{ - return new Foo($this->getService('anotherService'), '...'); -} + database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` -If the first argument is [autowired|autowiring] and you want to specify the second one, omit the first one with the `_` character, for example `Foo(_, %appDir%)`. Or better yet, pass only the second argument as a named parameter, e.g. `Foo(path: %appDir%)`. - -Nette DI and the NEON format give you extremely powerful expressive facilities to write almost anything. Thus an argument can be a newly created object, you can call static methods, methods of other services, or even global functions using special notation: +For better readability, we can list the arguments on separate lines. In this format, the use of commas is optional: ```neon services: - analyser: My\Analyser( - FilesystemIterator(%appDir%) # create object - DateTime::createFromFormat('Y-m-d') # call static method - @anotherService # passing another service - @http.request::getRemoteAddress() # calling another service method - ::getenv(NetteMode) # call a global function + database: PDO( + 'mysql:host=127.0.0.1;dbname=test' + root + secret ) ``` -Corresponds to PHP code: - -```php -public function createServiceAnalyser(): My\Analyser -{ - return new My\Analyser( - new FilesystemIterator('...'), - DateTime::createFromFormat('Y-m-d'), - $this->getService('anotherService'), - $this->getService('http.request')->getRemoteAddress(), - getenv('NetteMode') - ); -} -``` - - -Special Functions ------------------ - -You can also use special functions in arguments to cast or negate values: - -- `not(%arg%)` negation -- `bool(%arg%)` lossless cast to bool -- `int(%arg%)` lossless cast to int -- `float(%arg%)` lossless cast to float -- `string(%arg%)` lossless cast to string +You can also name the arguments, which then allows you to not worry about their order: ```neon services: - - Foo( - id: int(::getenv('ProjectId')) - productionMode: not(%debugMode%) + database: PDO( + username: root + password: secret + dsn: 'mysql:host=127.0.0.1;dbname=test' ) ``` -Lossless rewriting differs from normal PHP rewriting, e.g. using `(int)`, in that it throws an exception for non-numeric values. - -Multiple services can be passed as arguments. An array of all services of a particular type (i.e., class or interface) is created by function `typed()`. The function will omit services that have autowiring disabled, and multiple types separated by a comma can be specified. +If you wish to omit certain arguments and use their default values or insert a service via [autowiring], use an underscore: ```neon services: - - BarsDependent( typed(Bar) ) -``` - -You can also pass an array of services automatically using [autowiring|autowiring#Collection of Services]. - -An array of all services with a certain [tag|#tags] is created by function `tagged()`. Multiple tags separated by a comma can be specified. - -```neon -services: - - LoggersDependent( tagged(logger) ) + foo: Foo(_, %appDir%) ``` - -Referencing Services -==================== - -Individual services are referenced using character `@` and name, so for example `@database`: - -```neon -services: - - create: Foo(@database) - setup: - - setCacheStorage(@cache.storage) -``` - -Corresponds to PHP code: - -```php -public function createService01(): Foo -{ - $service = new Foo($this->getService('database')); - $service->setCacheStorage($this->getService('cache.storage')); - return $service; -} -``` - -Even anonymous services can be referenced using a callback, just specify their type (class or interface) instead of their name. However, this is usually not necessary due to [autowiring]. - -```neon -services: - - create: Foo(@Nette\Database\Connection) - setup: - - setCacheStorage(@cache.storage) -``` +Arguments can be services, parameters, and much more, see [#expression means]. Setup ===== -In the setup section we list the methods to be called when creating the service: +In the `setup` section, we define the methods that should be called when creating the service. ```neon services: @@ -274,7 +152,7 @@ services: - setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) ``` -Corresponds to PHP code: +In PHP, this would look like: ```php public function createServiceDatabase(): PDO @@ -285,8 +163,7 @@ public function createServiceDatabase(): PDO } ``` -Properites can also be set. Adding an element to an array is also supported, and should be written in quotes so as not to conflict with NEON syntax: - +In addition to method calls, you can also pass values to properties. Adding an element to an array is also supported, but you need to enclose it in quotes to avoid colliding with the NEON syntax: ```neon services: @@ -297,7 +174,7 @@ services: - '$onClick[]' = [@bar, clickHandler] ``` -Corresponds to PHP code: +In PHP, this would translate to: ```php public function createServiceFoo(): Foo @@ -309,8 +186,7 @@ public function createServiceFoo(): Foo } ``` -However, static methods or methods of other services can also be called in the setup. We pass the actual service to them as `@self`: - +In the setup, you can also call static methods or methods of other services. If you need to pass the current service as an argument, use `@self`: ```neon services: @@ -321,7 +197,7 @@ services: - @anotherService::setFoo(@self) ``` -Corresponds to PHP code: +Note that for simplicity, instead of `->`, we use `::`, see [#expression means]. This generates the following factory method: ```php public function createServiceFoo(): Foo @@ -334,23 +210,133 @@ public function createServiceFoo(): Foo ``` +Expression Means +================ + +Nette DI provides us with exceptionally rich expression capabilities, allowing us to articulate almost anything. In configuration files, we can use [parameters|configuration#parameters]: + +```neon +# parameter +%wwwDir% + +# value under a parameter key +%mailer.user% + +# parameter within a string +'%wwwDir%/images' +``` + +We can also create objects, call methods, and functions: + +```neon +# create an object +DateTime() + +# call a static method +Collator::create(%locale%) + +# call a PHP function +::getenv(DB_USER) +``` + +Refer to services either by their name or by type: + +```neon +# service by name +@database + +# service by type +@Nette\Database\Connection +``` + +Use constants: + +```neon +# class constant +FilesystemIterator::SKIP_DOTS + +# global constant obtained by the PHP function constant() +::constant(PHP_VERSION) +``` + +Method calls can be chained, just like in PHP. For simplicity, instead of `->`, we use `::`: + +```neon +DateTime()::format('Y-m-d') +# PHP: (new DateTime())->format('Y-m-d') + +@http.request::getUrl()::getHost() +# PHP: $this->getService('http.request')->getUrl()->getHost() +``` + +These expressions can be used anywhere when [creating services|#Service Creation], in [arguments|#Arguments], in the [#setup] section, or [parameters|configuration#parameters]: + +```neon +parameters: + ipAddress: @http.request::getRemoteAddress() + +services: + database: + create: DatabaseFactory::create( @anotherService::getDsn() ) + setup: + - initialize( ::getenv('DB_USER') ) +``` + + +Special Functions +----------------- + +Within configuration files, you can utilize these special functions: + +- `not()` for value negation +- `bool()`, `int()`, `float()`, `string()` for lossless type casting +- `typed()` to generate an array of all services of a specified type +- `tagged()` to create an array of all services with a given tag + +```neon +services: + - Foo( + id: int(::getenv('ProjectId')) + productionMode: not(%debugMode%) + ) +``` + +Compared to conventional typecasting in PHP, like `(int)`, lossless type casting will throw an exception for non-numeric values. + +The `typed()` function creates an array of all services of a particular type (class or interface). It excludes services with autowiring turned off. Multiple types can be specified, separated by commas. + +```neon +services: + - BarsDependent( typed(Bar) ) +``` + +You can also automatically pass an array of services of a specific type as an argument using [autowiring|autowiring#Collection of Services]. + +The `tagged()` function creates an array of all services with a specified tag. Multiple tags can be listed, separated by commas. + +```neon +services: + - LoggersDependent( tagged(logger) ) +``` + + Autowiring ========== -The autowired key can be used to exclude a service from autowiring or to influence its behavior. See [chapter on autowiring|autowiring] for more information. +The `autowired` key allows you to modify the autowiring behavior for a particular service. For more details, see [the autowiring chapter|autowiring]. ```neon services: foo: create: Foo - autowired: false # foo is removed from autowiring + autowired: false # the foo service is excluded from autowiring ``` Tags ==== -User information can be added to individual services in the form of tags: +Tags are used to add supplementary information to services. You can assign one or more tags to a service: ```neon services: @@ -360,7 +346,7 @@ services: - cached ``` -Tags can also have a value: +Tags can also carry values: ```neon services: @@ -370,26 +356,26 @@ services: logger: monolog.logger.event ``` -An array of services with certain tags can be passed as an argument using the function `tagged()`. Multiple tags separated by a comma can also be specified. +To retrieve all services with specific tags, you can use the `tagged()` function: ```neon services: - LoggersDependent( tagged(logger) ) ``` -Service names can be obtained from the DI container using the method `findByTag()`: +In the DI container, you can obtain the names of all services with a specific tag using the `findByTag()` method: ```php $names = $container->findByTag('logger'); // $names is an array containing the service name and tag value -// i.e. ['foo' => 'monolog.logger.event', ...] +// e.g. ['foo' => 'monolog.logger.event', ...] ``` Inject Mode =========== -The `inject: true` flag is used to activate the passing of dependencies via public variables with the [inject |best-practices:inject-method-attribute#Inject Attributes] annotation and the [inject*() |best-practices:inject-method-attribute#inject Methods] methods. +Using the flag `inject: true` activates the passing of dependencies via public variables with the [inject |best-practices:inject-method-attribute#Inject Attributes] annotation and [inject*() |best-practices:inject-method-attribute#inject Methods] methods. ```neon services: @@ -401,10 +387,10 @@ services: By default, `inject` is only activated for presenters. -Modification of Services -======================== +Service Modifications +===================== -There are a number of services in the DI container that have been added by built-in or [your extension|#di-extensions]. The definitions of these services can be modified in the configuration. For example, for service `application.application`, which is by default an object `Nette\Application\Application`, we can change the class: +The DI container contains many services added either by built-in or [user extensions|#extensions]. You can modify the definitions of these services directly in the configuration. For instance, you can change the class of the `application.application` service, which is conventionally `Nette\Application\Application`, to something else: ```neon services: @@ -413,9 +399,9 @@ services: alteration: true ``` -The `alteration` flag is informative and says that we are just modifying an existing service. +The `alteration` flag is informative, indicating that we're merely modifying an existing service. -We can also add a setup: +We can also supplement the setup: ```neon services: @@ -426,7 +412,7 @@ services: - '$onStartup[]' = [@resource, init] ``` -When rewriting a service, we may want to remove the original arguments, setup items or tags, which is what `reset` is for: +When overwriting a service, you might want to remove original arguments, setup items, or tags, which is where `reset` comes in handy: ```neon services: @@ -439,7 +425,7 @@ services: - tags ``` -A service added by extension can also be removed from the container: +If you wish to remove a service added by an extension, you can do so like this: ```neon services: diff --git a/dependency-injection/es/services.texy b/dependency-injection/es/services.texy index 4c971094e4..44176f808f 100644 --- a/dependency-injection/es/services.texy +++ b/dependency-injection/es/services.texy @@ -2,32 +2,32 @@ Definiciones de servicios ************************* .[perex] -Configuración es donde colocamos las definiciones de los servicios personalizados. Esto se hace en la sección `services`. +La configuración es el lugar donde instruimos al contenedor DI sobre cómo ensamblar servicios individuales y cómo conectarlos con otras dependencias. Nette proporciona una forma muy clara y elegante de conseguirlo. -Por ejemplo, así es como creamos un servicio llamado `database`, que será una instancia de la clase `PDO`: +La sección `services` en el archivo de configuración NEON es donde definimos nuestros servicios personalizados y sus configuraciones. Veamos un ejemplo sencillo de definición de un servicio llamado `database`, que representa una instancia de la clase `PDO`: ```neon services: database: PDO('sqlite::memory:') ``` -El nombre de los servicios se utiliza para permitirnos [referenciarlos|#Referencing Services]. Si un servicio no es referenciado, no hay necesidad de nombrarlo. Así que simplemente usamos una viñeta en lugar de un nombre: +Esta configuración resulta en el siguiente método de fábrica en el [contenedor DI |container]: -```neon -services: - - PDO('sqlite::memory:') # servicio anónimo +```php +public function createServiceDatabase(): PDO +{ + return new PDO('sqlite::memory:'); +} ``` -Una entrada de una línea puede dividirse en varias líneas para permitir añadir claves adicionales, como [#setup]. El alias de la clave `create:` es `factory:`. +Los nombres de los servicios nos permiten referenciarlos en otras partes del fichero de configuración, utilizando el formato `@serviceName`. Si no hay necesidad de nombrar el servicio, podemos usar simplemente una viñeta: ```neon services: - database: - create: PDO('sqlite::memory:') - setup: ... + - PDO('sqlite::memory:') ``` -A continuación recuperamos el servicio del contenedor DI usando el método `getService()` por nombre, o mejor aún, el método `getByType()` por tipo: +Para recuperar un servicio del contenedor DI, podemos utilizar el método `getService()` con el nombre del servicio como parámetro, o el método `getByType()` con el tipo de servicio: ```php $database = $container->getService('database'); @@ -35,236 +35,114 @@ $database = $container->getByType(PDO::class); ``` -Creación de un servicio .[#toc-creating-a-service] -================================================== +Creación de servicios .[#toc-service-creation] +============================================== -La mayoría de las veces, creamos un servicio simplemente creando una instancia de una clase: +Lo más común es crear un servicio simplemente instanciando una clase específica. Por ejemplo: ```neon services: database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` -Lo que generará un método de fábrica en [DI container|container]: - -```php -public function createServiceDatabase(): PDO -{ - return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret'); -} -``` - -Alternativamente, se puede usar una clave `arguments` para pasar [arguments|#Arguments]: +Si necesitamos ampliar la configuración con claves adicionales, la definición puede ampliarse en varias líneas: ```neon services: database: - create: PDO - arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] -``` - -Un método estático también puede crear un servicio: - -```neon -services: - database: My\Database::create(root, secret) + create: PDO('sqlite::memory:') + setup: ... ``` -Corresponde al código PHP: +La clave `create` tiene un alias `factory`, ambas versiones son comunes en la práctica. No obstante, recomendamos utilizar `create`. -```php -public function createServiceDatabase(): PDO -{ - return My\Database::create('root', 'secret'); -} -``` - -Se supone que un método estático `My\Database::create()` tiene un valor de retorno definido que el contenedor DI necesita conocer. Si no lo tiene, escribimos el tipo en la configuración: +Los argumentos del constructor o el método de creación pueden escribirse alternativamente en la clave `arguments`: ```neon services: database: - create: My\Database::create(root, secret) - type: PDO + create: PDO + arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] ``` -Nette DI te da facilidades de expresión extremadamente potentes para escribir casi cualquier cosa. Por ejemplo, para [refer|#Referencing services] a otro servicio y llamar a su método. Para simplificar, se utiliza `::` en lugar de `->`. +Los servicios no tienen por qué crearse por simple instanciación de una clase; también pueden ser el resultado de llamar a métodos estáticos o a métodos de otros servicios: ```neon services: - routerFactory: App\Router\Factory + database: DatabaseFactory::create() router: @routerFactory::create() ``` -Corresponde al código PHP: +Nótese que, por simplicidad, en lugar de `->`, utilizamos `::`, véase la [expresión significa |#expression means]. Estos métodos de fábrica se generan: ```php -public function createServiceRouterFactory(): App\Router\Factory +public function createServiceDatabase(): PDO { - return new App\Router\Factory; + return DatabaseFactory::create(); } -public function createServiceRouter(): Router +public function createServiceRouter(): RouteList { return $this->getService('routerFactory')->create(); } ``` -Las llamadas a métodos se pueden encadenar como en PHP: +El contenedor DI necesita conocer el tipo del servicio creado. Si creamos un servicio utilizando un método que no tiene un tipo de retorno especificado, debemos mencionar explícitamente este tipo en la configuración: ```neon services: - foo: FooFactory::build()::get() -``` - -Corresponde a código PHP: - -```php -public function createServiceFoo() -{ - return FooFactory::build()->get(); -} + database: + create: DatabaseFactory::create() + type: PDO ``` Argumentos .[#toc-arguments] ============================ -Los parámetros con nombre también pueden usarse para pasar argumentos: +Pasamos argumentos a los constructores y métodos de una manera muy similar a PHP normal: ```neon services: - database: PDO( - 'mysql:host=127.0.0.1;dbname=test' # positional - username: root # named - password: secret # named - ) -``` - -El uso de comas es opcional cuando se dividen los argumentos en varias líneas. - -Por supuesto, también podemos utilizar [otros servicios|#Referencing Services] o [parámetros|configuration#parameters] como argumentos: - -```neon -services: - - Foo(@anotherService, %appDir%) -``` - -Corresponde a código PHP: - -```php -public function createService01(): Foo -{ - return new Foo($this->getService('anotherService'), '...'); -} + database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` -Si el primer argumento es [autowired|autowiring] y quieres especificar el segundo, omite el primero con el caracter `_`, por ejemplo `Foo(_, %appDir%)`. O mejor aún, pase sólo el segundo argumento como un parámetro con nombre, por ejemplo `Foo(path: %appDir%)`. - -Nette DI y el formato NEON le ofrecen facilidades expresivas extremadamente potentes para escribir casi cualquier cosa. Así, un argumento puede ser un objeto recién creado, puede llamar a métodos estáticos, métodos de otros servicios, o incluso funciones globales utilizando una notación especial: +Para una mejor legibilidad, podemos listar los argumentos en líneas separadas. En este formato, el uso de comas es opcional: ```neon services: - analyser: My\Analyser( - FilesystemIterator(%appDir%) # crear objeto - DateTime::createFromFormat('Y-m-d') # llamar método estático - @anotherService # pasar otro servicio - @http.request::getRemoteAddress() # llamar a otro método de servicio - ::getenv(NetteMode) # llamar a una función global + database: PDO( + 'mysql:host=127.0.0.1;dbname=test' + root + secret ) ``` -Corresponde al código PHP: - -```php -public function createServiceAnalyser(): My\Analyser -{ - return new My\Analyser( - new FilesystemIterator('...'), - DateTime::createFromFormat('Y-m-d'), - $this->getService('anotherService'), - $this->getService('http.request')->getRemoteAddress(), - getenv('NetteMode') - ); -} -``` - - -Funciones especiales .[#toc-special-functions] ----------------------------------------------- - -También puede utilizar funciones especiales en los argumentos para convertir o negar valores: - -- `not(%arg%)` negation -- `bool(%arg%)` lossless cast to bool -- `int(%arg%)` lossless cast to int -- `float(%arg%)` lossless cast to float -- `string(%arg%)` lossless cast to string +También puedes nombrar los argumentos, lo que te permitirá despreocuparte de su orden: ```neon services: - - Foo( - id: int(::getenv('ProjectId')) - productionMode: not(%debugMode%) + database: PDO( + username: root + password: secret + dsn: 'mysql:host=127.0.0.1;dbname=test' ) ``` -La reescritura sin pérdidas difiere de la reescritura PHP normal, por ejemplo usando `(int)`, en que lanza una excepción para valores no numéricos. - -Se pueden pasar múltiples servicios como argumentos. La función `typed()` crea un array de todos los servicios de un tipo particular (clase o interfaz). La función omitirá los servicios que tengan desactivado el autowiring, y se pueden especificar múltiples tipos separados por una coma. +Si desea omitir ciertos argumentos y utilizar sus valores por defecto o insertar un servicio mediante [autocableado |autowiring], utilice un guión bajo: ```neon services: - - BarsDependent( typed(Bar) ) -``` - -También puede pasar un array de servicios automáticamente usando [autowiring|autowiring#Collection of Services]. - -La función `tagged()` crea una matriz de todos los servicios con una determinada [tag|#tags]. Se pueden especificar múltiples etiquetas separadas por una coma. - -```neon -services: - - LoggersDependent( tagged(logger) ) + foo: Foo(_, %appDir%) ``` - -Referencia a servicios .[#toc-referencing-services] -=================================================== - -Los servicios individuales se referencian utilizando el carácter `@` y el nombre, así por ejemplo `@database`: - -```neon -services: - - create: Foo(@database) - setup: - - setCacheStorage(@cache.storage) -``` - -Corresponde a código PHP: - -```php -public function createService01(): Foo -{ - $service = new Foo($this->getService('database')); - $service->setCacheStorage($this->getService('cache.storage')); - return $service; -} -``` - -Incluso los servicios anónimos pueden ser referenciados usando una llamada de retorno, simplemente especificando su tipo (clase o interfaz) en lugar de su nombre. Sin embargo, esto no suele ser necesario debido a [autowiring]. - -```neon -services: - - create: Foo(@Nette\Database\Connection) - setup: - - setCacheStorage(@cache.storage) -``` +Los argumentos pueden ser servicios, parámetros y mucho más, véase [medios de expresión |#expression means]. Configuración .[#toc-setup] =========================== -En la sección setup listamos los métodos a llamar al crear el servicio: +En la sección `setup`, definimos los métodos que deben ser llamados al crear el servicio. ```neon services: @@ -274,7 +152,7 @@ services: - setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) ``` -Corresponde al código PHP: +En PHP, esto se vería así: ```php public function createServiceDatabase(): PDO @@ -285,8 +163,7 @@ public function createServiceDatabase(): PDO } ``` -También se pueden establecer propiedades. También se puede añadir un elemento a un array, y debe escribirse entre comillas para no entrar en conflicto con la sintaxis de NEON: - +Además de llamadas a métodos, también puede pasar valores a propiedades. También se puede añadir un elemento a un array, pero es necesario encerrarlo entre comillas para evitar colisiones con la sintaxis NEON: ```neon services: @@ -297,7 +174,7 @@ services: - '$onClick[]' = [@bar, clickHandler] ``` -Corresponde a código PHP: +En PHP, esto se traduciría como: ```php public function createServiceFoo(): Foo @@ -309,8 +186,7 @@ public function createServiceFoo(): Foo } ``` -Sin embargo, los métodos estáticos o de otros servicios también pueden ser llamados en la configuración. Les pasamos el servicio real como `@self`: - +En la configuración, también puede llamar a métodos estáticos o métodos de otros servicios. Si necesita pasar el servicio actual como argumento, utilice `@self`: ```neon services: @@ -321,7 +197,7 @@ services: - @anotherService::setFoo(@self) ``` -Corresponde al código PHP: +Tenga en cuenta que, para simplificar, en lugar de `->`, utilizamos `::`, véase la [expresión significa |#expression means]. Esto genera el siguiente método de fábrica: ```php public function createServiceFoo(): Foo @@ -334,23 +210,133 @@ public function createServiceFoo(): Foo ``` -Autowiring (autocableado) .[#toc-autowiring] +Medios de expresión .[#toc-expression-means] ============================================ -La clave de autocableado se puede utilizar para excluir un servicio del autocableado o para influir en su comportamiento. Ver [chapter on autowiring|autowiring] para más información. +Nette DI nos proporciona capacidades de expresión excepcionalmente ricas, permitiéndonos articular casi cualquier cosa. En los archivos de configuración, podemos utilizar [parámetros |configuration#parameters]: + +```neon +# parámetro +%wwwDir% + +# valor bajo una clave de parámetro +%mailer.user% + +# parámetro dentro de una cadena +'%wwwDir%/images' +``` + +También podemos crear objetos, llamar a métodos y funciones: + +```neon +# crear un objeto +DateTime() + +# llamar a un método estático +Collator::create(%locale%) + +# llamar a una función PHP +::getenv(DB_USER) +``` + +Referirse a los servicios por su nombre o por su tipo: + +```neon +# servicio por nombre +@database + +# servicio por tipo +@Nette\Database\Connection +``` + +Utilizar constantes: + +```neon +# constante de clase +FilesystemIterator::SKIP_DOTS + +# constante global obtenida por la función PHP constant() +::constant(PHP_VERSION) +``` + +Las llamadas a métodos pueden encadenarse, como en PHP. Para simplificar, en lugar de `->`, usamos `::`: + +```neon +DateTime()::format('Y-m-d') +# PHP: (new DateTime())->format('A-m-d') + +@http.request::getUrl()::getHost() +# PHP: $this->getService('http.request')->getUrl()->getHost() +``` + +Estas expresiones se pueden utilizar en cualquier lugar al [crear servicios |#Service Creation], en [argumentos |#Arguments], en la sección de [configuración |#setup] o [parámetros |configuration#parameters]: + +```neon +parameters: + ipAddress: @http.request::getRemoteAddress() + +services: + database: + create: DatabaseFactory::create( @anotherService::getDsn() ) + setup: + - initialize( ::getenv('DB_USER') ) +``` + + +Funciones especiales .[#toc-special-functions] +---------------------------------------------- + +Dentro de los archivos de configuración, puede utilizar estas funciones especiales: + +- `not()` para la negación de valores +- `bool()`, `int()`, `float()`, `string()` para la conversión de tipos sin pérdidas +- `typed()` para generar una matriz de todos los servicios de un tipo especificado +- `tagged()` para crear una matriz de todos los servicios con una etiqueta determinada + +```neon +services: + - Foo( + id: int(::getenv('ProjectId')) + productionMode: not(%debugMode%) + ) +``` + +Comparado con el encasillamiento convencional en PHP, como `(int)`, el encasillamiento sin pérdida lanzará una excepción para valores no numéricos. + +La función `typed()` crea un array de todos los servicios de un tipo particular (clase o interfaz). Excluye los servicios con autocableado desactivado. Se pueden especificar varios tipos, separados por comas. + +```neon +services: + - BarsDependent( typed(Bar) ) +``` + +También puede pasar automáticamente una matriz de servicios de un tipo específico como argumento utilizando [autowiring |autowiring#Collection of Services]. + +La función `tagged()` crea una matriz de todos los servicios con una etiqueta especificada. Se pueden listar varias etiquetas, separadas por comas. + +```neon +services: + - LoggersDependent( tagged(logger) ) +``` + + +Autocableado .[#toc-autowiring] +=============================== + +La tecla `autowired` permite modificar el comportamiento del autocableado para un servicio en particular. Para más detalles, consulte [el capítulo |autowiring] sobre autocableado. ```neon services: foo: create: Foo - autowired: false # foo is removed from autowiring + autowired: false # el servicio foo queda excluido del autocableado ``` Etiquetas .[#toc-tags] ====================== -Se puede añadir información de usuario a servicios individuales en forma de etiquetas: +Las etiquetas se utilizan para añadir información complementaria a los servicios. Puede asignar una o varias etiquetas a un servicio: ```neon services: @@ -360,7 +346,7 @@ services: - cached ``` -Las etiquetas también pueden tener un valor: +Las etiquetas también pueden llevar valores: ```neon services: @@ -370,26 +356,26 @@ services: logger: monolog.logger.event ``` -Con la función `tagged()` se puede pasar como argumento un array de servicios con determinadas etiquetas. También se pueden especificar varias etiquetas separadas por una coma. +Para recuperar todos los servicios con etiquetas específicas, puede utilizar la función `tagged()`: ```neon services: - LoggersDependent( tagged(logger) ) ``` -Los nombres de los servicios pueden obtenerse del contenedor DI utilizando el método `findByTag()`: +En el contenedor DI, puede obtener los nombres de todos los servicios con una etiqueta específica utilizando el método `findByTag()`: ```php $names = $container->findByTag('logger'); -// $names es una matriz que contiene el nombre del servicio y el valor de la etiqueta -// i.e. ['foo' => 'monolog.logger.event', ...] +// $names es un array que contiene el nombre del servicio y el valor de la etiqueta +// por ejemplo ['foo' => 'monolog.logger.event', ...] ``` Modo de inyección .[#toc-inject-mode] ===================================== -El indicador `inject: true` se utiliza para activar el paso de dependencias a través de variables públicas con la anotación [inject |best-practices:inject-method-attribute#Inject Attributes] y los métodos [inject*() |best-practices:inject-method-attribute#inject Methods]. +El uso de la bandera `inject: true` activa el paso de dependencias a través de variables públicas con la anotación [inject |best-practices:inject-method-attribute#Inject Attributes] y los métodos [inject*() |best-practices:inject-method-attribute#inject Methods]. ```neon services: @@ -401,10 +387,10 @@ services: Por defecto, `inject` sólo está activado para los presentadores. -Modificación de servicios .[#toc-modification-of-services] -========================================================== +Modificaciones del servicio .[#toc-service-modifications] +========================================================= -Hay una serie de servicios en el contenedor DI que han sido añadidos por built-in o [su extensión|#di-extensions]. Las definiciones de estos servicios se pueden modificar en la configuración. Por ejemplo, para el servicio `application.application`, que por defecto es un objeto `Nette\Application\Application`, podemos cambiar la clase: +El contenedor DI contiene muchos servicios añadidos por [extensiones |#extensions] incorporadas o [de usuario |#extensions]. Puedes modificar las definiciones de estos servicios directamente en la configuración. Por ejemplo, puede cambiar la clase del servicio `application.application`, que convencionalmente es `Nette\Application\Application`, por otra: ```neon services: @@ -413,9 +399,9 @@ services: alteration: true ``` -La bandera `alteration` es informativa e indica que estamos modificando un servicio existente. +La bandera `alteration` es informativa, indicando que simplemente estamos modificando un servicio existente. -También podemos añadir una configuración: +También podemos complementar la configuración: ```neon services: @@ -426,7 +412,7 @@ services: - '$onStartup[]' = [@resource, init] ``` -Al reescribir un servicio, es posible que queramos eliminar los argumentos, elementos de configuración o etiquetas originales, que es para lo que sirve `reset`: +Al sobrescribir un servicio, es posible que desee eliminar los argumentos originales, elementos de configuración o etiquetas, que es donde `reset` es muy útil: ```neon services: @@ -439,7 +425,7 @@ services: - tags ``` -Un servicio añadido por extensión también se puede eliminar del contenedor: +Si deseas eliminar un servicio añadido por una extensión, puedes hacerlo así: ```neon services: diff --git a/dependency-injection/fr/services.texy b/dependency-injection/fr/services.texy index d4bd5296c3..0e9e312fbf 100644 --- a/dependency-injection/fr/services.texy +++ b/dependency-injection/fr/services.texy @@ -2,32 +2,32 @@ Définitions des services ************************ .[perex] -La configuration est l'endroit où nous plaçons les définitions des services personnalisés. Ceci est fait dans la section `services`. +La configuration est l'endroit où nous indiquons au conteneur DI comment assembler des services individuels et comment les relier à d'autres dépendances. Nette fournit une méthode très claire et élégante pour y parvenir. -Par exemple, voici comment nous créons un service nommé `database`, qui sera une instance de la classe `PDO`: +La section `services` du fichier de configuration NEON est l'endroit où nous définissons nos services personnalisés et leurs configurations. Examinons un exemple simple de définition d'un service nommé `database`, qui représente une instance de la classe `PDO`: ```neon services: database: PDO('sqlite::memory:') ``` -Le nommage des services est utilisé pour nous permettre de les [référencer |#Referencing Services]. Si un service n'est pas référencé, il n'est pas nécessaire de le nommer. Nous utilisons donc simplement une puce au lieu d'un nom : +Cette configuration se traduit par la méthode d'usine suivante dans le [conteneur DI |container]: -```neon -services: - - PDO('sqlite::memory:') # service anonyme +```php +public function createServiceDatabase(): PDO +{ + return new PDO('sqlite::memory:'); +} ``` -Une entrée d'une ligne peut être décomposée en plusieurs lignes pour permettre l'ajout de clés supplémentaires, telles que [setup |#setup]. L'alias de la clé `create:` est `factory:`. +Les noms des services nous permettent de les référencer dans d'autres parties du fichier de configuration, en utilisant le format `@serviceName`. S'il n'est pas nécessaire de nommer le service, nous pouvons simplement utiliser un point : ```neon services: - database: - create: PDO('sqlite::memory:') - setup: ... + - PDO('sqlite::memory:') ``` -Nous récupérons ensuite le service dans le conteneur DI en utilisant la méthode `getService()` par nom, ou mieux encore, la méthode `getByType()` par type : +Pour récupérer un service dans le conteneur DI, nous pouvons utiliser la méthode `getService()` avec le nom du service comme paramètre, ou la méthode `getByType()` avec le type de service : ```php $database = $container->getService('database'); @@ -35,236 +35,114 @@ $database = $container->getByType(PDO::class); ``` -Création d'un service .[#toc-creating-a-service] -================================================ +Création de services .[#toc-service-creation] +============================================= -Le plus souvent, nous créons un service en créant simplement une instance d'une classe : +Le plus souvent, nous créons un service en instanciant simplement une classe spécifique. Par exemple, nous pouvons créer un service en instanciant une classe spécifique : ```neon services: database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` -Ce qui va générer une méthode de fabrique dans le [conteneur DI |container]: - -```php -public function createServiceDatabase(): PDO -{ - return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret'); -} -``` - -Alternativement, une clé `arguments` peut être utilisée pour passer des [arguments |#Arguments]: +Si nous avons besoin d'étendre la configuration avec des clés supplémentaires, la définition peut être développée en plusieurs lignes : ```neon services: database: - create: PDO - arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] -``` - -Une méthode statique peut également créer un service : - -```neon -services: - database: My\Database::create(root, secret) + create: PDO('sqlite::memory:') + setup: ... ``` -Correspond au code PHP : +La clé `create` a un alias `factory`, les deux versions sont courantes dans la pratique. Cependant, nous recommandons d'utiliser `create`. -```php -public function createServiceDatabase(): PDO -{ - return My\Database::create('root', 'secret'); -} -``` - -Une méthode statique `My\Database::create()` est supposée avoir une valeur de retour définie que le conteneur DI doit connaître. S'il ne l'a pas, nous écrivons le type dans la configuration : +Les arguments du constructeur ou la méthode de création peuvent également être écrits dans la clé `arguments`: ```neon services: database: - create: My\Database::create(root, secret) - type: PDO + create: PDO + arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] ``` -Nette DI vous donne des facilités d'expression extrêmement puissantes pour écrire presque n'importe quoi. Par exemple, pour [faire référence |#Referencing Services] à un autre service et appeler sa méthode. Pour simplifier, on utilise `::` au lieu de `->`. +Les services ne doivent pas nécessairement être créés par la simple instanciation d'une classe ; ils peuvent également résulter de l'appel de méthodes statiques ou de méthodes d'autres services : ```neon services: - routerFactory: App\Router\Factory + database: DatabaseFactory::create() router: @routerFactory::create() ``` -Correspond au code PHP : +Notez que pour plus de simplicité, au lieu de `->`, nous utilisons `::`, voir [les moyens d'expression. |#expression means] Ces méthodes d'usine sont générées : ```php -public function createServiceRouterFactory(): App\Router\Factory +public function createServiceDatabase(): PDO { - return new App\Router\Factory; + return DatabaseFactory::create(); } -public function createServiceRouter(): Router +public function createServiceRouter(): RouteList { return $this->getService('routerFactory')->create(); } ``` -Les appels de méthode peuvent être enchaînés comme en PHP : +Le conteneur DI doit connaître le type du service créé. Si nous créons un service en utilisant une méthode qui n'a pas de type de retour spécifié, nous devons explicitement mentionner ce type dans la configuration : ```neon services: - foo: FooFactory::build()::get() -``` - -Correspond au code PHP : - -```php -public function createServiceFoo() -{ - return FooFactory::build()->get(); -} + database: + create: DatabaseFactory::create() + type: PDO ``` Arguments .[#toc-arguments] =========================== -Les paramètres nommés peuvent également être utilisés pour transmettre des arguments : +Nous passons des arguments aux constructeurs et aux méthodes d'une manière très similaire à celle de PHP : ```neon services: - database: PDO( - mysql:host=127.0.0.1;dbname=test' # positionnel - username: root # nommé - password: secret # nommé - ) -``` - -L'utilisation de virgules est facultative lorsque les arguments sont répartis sur plusieurs lignes. - -Bien entendu, nous pouvons également utiliser [d'autres services |#Referencing Services] ou [paramètres |configuration#parameters] comme arguments : - -```neon -services: - - Foo(@anotherService, %appDir%) -``` - -Correspond au code PHP : - -```php -public function createService01(): Foo -{ - return new Foo($this->getService('anotherService'), '...'); -} + database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` -Si le premier argument est [autodirigé |autowiring] et que vous souhaitez spécifier le second, omettez le premier avec `_` character, for example `Foo(_, %appDir%)`. Ou mieux encore, passez uniquement le second argument comme paramètre nommé, par exemple `Foo(path: %appDir%)`. - -Nette DI et le format NEON vous offrent des possibilités d'expression extrêmement puissantes pour écrire presque tout. Ainsi, un argument peut être un objet nouvellement créé, vous pouvez appeler des méthodes statiques, des méthodes d'autres services, ou même des fonctions globales en utilisant une notation spéciale : +Pour une meilleure lisibilité, nous pouvons lister les arguments sur des lignes séparées. Dans ce format, l'utilisation des virgules est optionnelle : ```neon services: - analyser: My\Analyser( - FilesystemIterator(%appDir%) # créer un objet - DateTime::createFromFormat('Y-m-d') # appelle la méthode statique - @anotherService # passage d'un autre service - @http.request::getRemoteAddress() # appel d'une autre méthode de service - ::getenv(NetteMode) # appel d'une fonction globale + database: PDO( + 'mysql:host=127.0.0.1;dbname=test' + root + secret ) ``` -Correspond au code PHP : - -```php -public function createServiceAnalyser(): My\Analyser -{ - return new My\Analyser( - new FilesystemIterator('...'), - DateTime::createFromFormat('Y-m-d'), - $this->getService('anotherService'), - $this->getService('http.request')->getRemoteAddress(), - getenv('NetteMode') - ); -} -``` - - -Fonctions spéciales .[#toc-special-functions] ---------------------------------------------- - -Vous pouvez également utiliser des fonctions spéciales dans les arguments pour exprimer ou nier des valeurs : - -- `not(%arg%)` négation -- `bool(%arg%)` Conversion sans perte en bool -- `int(%arg%)` Conversion sans perte en int -- `float(%arg%)` conversion sans perte en float -- `string(%arg%)` Moulage sans perte vers string +Vous pouvez également nommer les arguments, ce qui vous permet de ne pas vous soucier de leur ordre : ```neon services: - - Foo( - id: int(::getenv('ProjectId')) - productionMode: not(%debugMode%) + database: PDO( + username: root + password: secret + dsn: 'mysql:host=127.0.0.1;dbname=test' ) ``` -La réécriture sans perte diffère de la réécriture PHP normale, par exemple en utilisant `(int)`, car elle lève une exception pour les valeurs non numériques. - -Plusieurs services peuvent être passés en argument. Un tableau de tous les services d'un type particulier (c'est-à-dire une classe ou une interface) est créé par la fonction `typed()`. La fonction omettra les services dont le câblage automatique est désactivé, et plusieurs types séparés par une virgule peuvent être spécifiés. +Si vous souhaitez omettre certains arguments et utiliser leurs valeurs par défaut ou insérer un service par [câblage automatique |autowiring], utilisez un trait de soulignement : ```neon services: - - BarsDependent( typed(Bar) ) + foo: Foo(_, %appDir%) ``` -Vous pouvez également passer un tableau de services automatiquement en utilisant le [câblage automatique |autowiring#Collection of Services]. - -Un tableau de tous les services avec une certaine [étiquette |#tags] est créé par la fonction `tagged()`. Plusieurs balises séparées par une virgule peuvent être spécifiées. - -```neon -services: - - LoggersDependent( tagged(logger) ) -``` - - -Services de référencement .[#toc-referencing-services] -====================================================== - -Les services individuels sont référencés à l'aide du caractère `@` and name, so for example `@database`: - -```neon -services: - - create: Foo(@database) - setup: - - setCacheStorage(@cache.storage) -``` - -Correspond au code PHP : - -```php -public function createService01(): Foo -{ - $service = new Foo($this->getService('database')); - $service->setCacheStorage($this->getService('cache.storage')); - return $service; -} -``` - -Même les services anonymes peuvent être référencés à l'aide d'un callback, il suffit de spécifier leur type (classe ou interface) au lieu de leur nom. Cependant, cela n'est généralement pas nécessaire en raison du [câblage automatique |autowiring]. - -```neon -services: - - create: Foo(@Nette\Database\Connection) - setup: - - setCacheStorage(@cache.storage) -``` +Les arguments peuvent être des services, des paramètres et bien d'autres choses encore, voir les [moyens d'expression |#expression means]. Configuration .[#toc-setup] =========================== -Dans la section "setup", nous listons les méthodes à appeler lors de la création du service : +Dans la section `setup`, nous définissons les méthodes qui doivent être appelées lors de la création du service. ```neon services: @@ -274,7 +152,7 @@ services: - setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) ``` -Correspond au code PHP : +En PHP, cela ressemblerait à ```php public function createServiceDatabase(): PDO @@ -285,8 +163,7 @@ public function createServiceDatabase(): PDO } ``` -Les propriétés peuvent également être définies. L'ajout d'un élément à un tableau est également supporté, et doit être écrit entre guillemets pour ne pas entrer en conflit avec la syntaxe NEON : - +En plus des appels de méthodes, vous pouvez également passer des valeurs aux propriétés. L'ajout d'un élément à un tableau est également possible, mais vous devez le mettre entre guillemets pour éviter toute collision avec la syntaxe NEON : ```neon services: @@ -297,7 +174,7 @@ services: - '$onClick[]' = [@bar, clickHandler] ``` -Correspond au code PHP : +En PHP, cela se traduirait par : ```php public function createServiceFoo(): Foo @@ -309,8 +186,7 @@ public function createServiceFoo(): Foo } ``` -Cependant, les méthodes statiques ou les méthodes d'autres services peuvent également être appelées dans la configuration. Nous leur passons le service réel en tant que `@self`: - +Dans la configuration, vous pouvez également appeler des méthodes statiques ou des méthodes d'autres services. Si vous devez passer le service courant comme argument, utilisez `@self`: ```neon services: @@ -321,7 +197,7 @@ services: - @anotherService::setFoo(@self) ``` -Correspond au code PHP : +Notez que pour plus de simplicité, au lieu de `->`, nous utilisons `::`, voir [les moyens d'expression |#expression means]. Cela génère la méthode d'usine suivante : ```php public function createServiceFoo(): Foo @@ -334,23 +210,133 @@ public function createServiceFoo(): Foo ``` -Câblage automatique .[#toc-autowiring] -====================================== +Moyens d'expression .[#toc-expression-means] +============================================ + +Nette DI nous offre des capacités d'expression exceptionnellement riches, nous permettant d'articuler presque n'importe quoi. Dans les fichiers de configuration, nous pouvons utiliser des [paramètres |configuration#parameters]: + +```neon +# paramètre +%wwwDir% + +# valeur sous une clé de paramètre +%mailer.user% + +# paramètre dans une chaîne de caractères +'%wwwDir%/images' +``` + +Nous pouvons également créer des objets, appeler des méthodes et des fonctions : + +```neon +# créer un objet +DateTime() + +# appeler une méthode statique +Collator::create(%locale%) + +# appeler une fonction PHP +::getenv(DB_USER) +``` + +Faire référence aux services soit par leur nom, soit par leur type : + +```neon +# service par nom +@database + +# service par type +@Nette\Database\Connection +``` + +Utiliser des constantes : + +```neon +# constante de classe +FilesystemIterator::SKIP_DOTS + +# constante globale obtenue par la fonction PHP constant() +::constant(PHP_VERSION) +``` + +Les appels de méthodes peuvent être enchaînés, comme en PHP. Pour simplifier, au lieu de `->`, nous utilisons `::`: + +```neon +DateTime()::format('Y-m-d') +# PHP: (new DateTime())->format('Y-m-d') + +@http.request::getUrl()::getHost() +# PHP: $this->getService('http.request')->getUrl()->getHost() +``` + +Ces expressions peuvent être utilisées n'importe où lors de la [création de services |#Service Creation], dans les [arguments |#Arguments], dans la section de [configuration |#setup] ou dans les [paramètres |configuration#parameters]: + +```neon +parameters: + ipAddress: @http.request::getRemoteAddress() + +services: + database: + create: DatabaseFactory::create( @anotherService::getDsn() ) + setup: + - initialize( ::getenv('DB_USER') ) +``` + + +Fonctions spéciales .[#toc-special-functions] +--------------------------------------------- + +Dans les fichiers de configuration, vous pouvez utiliser ces fonctions spéciales : -La clé autowired peut être utilisée pour exclure un service de l'autowiring ou pour influencer son comportement. Voir le [chapitre sur le câblage automatique |autowiring] pour plus d'informations. +- `not()` pour la négation des valeurs +- `bool()`, `int()`, `float()`, `string()` pour le moulage de type sans perte +- `typed()` pour générer un tableau de tous les services d'un type spécifié +- `tagged()` pour créer un tableau de tous les services avec une étiquette donnée + +```neon +services: + - Foo( + id: int(::getenv('ProjectId')) + productionMode: not(%debugMode%) + ) +``` + +Par rapport au typage conventionnel en PHP, comme `(int)`, le typage sans perte lèvera une exception pour les valeurs non numériques. + +La fonction `typed()` crée un tableau de tous les services d'un type particulier (classe ou interface). Elle exclut les services dont le câblage automatique est désactivé. Plusieurs types peuvent être spécifiés, séparés par des virgules. + +```neon +services: + - BarsDependent( typed(Bar) ) +``` + +Vous pouvez également passer automatiquement un tableau de services d'un type spécifique comme argument en utilisant le [câblage automatique |autowiring#Collection of Services]. + +La fonction `tagged()` crée un tableau de tous les services ayant une balise spécifiée. Plusieurs balises peuvent être listées, séparées par des virgules. + +```neon +services: + - LoggersDependent( tagged(logger) ) +``` + + +Câblage automobile .[#toc-autowiring] +===================================== + +La clé `autowired` permet de modifier le comportement de l'autocâblage pour un service particulier. Pour plus de détails, voir [le chapitre sur |autowiring] l'autocâblage. ```neon services: foo: create: Foo - autowired: false # foo est retiré de l'autowiring + autowired: false # le service foo est exclu de l'autocâblage ``` Tags .[#toc-tags] ================= -Des informations sur les utilisateurs peuvent être ajoutées aux services individuels sous la forme de balises : +Les balises sont utilisées pour ajouter des informations supplémentaires aux services. Vous pouvez attribuer une ou plusieurs balises à un service : ```neon services: @@ -360,7 +346,7 @@ services: - cached ``` -Les étiquettes peuvent également avoir une valeur : +Les balises peuvent également comporter des valeurs : ```neon services: @@ -370,26 +356,26 @@ services: logger: monolog.logger.event ``` -Un tableau de services avec certaines balises peut être passé comme argument en utilisant la fonction `tagged()`. Plusieurs balises séparées par une virgule peuvent également être spécifiées. +Pour retrouver tous les services ayant des étiquettes spécifiques, vous pouvez utiliser la fonction `tagged()`: ```neon services: - LoggersDependent( tagged(logger) ) ``` -Les noms des services peuvent être obtenus du conteneur DI à l'aide de la méthode `findByTag()`: +Dans le conteneur DI, vous pouvez obtenir les noms de tous les services avec une étiquette spécifique en utilisant la méthode `findByTag()`: ```php $names = $container->findByTag('logger'); // $names est un tableau contenant le nom du service et la valeur du tag -// c'est-à-dire ['foo' => 'monolog.logger.event', ...] +// par exemple ['foo' => 'monolog.logger.event', ...] ``` Mode d'injection .[#toc-inject-mode] ==================================== -L'indicateur `inject: true` est utilisé pour activer le passage des dépendances via des variables publiques avec l'annotation [inject |best-practices:inject-method-attribute#Inject Attributes] et les méthodes [inject*() |best-practices:inject-method-attribute#inject Methods]. +L'utilisation du drapeau `inject: true` active le passage de dépendances via des variables publiques avec l'annotation [inject |best-practices:inject-method-attribute#Inject Attributes] et les méthodes [inject*() |best-practices:inject-method-attribute#inject Methods]. ```neon services: @@ -401,10 +387,10 @@ services: Par défaut, `inject` n'est activé que pour les présentateurs. -Modification des services .[#toc-modification-of-services] -========================================================== +Modifications du service .[#toc-service-modifications] +====================================================== -Il existe un certain nombre de services dans le conteneur DI qui ont été ajoutés par l'intégration ou [votre extension |#di-extensions]. Les définitions de ces services peuvent être modifiées dans la configuration. Par exemple, pour le service `application.application`, qui est par défaut un objet `Nette\Application\Application`, nous pouvons changer la classe : +Le conteneur DI contient de nombreux services ajoutés soit par des [extensions |#extensions] intégrées, soit par des [extensions utilisateur |#extensions]. Vous pouvez modifier les définitions de ces services directement dans la configuration. Par exemple, vous pouvez changer la classe du service `application.application`, qui est conventionnellement `Nette\Application\Application`, en quelque chose d'autre : ```neon services: @@ -413,9 +399,9 @@ services: alteration: true ``` -Le drapeau `alteration` est informatif et indique que nous ne faisons que modifier un service existant. +Le drapeau `alteration` est informatif, indiquant que nous modifions simplement un service existant. -Nous pouvons également ajouter un service : +Nous pouvons également compléter la configuration : ```neon services: @@ -426,7 +412,7 @@ services: - '$onStartup[]' = [@resource, init] ``` -Lorsque nous réécrivons un service, nous pouvons vouloir supprimer les arguments, les éléments de configuration ou les balises d'origine, ce à quoi sert `reset`: +Lors de l'écrasement d'un service, il se peut que vous souhaitiez supprimer les arguments, les éléments de configuration ou les balises d'origine, et c'est là que `reset` s'avère utile : ```neon services: @@ -439,7 +425,7 @@ services: - tags ``` -Un service ajouté par extension peut également être retiré du conteneur : +Si vous souhaitez supprimer un service ajouté par une extension, vous pouvez procéder comme suit : ```neon services: diff --git a/dependency-injection/hu/services.texy b/dependency-injection/hu/services.texy index db1874d9fd..3b933b1ab5 100644 --- a/dependency-injection/hu/services.texy +++ b/dependency-injection/hu/services.texy @@ -2,32 +2,32 @@ Szolgáltatás meghatározások *************************** .[perex] -A konfigurációban helyezzük el az egyéni szolgáltatások definícióit. Ez a `services` szakaszban történik. +A konfiguráció az a hely, ahol utasítjuk a DI konténert, hogyan állítsa össze az egyes szolgáltatásokat, és hogyan kapcsolja össze őket más függőségekkel. A Nette egy nagyon világos és elegáns módot biztosít erre. -Például így hozunk létre egy `database` nevű szolgáltatást, amely a `PDO` osztály példánya lesz: +A NEON konfigurációs fájl `services` szakasza az a hely, ahol definiáljuk az egyéni szolgáltatásainkat és azok konfigurációit. Nézzünk egy egyszerű példát a `database` nevű szolgáltatás definiálására, amely a `PDO` osztály egy példányát képviseli: ```neon services: database: PDO('sqlite::memory:') ``` -A szolgáltatások elnevezése arra szolgál, hogy [hivatkozni |#Referencing Services] tudjunk rájuk. Ha egy szolgáltatásra nem hivatkozunk, akkor nincs szükség nevet adni neki. Ezért a név helyett csak egy felsoroláspontot használunk: +Ez a konfiguráció a következő gyári metódust eredményezi a [DI konténerben |container]: -```neon -services: - - PDO('sqlite::memory:') # anonim szolgáltatás +```php +public function createServiceDatabase(): PDO +{ + return new PDO('sqlite::memory:'); +} ``` -Az egysoros bejegyzés több sorra bontható, hogy további kulcsokat lehessen hozzáadni, például [setup |#setup]. A `create:` billentyű álneve a `factory:`. +A szolgáltatásnevek lehetővé teszik, hogy a konfigurációs fájl más részeiben hivatkozzunk rájuk a `@serviceName` formátumban. Ha nincs szükség a szolgáltatás elnevezésére, akkor egyszerűen használhatunk egy felsorolásjelet: ```neon services: - database: - create: PDO('sqlite::memory:') - setup: ... + - PDO('sqlite::memory:') ``` -Ezután a szolgáltatást a DI konténerből a `getService()` metódus segítségével hívjuk le név szerint, vagy még jobb esetben a `getByType()` metódus segítségével típus szerint: +Egy szolgáltatás lekérdezéséhez a DI konténerből a `getService()` metódust használhatjuk a szolgáltatás nevével paraméterként, vagy a `getByType()` metódust a szolgáltatás típusával: ```php $database = $container->getService('database'); @@ -35,236 +35,114 @@ $database = $container->getByType(PDO::class); ``` -Szolgáltatás létrehozása .[#toc-creating-a-service] -=================================================== +Szolgáltatás létrehozása .[#toc-service-creation] +================================================= -Leggyakrabban úgy hozunk létre egy szolgáltatást, hogy egyszerűen létrehozzuk egy osztály példányát: +Leggyakrabban egy szolgáltatást egyszerűen egy adott osztály példányosításával hozunk létre. Például: ```neon services: database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` -Ami egy gyári metódust generál a [DI konténerben |container]: - -```php -public function createServiceDatabase(): PDO -{ - return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret'); -} -``` - -Alternatívaként egy kulcsot `arguments` lehet használni [az argumentumok |#Arguments] átadására: +Ha a konfigurációt további kulcsokkal kell bővítenünk, a definíciót több sorban is kibővíthetjük: ```neon services: database: - create: PDO - arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] -``` - -Egy statikus módszer is létrehozhat egy szolgáltatást: - -```neon -services: - database: My\Database::create(root, secret) + create: PDO('sqlite::memory:') + setup: ... ``` -Megfelel a PHP-kódnak: +A `create` kulcsnak van egy aliasa: `factory`, mindkét változat gyakori a gyakorlatban. Javasoljuk azonban a `create` használatát. -```php -public function createServiceDatabase(): PDO -{ - return My\Database::create('root', 'secret'); -} -``` - -Egy statikus metódus `My\Database::create()` feltételezhetően rendelkezik egy meghatározott visszatérési értékkel, amelyet a DI konténernek ismernie kell. Ha nem rendelkezik vele, akkor a típusát a konfigurációba írjuk: +A konstruktor argumentumai vagy a létrehozási módszer alternatívaként a `arguments` kulcsban is leírhatók: ```neon services: database: - create: My\Database::create(root, secret) - type: PDO + create: PDO + arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] ``` -A Nette DI rendkívül hatékony kifejezési lehetőségeket biztosít, amelyekkel szinte bármit leírhatunk. Például egy másik szolgáltatásra való [hivatkozás |#Referencing Services] és annak metódusának meghívása. Az egyszerűség kedvéért a `->` helyett a `::` -t használjuk. +A szolgáltatásokat nem csak egy osztály egyszerű példányosításával kell létrehozni; létrejöhetnek statikus metódusok vagy más szolgáltatások metódusainak hívásából is: ```neon services: - routerFactory: App\Router\Factory + database: DatabaseFactory::create() router: @routerFactory::create() ``` -Megfelel a PHP-kódnak: +Megjegyezzük, hogy az egyszerűség kedvéért a `->` helyett a `::` használjuk, lásd a [kifejezés eszközeit |#expression means]. Ezeket a gyári metódusokat generáljuk: ```php -public function createServiceRouterFactory(): App\Router\Factory +public function createServiceDatabase(): PDO { - return new App\Router\Factory; + return DatabaseFactory::create(); } -public function createServiceRouter(): Router +public function createServiceRouter(): RouteList { return $this->getService('routerFactory')->create(); } ``` -A metódushívások a PHP-hez hasonlóan láncolhatók egymáshoz: +A DI konténernek tudnia kell a létrehozott szolgáltatás típusát. Ha olyan metódussal hozunk létre egy szolgáltatást, amelynek nincs megadott visszatérési típusa, akkor ezt a típust kifejezetten meg kell említenünk a konfigurációban: ```neon services: - foo: FooFactory::build()::get() -``` - -Megfelel a PHP kódnak: - -```php -public function createServiceFoo() -{ - return FooFactory::build()->get(); -} + database: + create: DatabaseFactory::create() + type: PDO ``` -Érvek: .[#toc-arguments] -======================== - -A megnevezett paraméterek argumentumok átadására is használhatók: - -```neon -services: - database: PDO( - 'mysql:host=127.0.0.1;dbname=test' # pozicionális - username: root # named - password: secret # named - ) -``` - -A vesszők használata opcionális, ha az argumentumokat több sorra bontjuk. +Érvek .[#toc-arguments] +======================= -Természetesen [más szolgáltatásokat |#Referencing Services] vagy [paramétereket |configuration#parameters] is használhatunk argumentumként: +A konstruktoroknak és metódusoknak a hagyományos PHP-hoz nagyon hasonló módon adunk át argumentumokat: ```neon services: - - Foo(@anotherService, %appDir%) -``` - -Megfelel a PHP-kódnak: - -```php -public function createService01(): Foo -{ - return new Foo($this->getService('anotherService'), '...'); -} + database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` -`_` character, for example `Foo(_, %appDir%)`Vagy még jobb, ha csak a második argumentumot adjuk át megnevezett paraméterként, pl. `Foo(path: %appDir%)`. - -A Nette DI és a NEON formátum rendkívül erőteljes kifejezési lehetőségeket biztosít szinte bármi megírásához. Így egy argumentum lehet egy újonnan létrehozott objektum, hívhat statikus metódusokat, más szolgáltatások metódusait, vagy akár globális függvényeket is, speciális jelölés használatával: +A jobb olvashatóság érdekében az argumentumokat külön sorokban is felsorolhatjuk. Ebben a formátumban a vesszők használata opcionális: ```neon services: - analyser: My\Analyser( - FilesystemIterator(%appDir%) # create object - DateTime::createFromFormat('Y-m-d') # statikus metódus hívása - @anotherService # egy másik szolgáltatás átadása - @http.request::getRemoteAddress() # egy másik szolgáltatás metódusának hívása - ::getenv(NetteMode) # globális függvény hívása + database: PDO( + 'mysql:host=127.0.0.1;dbname=test' + root + secret ) ``` -Megfelel a PHP kódnak: - -```php -public function createServiceAnalyser(): My\Analyser -{ - return new My\Analyser( - new FilesystemIterator('...'), - DateTime::createFromFormat('Y-m-d'), - $this->getService('anotherService'), - $this->getService('http.request')->getRemoteAddress(), - getenv('NetteMode') - ); -} -``` - - -Speciális funkciók .[#toc-special-functions] --------------------------------------------- - -Speciális függvényeket is használhat az argumentumokban értékek kiértékelésére vagy negálására: - -- `not(%arg%)` negáció -- `bool(%arg%)` lossless cast to bool -- `int(%arg%)` veszteségmentes átváltás int-re -- `float(%arg%)` lossless cast to float -- `string(%arg%)` lossless cast to string +Az argumentumokat el is nevezhetjük, így nem kell aggódnunk a sorrendjük miatt: ```neon services: - - Foo( - id: int(::getenv('ProjectId')) - productionMode: not(%debugMode%) + database: PDO( + username: root + password: secret + dsn: 'mysql:host=127.0.0.1;dbname=test' ) ``` -A veszteségmentes átírás abban különbözik a normál PHP átírástól, pl. a `(int)` használatával, hogy a nem numerikus értékek esetén kivételt dob. - -Több szolgáltatás is átadható argumentumként. Egy adott típusú (azaz osztály vagy interfész) összes szolgáltatásának tömbjét a `typed()` függvény hozza létre. A függvény kihagyja azokat a szolgáltatásokat, amelyeknél az automatikus kapcsolás ki van kapcsolva, és több típus is megadható vesszővel elválasztva. - -```neon -services: - - BarsDependent( typed(Bar) ) -``` - -A szolgáltatások tömbjét automatikusan is átadhatja az [automatikus bekötés |autowiring#Collection of Services] segítségével. - -A `tagged()` függvény létrehozza az összes, egy adott [címkével |#tags] rendelkező szolgáltatás tömbjét. Több, vesszővel elválasztott címke is megadható. - -```neon -services: - - LoggersDependent( tagged(logger) ) -``` - - -Szolgáltatásokra való hivatkozás .[#toc-referencing-services] -============================================================= - -Az egyes szolgáltatásokra a `@` and name, so for example `@database` karakterek segítségével lehet hivatkozni: +Ha bizonyos argumentumokat el akar hagyni, és azok alapértelmezett értékét kívánja használni, vagy egy szolgáltatást [automatikus bekötéssel |autowiring] szeretne beilleszteni, használjon aláhúzást: ```neon services: - - create: Foo(@database) - setup: - - setCacheStorage(@cache.storage) + foo: Foo(_, %appDir%) ``` -Megfelel a PHP kódnak: - -```php -public function createService01(): Foo -{ - $service = new Foo($this->getService('database')); - $service->setCacheStorage($this->getService('cache.storage')); - return $service; -} -``` - -A névtelen szolgáltatásokra is lehet hivatkozni visszahívással, csak a típusukat (osztály vagy interfész) kell megadni a nevük helyett. Erre azonban az [autowiring |autowiring] miatt általában nincs szükség. - -```neon -services: - - create: Foo(@Nette\Database\Connection) - setup: - - setCacheStorage(@cache.storage) -``` +Az argumentumok lehetnek szolgáltatások, paraméterek és még sok más, lásd a [kifejezés eszközeit |#expression means]. Beállítás .[#toc-setup] ======================= -A setup szakaszban felsoroljuk a szolgáltatás létrehozásakor meghívandó metódusokat: +A `setup` szakaszban definiáljuk azokat a metódusokat, amelyeket a szolgáltatás létrehozásakor meg kell hívni. ```neon services: @@ -274,7 +152,7 @@ services: - setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) ``` -Megfelel a PHP-kódnak: +PHP nyelven ez így nézne ki: ```php public function createServiceDatabase(): PDO @@ -285,8 +163,7 @@ public function createServiceDatabase(): PDO } ``` -Properites is beállítható. Egy elem hozzáadása egy tömbhöz szintén támogatott, és idézőjelek közé kell írni, hogy ne ütközzön a NEON szintaxissal: - +A metódushívások mellett értékeket is átadhat a tulajdonságoknak. Egy elem hozzáadása egy tömbhöz szintén támogatott, de azt idézőjelek közé kell zárni, hogy ne ütközzön a NEON szintaxissal: ```neon services: @@ -297,7 +174,7 @@ services: - '$onClick[]' = [@bar, clickHandler] ``` -Megfelel a PHP-kódnak: +PHP-ben ez a következőképpen hangzana: ```php public function createServiceFoo(): Foo @@ -309,8 +186,7 @@ public function createServiceFoo(): Foo } ``` -A beállításban azonban statikus metódusok vagy más szolgáltatások metódusai is meghívhatók. Az aktuális szolgáltatást a `@self` címen adjuk át nekik: - +A beállításban statikus módszereket vagy más szolgáltatások metódusait is meghívhatja. Ha az aktuális szolgáltatást kell átadni argumentumként, használja a `@self` címet: ```neon services: @@ -321,7 +197,7 @@ services: - @anotherService::setFoo(@self) ``` -Megfelel a PHP kódnak: +Vegye figyelembe, hogy az egyszerűség kedvéért a `->` helyett a `::`, lásd a [kifejezés eszközeit |#expression means]. Ez a következő gyári metódust generálja: ```php public function createServiceFoo(): Foo @@ -334,23 +210,133 @@ public function createServiceFoo(): Foo ``` +Kifejezés Eszközök .[#toc-expression-means] +=========================================== + +A Nette DI kivételesen gazdag kifejezési lehetőségeket biztosít számunkra, lehetővé téve számunkra, hogy szinte bármit megfogalmazzunk. A konfigurációs fájlokban használhatunk [paramétereket |configuration#parameters]: + +```neon +# paraméter +%wwwDir% + +# érték egy paraméterkulcs alatt +%mailer.user% + +# paraméter egy karakterláncon belül +'%wwwDir%/images' +``` + +Objektumokat is létrehozhatunk, metódusokat és függvényeket hívhatunk: + +```neon +# hozzon létre egy objektumot +DateTime() + +# statikus metódus hívása +Collator::create(%locale%) + +# PHP függvény hívása +::getenv(DB_USER) +``` + +A szolgáltatásokra a nevük vagy a típusuk alapján hivatkozhatunk: + +```neon +# szolgáltatás név szerint +@database + +# szolgáltatás típusa szerint +@Nette\Database\Connection +``` + +Konstanciák használata: + +```neon +# osztálykonstans +FilesystemIterator::SKIP_DOTS + +# globális konstans, amelyet a PHP konstans() függvényével kapunk. +::constant(PHP_VERSION) +``` + +A metódushívások láncolhatók, akárcsak a PHP-ban. Az egyszerűség kedvéért a `->` helyett a `::` címet használjuk: + +```neon +DateTime()::format('Y-m-d') +# PHP: (new DateTime())->format('Y-m-d') + +@http.request::getUrl()::getHost() +# PHP: http.request')->getUrl()->getHost() +``` + +Ezek a kifejezések bárhol használhatók a [szolgáltatások létrehozásakor |#Service Creation], az [argumentumokban |#Arguments], a [beállítási |#setup] szakaszban vagy a [paraméterekben |configuration#parameters]: + +```neon +parameters: + ipAddress: @http.request::getRemoteAddress() + +services: + database: + create: DatabaseFactory::create( @anotherService::getDsn() ) + setup: + - initialize( ::getenv('DB_USER') ) +``` + + +Különleges funkciók .[#toc-special-functions] +--------------------------------------------- + +A konfigurációs fájlokon belül használhatja ezeket a speciális funkciókat: + +- `not()` az érték negációjához +- `bool()`, `int()`, `float()`, `string()` a veszteségmentes típusváltáshoz. +- `typed()` a megadott típusú szolgáltatások tömbjének létrehozásához. +- `tagged()` egy adott címkével rendelkező összes szolgáltatás tömbjének létrehozásához. + +```neon +services: + - Foo( + id: int(::getenv('ProjectId')) + productionMode: not(%debugMode%) + ) +``` + +A PHP hagyományos típuskiosztásához képest, mint például a `(int)`, a veszteségmentes típuskiosztás kivételt dob a nem numerikus értékek esetén. + +A `typed()` függvény egy adott típusú (osztály vagy interfész) összes szolgáltatásának tömbjét hozza létre. Kizárja azokat a szolgáltatásokat, amelyeknél az automatikus kapcsolás ki van kapcsolva. Több típus is megadható, vesszővel elválasztva. + +```neon +services: + - BarsDependent( typed(Bar) ) +``` + +Az [autowiring |autowiring#Collection of Services] használatával egy adott típusú szolgáltatások tömbjét is automatikusan átadhatja argumentumként. + +A `tagged()` függvény létrehozza a megadott címkével rendelkező összes szolgáltatás tömbjét. Több címke is felsorolható, vesszővel elválasztva. + +```neon +services: + - LoggersDependent( tagged(logger) ) +``` + + Autowiring .[#toc-autowiring] ============================= -Az autowired kulccsal kizárható egy szolgáltatás az autowiringből, vagy befolyásolható a viselkedése. További információért lásd [az autowiring fejezetet |autowiring]. +A `autowired` billentyűvel módosíthatja egy adott szolgáltatás autowiring viselkedését. További részletekért lásd [az autowiring fejezetet |autowiring]. ```neon services: foo: create: Foo - autowired: false # foo-t eltávolítjuk az autowiringből + autowired: false # a foo szolgáltatás ki van zárva az automatikus bekötésből ``` Címkék .[#toc-tags] =================== -A felhasználói információk címkék formájában adhatók hozzá az egyes szolgáltatásokhoz: +A címkék a szolgáltatások kiegészítő információkkal való kiegészítésére szolgálnak. Egy vagy több címkét rendelhet egy szolgáltatáshoz: ```neon services: @@ -360,7 +346,7 @@ services: - cached ``` -A címkéknek lehet értékük is: +A címkék értékeket is hordozhatnak: ```neon services: @@ -370,14 +356,14 @@ services: logger: monolog.logger.event ``` -A `tagged()` függvény segítségével bizonyos címkékkel rendelkező szolgáltatások tömbje adható át argumentumként. Több, vesszővel elválasztott címke is megadható. +A `tagged()` funkcióval lekérdezheti az adott címkékkel rendelkező összes szolgáltatást: ```neon services: - LoggersDependent( tagged(logger) ) ``` -A szolgáltatások nevei a DI konténerből a `findByTag()` módszerrel szerezhetők be: +A DI konténerben a `findByTag()` metódus segítségével megkaphatja az összes, egy adott címkével rendelkező szolgáltatás nevét: ```php $names = $container->findByTag('logger'); @@ -386,10 +372,10 @@ $names = $container->findByTag('logger'); ``` -Inject Mode .[#toc-inject-mode] -=============================== +Injektálás mód .[#toc-inject-mode] +================================== -A `inject: true` flag a függőségek nyilvános változókon keresztüli átadásának aktiválására szolgál az [inject |best-practices:inject-method-attribute#Inject Attributes] annotációval és az [inject*() |best-practices:inject-method-attribute#inject Methods] metódusokkal. +A `inject: true` jelző használata aktiválja a függőségek átadását nyilvános változókon keresztül az [inject |best-practices:inject-method-attribute#Inject Attributes] megjegyzésekkel és az [inject*() |best-practices:inject-method-attribute#inject Methods] metódusokkal. ```neon services: @@ -401,10 +387,10 @@ services: Alapértelmezés szerint a `inject` csak az előadók esetében van aktiválva. -A szolgáltatások módosítása .[#toc-modification-of-services] -============================================================ +Szolgáltatás módosítások .[#toc-service-modifications] +====================================================== -A DI konténerben számos olyan szolgáltatás van, amelyet beépített vagy [a bővítménye |#di-extensions] adott hozzá. Ezeknek a szolgáltatásoknak a definíciói a konfigurációban módosíthatók. Például a `application.application` szolgáltatás esetében, amely alapértelmezés szerint egy `Nette\Application\Application` objektum, megváltoztathatjuk az osztályt: +A DI konténer számos beépített vagy [felhasználói bővítéssel |#extensions] hozzáadott szolgáltatást tartalmaz. Ezeknek a szolgáltatásoknak a definícióit közvetlenül a konfigurációban módosíthatja. Például megváltoztathatja a `application.application` szolgáltatás osztályát, amely a hagyományos `Nette\Application\Application`, másra: ```neon services: @@ -413,9 +399,9 @@ services: alteration: true ``` -A `alteration` jelző tájékoztató jellegű, és azt mondja, hogy csak egy meglévő szolgáltatást módosítunk. +A `alteration` jelző tájékoztató jellegű, jelzi, hogy csupán egy meglévő szolgáltatást módosítunk. -Hozzáadhatunk egy beállítást is: +Kiegészíthetjük a beállítást is: ```neon services: @@ -426,7 +412,7 @@ services: - '$onStartup[]' = [@resource, init] ``` -Erre való a `reset`: +Itt jön jól a `reset`: ```neon services: @@ -439,7 +425,7 @@ services: - tags ``` -A kiterjesztéssel hozzáadott szolgáltatás is eltávolítható a konténerből: +Ha egy bővítmény által hozzáadott szolgáltatást szeretne eltávolítani, akkor ezt a következőképpen teheti meg: ```neon services: diff --git a/dependency-injection/it/services.texy b/dependency-injection/it/services.texy index 4f16ef0548..bf2d53ce0a 100644 --- a/dependency-injection/it/services.texy +++ b/dependency-injection/it/services.texy @@ -2,32 +2,32 @@ Definizioni del servizio ************************ .[perex] -La configurazione è il punto in cui si inseriscono le definizioni dei servizi personalizzati. Questo viene fatto nella sezione `services`. +La configurazione è il luogo in cui si istruisce il contenitore DI su come assemblare i singoli servizi e come collegarli con altre dipendenze. Nette fornisce un modo molto chiaro ed elegante per raggiungere questo obiettivo. -Per esempio, ecco come si crea un servizio chiamato `database`, che sarà un'istanza della classe `PDO`: +La sezione `services` del file di configurazione di NEON è il luogo in cui si definiscono i servizi personalizzati e le loro configurazioni. Vediamo un semplice esempio di definizione di un servizio chiamato `database`, che rappresenta un'istanza della classe `PDO`: ```neon services: database: PDO('sqlite::memory:') ``` -La denominazione dei servizi serve a consentirci di fare [riferimento a |#Referencing Services] essi. Se un servizio non è referenziato, non c'è bisogno di dargli un nome. Per questo motivo, al posto del nome si usa un punto elenco: +Questa configurazione dà luogo al seguente metodo factory nel [contenitore DI |container]: -```neon -services: - - PDO('sqlite::memory:') # servizio anonimo +```php +public function createServiceDatabase(): PDO +{ + return new PDO('sqlite::memory:'); +} ``` -Una voce di una riga può essere suddivisa in più righe per consentire l'aggiunta di altre chiavi, come [setup |#setup]. L'alias della chiave `create:` è `factory:`. +I nomi dei servizi consentono di fare riferimento ad essi in altre parti del file di configurazione, utilizzando il formato `@serviceName`. Se non è necessario dare un nome al servizio, si può usare semplicemente un punto: ```neon services: - database: - create: PDO('sqlite::memory:') - setup: ... + - PDO('sqlite::memory:') ``` -Si recupera quindi il servizio dal contenitore DI usando il metodo `getService()` per nome o, meglio ancora, il metodo `getByType()` per tipo: +Per recuperare un servizio dal contenitore DI, si può usare il metodo `getService()` con il nome del servizio come parametro, oppure il metodo `getByType()` con il tipo di servizio: ```php $database = $container->getService('database'); @@ -35,236 +35,114 @@ $database = $container->getByType(PDO::class); ``` -Creare un servizio .[#toc-creating-a-service] +Creazione di servizi .[#toc-service-creation] ============================================= -Il più delle volte, per creare un servizio basta creare un'istanza di una classe: +Più comunemente, si crea un servizio semplicemente istanziando una classe specifica. Ad esempio: ```neon services: database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` -Il che genererà un metodo factory nel [contenitore DI |container]: - -```php -public function createServiceDatabase(): PDO -{ - return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret'); -} -``` - -In alternativa, si può usare una chiave `arguments` per passare gli [argomenti |#Arguments]: +Se abbiamo bisogno di espandere la configurazione con ulteriori chiavi, la definizione può essere espansa in più righe: ```neon services: database: - create: PDO - arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] -``` - -Un metodo statico può anche creare un servizio: - -```neon -services: - database: My\Database::create(root, secret) + create: PDO('sqlite::memory:') + setup: ... ``` -Corrisponde al codice PHP: +La chiave `create` ha un alias `factory`, entrambe le versioni sono comuni nella pratica. Tuttavia, si consiglia di utilizzare `create`. -```php -public function createServiceDatabase(): PDO -{ - return My\Database::create('root', 'secret'); -} -``` - -Si presume che un metodo statico `My\Database::create()` abbia un valore di ritorno definito che il contenitore DI deve conoscere. Se non ce l'ha, si scrive il tipo nella configurazione: +Gli argomenti del costruttore o il metodo di creazione possono essere scritti in alternativa nella chiave `arguments`: ```neon services: database: - create: My\Database::create(root, secret) - type: PDO + create: PDO + arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] ``` -Nette DI offre strumenti di espressione estremamente potenti per scrivere quasi tutto. Ad esempio, per fare [riferimento |#Referencing Services] a un altro servizio e chiamare il suo metodo. Per semplicità, si usa `::` invece di `->`. +I servizi non devono essere creati solo tramite la semplice istanziazione di una classe; possono anche derivare dalla chiamata di metodi statici o di altri servizi: ```neon services: - routerFactory: App\Router\Factory + database: DatabaseFactory::create() router: @routerFactory::create() ``` -Corrisponde al codice PHP: +Si noti che per semplicità, al posto di `->`, si usa `::`, vedi [espressione significa |#expression means]. Questi metodi di fabbrica sono generati: ```php -public function createServiceRouterFactory(): App\Router\Factory +public function createServiceDatabase(): PDO { - return new App\Router\Factory; + return DatabaseFactory::create(); } -public function createServiceRouter(): Router +public function createServiceRouter(): RouteList { return $this->getService('routerFactory')->create(); } ``` -Le chiamate ai metodi possono essere concatenate come in PHP: +Il contenitore DI deve conoscere il tipo del servizio creato. Se si crea un servizio usando un metodo che non ha un tipo di ritorno specificato, si deve menzionare esplicitamente questo tipo nella configurazione: ```neon services: - foo: FooFactory::build()::get() -``` - -Corrisponde al codice PHP: - -```php -public function createServiceFoo() -{ - return FooFactory::build()->get(); -} + database: + create: DatabaseFactory::create() + type: PDO ``` Argomenti .[#toc-arguments] =========================== -I parametri denominati possono essere usati anche per passare argomenti: +Passiamo gli argomenti ai costruttori e ai metodi in modo molto simile al normale PHP: ```neon services: - database: PDO( - 'mysql:host=127.0.0.1;dbname=test' # posizionale - username: root # nominato - password: secret # nominato - ) -``` - -L'uso delle virgole è facoltativo quando si suddividono gli argomenti in più righe. - -Naturalmente, è possibile utilizzare [altri servizi |#Referencing Services] o [parametri |configuration#parameters] come argomenti: - -```neon -services: - - Foo(@anotherService, %appDir%) -``` - -Corrisponde al codice PHP: - -```php -public function createService01(): Foo -{ - return new Foo($this->getService('anotherService'), '...'); -} + database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` -Se il primo argomento è [autocablato |autowiring] e si vuole specificare il secondo, omettere il primo con `_` character, for example `Foo(_, %appDir%)`. O meglio ancora, passare solo il secondo argomento come parametro con nome, ad esempio `Foo(path: %appDir%)`. - -Nette DI e il formato NEON offrono strumenti espressivi estremamente potenti per scrivere praticamente qualsiasi cosa. Un argomento può essere un oggetto appena creato, si possono chiamare metodi statici, metodi di altri servizi o persino funzioni globali, utilizzando una notazione speciale: +Per una migliore leggibilità, possiamo elencare gli argomenti su righe separate. In questo formato, l'uso delle virgole è facoltativo: ```neon services: - analyser: My\Analyser( - FilesystemIterator(%appDir%) # creare l'oggetto - DateTime::createFromFormat('Y-m-d') # chiama un metodo statico - @anotherService # passare un altro servizio - @http.request::getRemoteAddress() # chiamare un altro metodo del servizio - ::getenv(NetteMode) # chiama una funzione globale + database: PDO( + 'mysql:host=127.0.0.1;dbname=test' + root + secret ) ``` -Corrisponde al codice PHP: - -```php -public function createServiceAnalyser(): My\Analyser -{ - return new My\Analyser( - new FilesystemIterator('...'), - DateTime::createFromFormat('Y-m-d'), - $this->getService('anotherService'), - $this->getService('http.request')->getRemoteAddress(), - getenv('NetteMode') - ); -} -``` - - -Funzioni speciali .[#toc-special-functions] -------------------------------------------- - -È inoltre possibile utilizzare funzioni speciali negli argomenti per eseguire il cast o la negazione dei valori: - -- `not(%arg%)` negazione -- `bool(%arg%)` cast senza perdite a bool -- `int(%arg%)` cast senza perdite in int -- `float(%arg%)` cast senza perdite a float -- `string(%arg%)` cast senza perdite a stringa +È possibile anche dare un nome agli argomenti, in modo da non preoccuparsi del loro ordine: ```neon services: - - Foo( - id: int(::getenv('ProjectId')) - productionMode: not(%debugMode%) + database: PDO( + username: root + password: secret + dsn: 'mysql:host=127.0.0.1;dbname=test' ) ``` -La riscrittura lossless differisce dalla normale riscrittura PHP, ad esempio utilizzando `(int)`, in quanto lancia un'eccezione per i valori non numerici. - -È possibile passare più servizi come argomenti. Un array di tutti i servizi di un particolare tipo (cioè, classe o interfaccia) viene creato dalla funzione `typed()`. La funzione ometterà i servizi che hanno il cablaggio automatico disabilitato e si possono specificare più tipi separati da una virgola. - -```neon -services: - - BarsDependent( typed(Bar) ) -``` - -È anche possibile passare automaticamente un array di servizi utilizzando l'[autowiring |autowiring#Collection of Services]. - -Un array di tutti i servizi con un determinato [tag |#tags] viene creato dalla funzione `tagged()`. È possibile specificare più tag separati da una virgola. - -```neon -services: - - LoggersDependent( tagged(logger) ) -``` - - -Servizi di riferimento .[#toc-referencing-services] -=================================================== - -I singoli servizi sono referenziati utilizzando il carattere `@` and name, so for example `@database`: +Se si desidera omettere alcuni argomenti e utilizzare i loro valori predefiniti o inserire un servizio tramite [autocablaggio |autowiring], utilizzare un trattino basso: ```neon services: - - create: Foo(@database) - setup: - - setCacheStorage(@cache.storage) -``` - -Corrisponde al codice PHP: - -```php -public function createService01(): Foo -{ - $service = new Foo($this->getService('database')); - $service->setCacheStorage($this->getService('cache.storage')); - return $service; -} + foo: Foo(_, %appDir%) ``` -Anche i servizi anonimi possono essere referenziati usando un callback, basta specificare il loro tipo (classe o interfaccia) invece del loro nome. Tuttavia, di solito non è necessario, a causa del [cablaggio automatico |autowiring]. +Gli argomenti possono essere servizi, parametri e molto altro, vedere i [mezzi di espressione |#expression means]. -```neon -services: - - create: Foo(@Nette\Database\Connection) - setup: - - setCacheStorage(@cache.storage) -``` +Impostazione .[#toc-setup] +========================== -Configurazione .[#toc-setup] -============================ - -Nella sezione di configurazione vengono elencati i metodi da richiamare durante la creazione del servizio: +Nella sezione `setup`, si definiscono i metodi che devono essere richiamati durante la creazione del servizio. ```neon services: @@ -274,7 +152,7 @@ services: - setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) ``` -Corrisponde al codice PHP: +In PHP, questo sarebbe simile a: ```php public function createServiceDatabase(): PDO @@ -285,8 +163,7 @@ public function createServiceDatabase(): PDO } ``` -È possibile impostare anche le proprietà. È supportata anche l'aggiunta di un elemento a un array, che deve essere scritto tra virgolette per non entrare in conflitto con la sintassi NEON: - +Oltre alle chiamate di metodo, è possibile passare valori alle proprietà. È supportata anche l'aggiunta di un elemento a un array, ma è necessario racchiuderlo tra virgolette per evitare di scontrarsi con la sintassi NEON: ```neon services: @@ -297,7 +174,7 @@ services: - '$onClick[]' = [@bar, clickHandler] ``` -Corrisponde al codice PHP: +In PHP, questo si tradurrebbe in: ```php public function createServiceFoo(): Foo @@ -309,8 +186,7 @@ public function createServiceFoo(): Foo } ``` -Tuttavia, anche i metodi statici o i metodi di altri servizi possono essere chiamati nel setup. Si passa il servizio effettivo a loro come `@self`: - +Nella configurazione, si possono anche chiamare metodi statici o metodi di altri servizi. Se è necessario passare il servizio corrente come argomento, utilizzare `@self`: ```neon services: @@ -321,7 +197,7 @@ services: - @anotherService::setFoo(@self) ``` -Corrisponde al codice PHP: +Si noti che per semplicità, al posto di `->`, si usa `::`, vedi [espressione significa |#expression means]. Questo genera il seguente metodo di fabbrica: ```php public function createServiceFoo(): Foo @@ -334,23 +210,133 @@ public function createServiceFoo(): Foo ``` -Cablaggio automatico .[#toc-autowiring] -======================================= +Mezzi di espressione .[#toc-expression-means] +============================================= + +Nette DI ci fornisce capacità di espressione eccezionalmente ricche, che ci permettono di articolare quasi tutto. Nei file di configurazione, possiamo usare dei [parametri |configuration#parameters]: + +```neon +# parametro +%wwwDir% + +# valore sotto una chiave di parametro +%mailer.user% + +# parametro all'interno di una stringa +'%wwwDir%/images' +``` + +Possiamo anche creare oggetti, chiamare metodi e funzioni: + +```neon +# creare un oggetto +DateTime() + +# chiamare un metodo statico +Collator::create(%locale%) + +# chiamare una funzione PHP +::getenv(DB_USER) +``` + +Fare riferimento ai servizi con il loro nome o con il loro tipo: + +```neon +# servizio per nome +@database + +# servizio per tipo +@Nette\Database\Connection +``` + +Utilizzare le costanti: + +```neon +# costante di classe +FilesystemIterator::SKIP_DOTS + +# costante globale ottenuta con la funzione PHP constant() +::constant(PHP_VERSION) +``` + +Le chiamate ai metodi possono essere concatenate, proprio come in PHP. Per semplicità, invece di `->`, usiamo `::`: + +```neon +DateTime()::format('Y-m-d') +# PHP: (new DateTime())->format('Y-m-d') + +@http.request::getUrl()::getHost() +# PHP: $this->getService('http.request')->getUrl()->getHost() +``` + +Queste espressioni possono essere utilizzate ovunque durante la [creazione di servizi |#Service Creation], nei [parametri |#Arguments], nella sezione di [impostazione |#setup] o nei [parametri |configuration#parameters]: + +```neon +parameters: + ipAddress: @http.request::getRemoteAddress() + +services: + database: + create: DatabaseFactory::create( @anotherService::getDsn() ) + setup: + - initialize( ::getenv('DB_USER') ) +``` + + +Funzioni speciali .[#toc-special-functions] +------------------------------------------- + +All'interno dei file di configurazione è possibile utilizzare queste funzioni speciali: + +- `not()` per la negazione dei valori +- `bool()`, `int()`, `float()`, `string()` per la fusione dei tipi senza perdita di informazioni +- `typed()` per generare un array di tutti i servizi di un tipo specificato +- `tagged()` per creare un array di tutti i servizi con un determinato tag + +```neon +services: + - Foo( + id: int(::getenv('ProjectId')) + productionMode: not(%debugMode%) + ) +``` + +Rispetto al typecasting convenzionale in PHP, come `(int)`, il type casting lossless lancia un'eccezione per i valori non numerici. + +La funzione `typed()` crea un array di tutti i servizi di un particolare tipo (classe o interfaccia). Esclude i servizi con il cablaggio automatico disattivato. È possibile specificare più tipi, separati da virgole. + +```neon +services: + - BarsDependent( typed(Bar) ) +``` + +È anche possibile passare automaticamente un array di servizi di un tipo specifico come argomento utilizzando l'[autowiring |autowiring#Collection of Services]. + +La funzione `tagged()` crea un array di tutti i servizi con un tag specificato. È possibile elencare più tag, separati da virgole. + +```neon +services: + - LoggersDependent( tagged(logger) ) +``` + + +Cablaggio auto .[#toc-autowiring] +================================= -La chiave autowiring può essere usata per escludere un servizio dall'autowiring o per influenzarne il comportamento. Per ulteriori informazioni, vedere il [capitolo sull'autowiring |autowiring]. +Il tasto `autowired` consente di modificare il comportamento del cablaggio automatico per un particolare servizio. Per maggiori dettagli, vedere [il capitolo sul cablaggio automatico |autowiring]. ```neon services: foo: create: Foo - autowired: false # foo è rimosso dall'autowiring + autowired: false # il servizio pippo è escluso dal cablaggio automatico ``` Tag .[#toc-tags] ================ -Le informazioni sugli utenti possono essere aggiunte ai singoli servizi sotto forma di tag: +I tag sono utilizzati per aggiungere informazioni supplementari ai servizi. È possibile assegnare uno o più tag a un servizio: ```neon services: @@ -360,7 +346,7 @@ services: - cached ``` -I tag possono anche avere un valore: +I tag possono anche contenere dei valori: ```neon services: @@ -370,14 +356,14 @@ services: logger: monolog.logger.event ``` -Un array di servizi con determinati tag può essere passato come argomento utilizzando la funzione `tagged()`. Si possono anche specificare più tag separati da una virgola. +Per recuperare tutti i servizi con tag specifici, è possibile utilizzare la funzione `tagged()`: ```neon services: - LoggersDependent( tagged(logger) ) ``` -I nomi dei servizi possono essere ottenuti dal contenitore DI con il metodo `findByTag()`: +Nel contenitore DI, è possibile ottenere i nomi di tutti i servizi con un tag specifico utilizzando il metodo `findByTag()`: ```php $names = $container->findByTag('logger'); @@ -386,10 +372,10 @@ $names = $container->findByTag('logger'); ``` -Modalità Inject .[#toc-inject-mode] -=================================== +Modalità di iniezione .[#toc-inject-mode] +========================================= -Il flag `inject: true` è usato per attivare il passaggio di dipendenze tramite variabili pubbliche con l'annotazione [inject |best-practices:inject-method-attribute#Inject Attributes] e i metodi [inject*() |best-practices:inject-method-attribute#inject Methods]. +L'uso del flag `inject: true` attiva il passaggio delle dipendenze tramite variabili pubbliche con l'annotazione [inject |best-practices:inject-method-attribute#Inject Attributes] e i metodi [inject*() |best-practices:inject-method-attribute#inject Methods]. ```neon services: @@ -401,10 +387,10 @@ services: Per impostazione predefinita, `inject` è attivato solo per i presentatori. -Modifica dei servizi .[#toc-modification-of-services] -===================================================== +Modifiche del servizio .[#toc-service-modifications] +==================================================== -Nel contenitore DI sono presenti diversi servizi aggiunti da un'[estensione |#di-extensions] incorporata o dall'[utente |#di-extensions]. Le definizioni di questi servizi possono essere modificate nella configurazione. Ad esempio, per il servizio `application.application`, che per impostazione predefinita è un oggetto `Nette\Application\Application`, si può cambiare la classe: +Il contenitore DI contiene molti servizi aggiunti da [estensioni |#extensions] integrate o dall'[utente |#extensions]. È possibile modificare le definizioni di questi servizi direttamente nella configurazione. Per esempio, si può cambiare la classe del servizio `application.application`, che è convenzionalmente `Nette\Application\Application`, in un'altra: ```neon services: @@ -413,9 +399,9 @@ services: alteration: true ``` -Il flag `alteration` è informativo e indica che stiamo solo modificando un servizio esistente. +Il flag `alteration` è informativo e indica che stiamo semplicemente modificando un servizio esistente. -Possiamo anche aggiungere una configurazione: +Possiamo anche completare la configurazione: ```neon services: @@ -426,7 +412,7 @@ services: - '$onStartup[]' = [@resource, init] ``` -Quando si riscrive un servizio, si possono rimuovere gli argomenti originali, gli elementi di configurazione o i tag, a questo serve `reset`: +Quando si sovrascrive un servizio, si potrebbe voler rimuovere gli argomenti originali, gli elementi di configurazione o i tag, ed è qui che `reset` si rivela utile: ```neon services: @@ -439,7 +425,7 @@ services: - tags ``` -Un servizio aggiunto per estensione può anche essere rimosso dal contenitore: +Se si desidera rimuovere un servizio aggiunto da un'estensione, è possibile farlo in questo modo: ```neon services: diff --git a/dependency-injection/ja/services.texy b/dependency-injection/ja/services.texy index 5ea5de0182..83bc008621 100644 --- a/dependency-injection/ja/services.texy +++ b/dependency-injection/ja/services.texy @@ -2,32 +2,32 @@ ****** .[perex] -コンフィギュレーションは、カスタムサービスの定義を配置する場所です。これは、セクション`services` で行います。 +コンフィギュレーションは、DIコンテナに対して、個々のサービスの組み立て方や、他の依存関係との接続方法を指示する場所です。Netteは、これを実現するための非常に明確でエレガントな方法を提供します。 -例えば、これは`database` という名前のサービスを作成する方法で、これはクラス`PDO` のインスタンスになります。 +NEON設定ファイルの`services` セクションは、カスタムサービスとその設定を定義する場所です。`PDO` クラスのインスタンスを表す`database` というサービスを定義する簡単な例を見てみましょう: ```neon services: database: PDO('sqlite::memory:') ``` -サービスの名前付けは,サービスを[参照 |#Referencing Services]できるようにするために行います.もしサービスが参照されないのであれば、名前を付ける必要はありません。そこで、名前の代わりに箇条書きを使っているだけです。 +この設定により、[DIコンテナの |container]ファクトリーメソッドは次のようになります: -```neon -services: - - PDO('sqlite::memory:') # anonymous service +```php +public function createServiceDatabase(): PDO +{ + return new PDO('sqlite::memory:'); +} ``` -1行のエントリーを複数行に分割して、[setupなどの |#setup]キーを追加できるようにすることも可能です。`create:` キーのエイリアスは、`factory:` です。 +サービス名は、設定ファイルの他の部分で参照できるようにするためのもので、`@serviceName`.サービス名を付ける必要がない場合は、単に箇条書きを使用できます: ```neon services: - database: - create: PDO('sqlite::memory:') - setup: ... + - PDO('sqlite::memory:') ``` -次に、DIコンテナからサービスを取り出すには、名前を指定して`getService()` というメソッドを使うか、種類を指定して`getByType()` というメソッドを使うとよいでしょう。 +DIコンテナからサービスを取得するには、`getService()` メソッドにサービス名をパラメータとして指定するか、`getByType()` メソッドにサービスタイプを指定して指定します: ```php $database = $container->getService('database'); @@ -35,236 +35,114 @@ $database = $container->getByType(PDO::class); ``` -サービスの作成 .[#toc-creating-a-service] -================================== +サービスクリエーション .[#toc-service-creation] +==================================== -多くの場合、サービスの作成は単にクラスのインスタンスを作成することで行います。 +ほとんどの場合、特定のクラスをインスタンス化するだけでサービスを作成します。例えば ```neon services: database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` -この場合、[DIコンテナ |container]内にファクトリーメソッドが生成されます。 - -```php -public function createServiceDatabase(): PDO -{ - return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret'); -} -``` - -また、[引数の |#Arguments]受け渡しにキー`arguments` を使うこともできます。 +追加のキーで設定を拡張する必要がある場合、定義を複数行に拡張することができます: ```neon services: database: - create: PDO - arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] -``` - -静的メソッドは、サービスを作成することもできます。 - -```neon -services: - database: My\Database::create(root, secret) + create: PDO('sqlite::memory:') + setup: ... ``` -PHP のコードに対応します。 +`create` キーには`factory` という別名がある。しかし、`create` の使用を推奨する。 -```php -public function createServiceDatabase(): PDO -{ - return My\Database::create('root', 'secret'); -} -``` - -静的メソッド`My\Database::create()` は、DI コンテナが知る必要のある戻り値が定義されていることが前提です。もしそれがない場合は、その型を設定に書き込みます。 +コンストラクタの引数や作成メソッドは、`arguments` キーに記述することもできる: ```neon services: database: - create: My\Database::create(root, secret) - type: PDO + create: PDO + arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] ``` -Nette DIは、非常に強力な表現機能を備えており、ほとんど何でも書くことができます。例えば、他のサービスを[参照して |#Referencing Services]、そのメソッドを呼び出すことができます。簡単のために、`->` の代わりに`::` を使用します。 +静的メソッドや他のサービスのメソッドを呼び出すことによって生成されることもあります: ```neon services: - routerFactory: App\Router\Factory + database: DatabaseFactory::create() router: @routerFactory::create() ``` -PHPのコードに対応します。 +簡単にするために、`->` の代わりに`::` を使うことに注意[。 |#expression means]これらのファクトリーメソッドは生成されます: ```php -public function createServiceRouterFactory(): App\Router\Factory +public function createServiceDatabase(): PDO { - return new App\Router\Factory; + return DatabaseFactory::create(); } -public function createServiceRouter(): Router +public function createServiceRouter(): RouteList { return $this->getService('routerFactory')->create(); } ``` -PHPのようにメソッドコールを連鎖させることができます。 +DIコンテナは、作成されたサービスのタイプを知る必要がある。戻り値の型が指定されていないメソッドを使用してサービスを作成する場合は、設定にこの型を明示的に記述する必要があります: ```neon services: - foo: FooFactory::build()::get() -``` - -PHPのコードに対応しています。 - -```php -public function createServiceFoo() -{ - return FooFactory::build()->get(); -} + database: + create: DatabaseFactory::create() + type: PDO ``` 引数 .[#toc-arguments] ==================== -名前付きパラメータは引数の受け渡しに使うこともできます。 +コンストラクタやメソッドに引数を渡す方法は、通常のPHPとよく似ています: ```neon services: - database: PDO( - 'mysql:host=127.0.0.1;dbname=test' # positional - username: root # named - password: secret # named - ) -``` - -引数を複数行に分ける場合、カンマの使用は任意である。 - -もちろん、[他のサービスや |#Referencing Services] [パラメータを |configuration#parameters]引数として使用することもできます。 - -```neon -services: - - Foo(@anotherService, %appDir%) -``` - -PHPのコードに対応します。 - -```php -public function createService01(): Foo -{ - return new Foo($this->getService('anotherService'), '...'); -} + database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` -第一引数が[自動生成で |autowiring]、第二引数を指定したい場合は、第一引数を省略して`_` character, for example `Foo(_, %appDir%)`. あるいは、第二引数のみを名前付きパラメータとして渡すのがよいでしょう。例えば、`Foo(path: %appDir%)`. - -Nette DI と NEON フォーマットは、ほとんど何でも書くことができる非常に強力な表現力を持っています。そのため、引数には新しく作成したオブジェクトを指定したり、静的メソッドや他のサービスのメソッドを呼び出したり、特殊な記法を使ってグローバルな関数を呼び出すこともできます。 +読みやすくするために、引数を別々の行に書くこともできます。この形式では、カンマの使用は任意です: ```neon services: - analyser: My\Analyser( - FilesystemIterator(%appDir%) # create object - DateTime::createFromFormat('Y-m-d') # call static method - @anotherService # passing another service - @http.request::getRemoteAddress() # calling another service method - ::getenv(NetteMode) # call a global function + database: PDO( + 'mysql:host=127.0.0.1;dbname=test' + root + secret ) ``` -PHPのコードに対応します。 - -```php -public function createServiceAnalyser(): My\Analyser -{ - return new My\Analyser( - new FilesystemIterator('...'), - DateTime::createFromFormat('Y-m-d'), - $this->getService('anotherService'), - $this->getService('http.request')->getRemoteAddress(), - getenv('NetteMode') - ); -} -``` - - -特殊機能 .[#toc-special-functions] ------------------------------- - -引数で特殊関数を使用し、値のキャストやネゲートを行うこともできます。 - --`not(%arg%)` 負論理 --`bool(%arg%)` 無損失な bool へのキャスト --`int(%arg%)` int へのロスレスキャスト --`float(%arg%)` float へのロスレスキャスト --`string(%arg%)` ロスレス キャストから文字列 +また、引数に名前を付けることもでき、その場合は順番を気にする必要はありません: ```neon services: - - Foo( - id: int(::getenv('ProjectId')) - productionMode: not(%debugMode%) + database: PDO( + username: root + password: secret + dsn: 'mysql:host=127.0.0.1;dbname=test' ) ``` -ロスレス書き換えは、通常の PHP の書き換え (`(int)` など) とは異なり、数値以外の値では例外がスローされます。 - -引数として、複数のサービスを渡すことができます。特定の型 (クラスやインターフェイス) のすべてのサービスの配列は、関数`typed()` で作成されます。この関数では,自動配線を無効にしているサービスは省略されます.また,複数のタイプをカンマで区切って指定することもできます. - -```neon -services: - - BarsDependent( typed(Bar) ) -``` - -また,[autowiringを |autowiring#Collection of Services]使用して,自動的にサービスの配列を渡すこともできます. - -ある[タグを |#tags]持つすべてのサービスの配列を関数`tagged()` で作成します.タグはカンマで区切って複数指定することができます。 - -```neon -services: - - LoggersDependent( tagged(logger) ) -``` - - -参照先サービス .[#toc-referencing-services] -==================================== - -個々のサービスの参照には、`@` and name, so for example `@database` を使用します。 +特定の引数を省略してデフォルト値を使用したい場合や、[自動配線で |autowiring]サービスを挿入したい場合は、アンダースコアを使用します: ```neon services: - - create: Foo(@database) - setup: - - setCacheStorage(@cache.storage) -``` - -PHPのコードに対応します。 - -```php -public function createService01(): Foo -{ - $service = new Foo($this->getService('database')); - $service->setCacheStorage($this->getService('cache.storage')); - return $service; -} + foo: Foo(_, %appDir%) ``` -匿名サービスでもコールバックを使って参照することができます。ただし、[自動配線の |autowiring]関係で通常は必要ありません。 - -```neon -services: - - create: Foo(@Nette\Database\Connection) - setup: - - setCacheStorage(@cache.storage) -``` +引数には、サービス、パラメータ、その他いろいろなものがあります[。 |#expression means] セットアップ .[#toc-setup] ==================== -セットアップでは、サービスを作成する際に呼び出されるメソッドをリストアップします。 +`setup` セクションでは、サービスを作成する際に呼び出されるメソッドを定義します。 ```neon services: @@ -274,7 +152,7 @@ services: - setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) ``` -PHPのコードに対応します。 +PHPでは次のようになります: ```php public function createServiceDatabase(): PDO @@ -285,8 +163,7 @@ public function createServiceDatabase(): PDO } ``` -プロパティを設定することも可能です。配列への要素の追加もサポートされており、NEON の構文と衝突しないように引用符で囲んで記述する必要があります。 - +メソッド呼び出しに加えて、プロパティに値を渡すこともできます。配列への要素の追加もサポートされていますが、NEON構文と衝突しないように引用符で囲む必要があります: ```neon services: @@ -297,7 +174,7 @@ services: - '$onClick[]' = [@bar, clickHandler] ``` -PHP のコードに対応します。 +PHPでは次のようになります: ```php public function createServiceFoo(): Foo @@ -309,8 +186,7 @@ public function createServiceFoo(): Foo } ``` -ただし、静的メソッドや他のサービスのメソッドもセットアップで呼び出すことができます。それらには、実際のサービスを`@self` として渡します。 - +セットアップでは、静的メソッドや他のサービスのメソッドを呼び出すこともできます。現在のサービスを引数として渡す必要がある場合は、`@self` : ```neon services: @@ -321,7 +197,7 @@ services: - @anotherService::setFoo(@self) ``` -PHPのコードに対応する。 +簡単のため、`->` の代わりに、`::` を使用することに注意して[ください |#expression means]。これにより、以下のファクトリーメソッドが生成される: ```php public function createServiceFoo(): Foo @@ -334,23 +210,133 @@ public function createServiceFoo(): Foo ``` -オートワイヤリング .[#toc-autowiring] -============================ +表現方法 .[#toc-expression-means] +============================= + +Nette DIは、非常に豊富な表現機能を備えており、ほとんど何でも表現することができます。設定ファイルでは、[パラメータを |configuration#parameters]使うことができます: + +```neon +# parameter +%wwwDir% + +# value under a parameter key +%mailer.user% + +# parameter within a string +'%wwwDir%/images' +``` + +また、オブジェクトを作成したり、メソッドや関数を呼び出したりすることもできます: + +```neon +# create an object +DateTime() + +# call a static method +Collator::create(%locale%) + +# call a PHP function +::getenv(DB_USER) +``` + +サービスを名前またはタイプで参照する: + +```neon +# service by name +@database + +# service by type +@Nette\Database\Connection +``` + +定数を使用する: + +```neon +# class constant +FilesystemIterator::SKIP_DOTS + +# global constant obtained by the PHP function constant() +::constant(PHP_VERSION) +``` + +Method calls can be chained, just like in PHP. For simplicity, instead of `->`, we use `::`: + +```neon +DateTime()::format('Y-m-d') +# PHP: (new DateTime())->format('Y-m-d') + +@http.request::getUrl()::getHost() +# PHP: $this->getService('http.request')->getUrl()->getHost() +``` + +これらの式は、[サービスを作成する |#Service Creation]際、[引数 |#Arguments]、[設定 |#setup]セクション、[パラメータなど |configuration#parameters]、どこでも使用できます: + +```neon +parameters: + ipAddress: @http.request::getRemoteAddress() + +services: + database: + create: DatabaseFactory::create( @anotherService::getDsn() ) + setup: + - initialize( ::getenv('DB_USER') ) +``` + + +特殊機能 .[#toc-special-functions] +------------------------------ + +コンフィギュレーション・ファイル内では、これらの特殊関数を利用することができます: + +-`not()` 値の否定 +-`bool()`,`int()`,`float()`,`string()` によるロスレス型キャスト +-`typed()` 指定された型のすべてのサービスの配列を生成する。 +-`tagged()` 指定されたタグを持つすべてのサービスの配列を作成する。 + +```neon +services: + - Foo( + id: int(::getenv('ProjectId')) + productionMode: not(%debugMode%) + ) +``` + +`(int)` のような PHP の従来の型キャストと比較すると、 ロスレス型キャストは数値以外の値に対して例外をスローします。 + +`typed()` 関数は、特定の型 (クラスまたはインターフェイス) のすべてのサービスの配列を作成します。自動配線をオフにしたサービスは除外されます。複数の型をカンマ区切りで指定することができます。 + +```neon +services: + - BarsDependent( typed(Bar) ) +``` + +また、[自動配線を |autowiring#Collection of Services]使用して、特定のタイプのサービスの配列を自動的に引数として渡すこともできます。 + +`tagged()` 関数は、指定されたタグを持つすべてのサービスの配列を作成します。複数のタグをカンマ区切りで列挙できます。 + +```neon +services: + - LoggersDependent( tagged(logger) ) +``` + + +自動配線 .[#toc-autowiring] +======================= -autowiredキーは、あるサービスを自動配線から除外したり、その動作に影響を与えたりするために使用されます。詳細については、「自動配線」の[章を |autowiring]参照してください。 +`autowired` キーにより、特定のサービスの自動配線の動作を変更することができます。詳細は自動配線の[章を |autowiring]参照してください。 ```neon services: foo: create: Foo - autowired: false # foo is removed from autowiring + autowired: false # fooサービスは自動配線の対象外です。 ``` タグ .[#toc-tags] =============== -個々のサービスには、タグという形でユーザー情報を付加することができます。 +タグはサービスに補足情報を追加するために使用します。サービスには1つ以上のタグを割り当てることができます. ```neon services: @@ -360,7 +346,7 @@ services: - cached ``` -タグは値を持つこともできます。 +タグは値を持つこともできます: ```neon services: @@ -370,26 +356,26 @@ services: logger: monolog.logger.event ``` -特定のタグを持つサービスの配列は,関数`tagged()` を使って引数として渡すことができます.カンマで区切って複数のタグを指定することもできます. +特定のタグを持つすべてのサービスを検索するには、`tagged()` 関数を使用できます: ```neon services: - LoggersDependent( tagged(logger) ) ``` -サービス名は,DIコンテナから`findByTag()` というメソッドで取得することができる. +DIコンテナでは、`findByTag()` メソッドを使用して、特定のタグを持つすべてのサービス名を取得できます: ```php $names = $container->findByTag('logger'); -// $names is an array containing the service name and tag value -// i.e. ['foo' => 'monolog.logger.event', ...] +// namesはサービス名とタグの値を含む配列です。 + 例えば ['foo' => 'monolog.logger.event', ...] などです。 ``` インジェクトモード .[#toc-inject-mode] ============================= -`inject: true` フラグは、[inject |best-practices:en:inject-method-attribute#Inject Attributes]アノテーションと[inject*() |best-practices:en:inject-method-attribute#inject Methods]メソッドによるパブリック変数経由の依存関係の受け渡しを有効にするために使用されます。 +フラグ`inject: true` を使用すると、[inject |best-practices:en:inject-method-attribute#Inject Attributes]アノテーションと[inject*() |best-practices:en:inject-method-attribute#inject Methods]メソッドでパブリック変数を介した依存関係の受け渡しが有効になります。 ```neon services: @@ -401,10 +387,10 @@ services: デフォルトでは、`inject` はプレゼンターに対してのみ有効です。 -サービスの変更 .[#toc-modification-of-services] -======================================== +サービスの変更 .[#toc-service-modifications] +===================================== -DIコンテナには、ビルトインまたは[拡張機能 |#di-extensions]によって追加されたサービスが多数存在します。これらのサービスの定義は、コンフィギュレーションで変更することができます。例えば、サービス`application.application` 、デフォルトではオブジェクト`Nette\Application\Application` 、クラスを変更することができます。 +DIコンテナには、組み込みまたは[ユーザーによる拡張によって |#extensions]追加された多くのサービスが含まれています。これらのサービスの定義は、コンフィギュレーションで直接変更できます。たとえば、従来は`Nette\Application\Application` であった`application.application` サービスのクラスを別のものに変更することができます: ```neon services: @@ -413,9 +399,9 @@ services: alteration: true ``` -`alteration` フラグは情報提供であり、既存のサービスを変更するだけであることを示します。 +`alteration` フラグは、単に既存のサービスを変更するだけであることを示す情報的なものである。 -また、セットアップを追加することもできます。 +セットアップを補足することもできる: ```neon services: @@ -426,7 +412,7 @@ services: - '$onStartup[]' = [@resource, init] ``` -サービスを書き換える際、元の引数や設定項目、タグを削除したい場合があります。そのために、`reset` 。 +サービスを上書きする際に、オリジナルの引数や設定項目、タグを削除したい場合があります。このような場合に便利なのが、`reset` : ```neon services: @@ -439,7 +425,7 @@ services: - tags ``` -拡張で追加されたサービスもコンテナから削除することができます. +拡張機能によって追加されたサービスを削除したい場合は、次のようにします: ```neon services: diff --git a/dependency-injection/pl/services.texy b/dependency-injection/pl/services.texy index f38f1f389a..330962ebf9 100644 --- a/dependency-injection/pl/services.texy +++ b/dependency-injection/pl/services.texy @@ -2,32 +2,32 @@ Definiowanie usług ****************** .[perex] -Konfiguracja to miejsce, w którym umieszczamy nasze niestandardowe definicje usług. Służy do tego sekcja `services`. +Konfiguracja to miejsce, w którym instruujemy kontener DI, jak składać poszczególne usługi i jak łączyć je z innymi zależnościami. Nette zapewnia bardzo przejrzysty i elegancki sposób na osiągnięcie tego celu. -Na przykład w ten sposób tworzymy serwis o nazwie `database`, który będzie instancją klasy `PDO`: +Sekcja `services` w pliku konfiguracyjnym NEON to miejsce, w którym definiujemy nasze niestandardowe usługi i ich konfiguracje. Przyjrzyjmy się prostemu przykładowi definiowania usługi o nazwie `database`, która reprezentuje instancję klasy `PDO`: ```neon services: database: PDO('sqlite::memory:') ``` -Nazewnictwo usług służy do [odwoływania się |#Referencing-Services] do nich. Jeśli usługa nie jest przywoływana, nie musi być nazwana. Więc po prostu używamy wypunktowania zamiast nazwy: +Ta konfiguracja skutkuje następującą metodą fabryczną w [kontenerze DI |container]: -```neon -services: - - PDO('sqlite::memory:') # anonimowa usługa +```php +public function createServiceDatabase(): PDO +{ + return new PDO('sqlite::memory:'); +} ``` -Wpis jednowierszowy może być rozbity na wiele wierszy, aby umożliwić dodanie innych klawiszy, takich jak [konfiguracja |#Setup]. Alias dla klucza `create:` to `factory:`. +Nazwy usług pozwalają nam odwoływać się do nich w innych częściach pliku konfiguracyjnego, używając formatu `@serviceName`. Jeśli nie ma potrzeby nazywania usługi, możemy po prostu użyć punktora: ```neon services: - database: - create: PDO('sqlite::memory:') - setup: ... + - PDO('sqlite::memory:') ``` -Usługa jest następnie pobierana z kontenera DI za pomocą metody `getService()` by name lub lepiej `getByType()` by type: +Aby pobrać usługę z kontenera DI, możemy użyć metody `getService()` z nazwą usługi jako parametrem lub metody `getByType()` z typem usługi: ```php $database = $container->getService('database'); @@ -35,236 +35,114 @@ $database = $container->getByType(PDO::class); ``` -Tworzenie usługi .[#toc-creating-a-service] -=========================================== +Tworzenie usług .[#toc-service-creation] +======================================== -Najczęściej tworzymy usługę, tworząc po prostu instancję klasy: +Najczęściej tworzymy usługę po prostu poprzez instancjonowanie określonej klasy. Na przykład: ```neon services: database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` -Co generuje metodę fabryczną w [kontenerze DI |container]: - -```php -public function createServiceDatabase(): PDO -{ - return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret'); -} -``` - -Alternatywnie, klucz `arguments` może być użyty do przekazania [argumentów |#Arguments]: +Jeśli musimy rozszerzyć konfigurację o dodatkowe klucze, definicję można rozszerzyć na wiele linii: ```neon services: database: - create: PDO - arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] -``` - -Metoda statyczna może również tworzyć usługę: - -```neon -services: - database: My\Database::create(root, secret) + create: PDO('sqlite::memory:') + setup: ... ``` -Odpowiada kodowi PHP: +Klucz `create` ma alias `factory`, obie wersje są powszechne w praktyce. Zalecamy jednak używanie `create`. -```php -public function createServiceDatabase(): PDO -{ - return My\Database::create('root', 'secret'); -} -``` - -Zakłada się, że metoda statyczna `My\Database::create()` ma zdefiniowaną wartość zwrotną, którą kontener DI musi znać. Jeśli go nie ma, zapisz typ do konfiguracji: +Argumenty konstruktora lub metoda tworzenia mogą być alternatywnie zapisane w kluczu `arguments`: ```neon services: database: - create: My\Database::create(root, secret) - type: PDO + create: PDO + arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] ``` -Nette DI daje nam niezwykle potężne środki wyrazu, które możesz wykorzystać do napisania niemal wszystkiego. Na przykład, aby [odwołać się do |#Referencing-Services] innej usługi i wywołać jej metodę. Dla uproszczenia, zamiast `->`, używamy `::` +Usługi nie muszą być tworzone tylko przez prostą instancję klasy; mogą one również wynikać z wywoływania metod statycznych lub metod innych usług: ```neon services: - routerFactory: App\Router\Factory + database: DatabaseFactory::create() router: @routerFactory::create() ``` -Odpowiada kodowi PHP: +Zauważ, że dla uproszczenia, zamiast `->`, używamy `::`, patrz [wyrażenie oznacza |#expression means]. Te metody fabryczne są generowane: ```php -public function createServiceRouterFactory(): App\Router\Factory +public function createServiceDatabase(): PDO { - return new App\Router\Factory; + return DatabaseFactory::create(); } -public function createServiceRouter(): Router +public function createServiceRouter(): RouteList { return $this->getService('routerFactory')->create(); } ``` -Wywołania metod mogą być łączone łańcuchowo, tak jak w PHP: +Kontener DI musi znać typ tworzonej usługi. Jeśli tworzymy usługę przy użyciu metody, która nie ma określonego typu zwracanego, musimy wyraźnie wspomnieć o tym typie w konfiguracji: ```neon services: - foo: FooFactory::build()::get() -``` - -Odpowiada kodowi PHP: - -```php -public function createServiceFoo() -{ - return FooFactory::build()->get(); -} + database: + create: DatabaseFactory::create() + type: PDO ``` Argumenty .[#toc-arguments] =========================== -Parametry nazwane mogą być również używane do przekazywania argumentów: +Przekazujemy argumenty do konstruktorów i metod w sposób bardzo podobny do zwykłego PHP: ```neon services: - database: PDO( - 'mysql:host=127.0.0.1;dbname=test' # pozycja - username: root # nazwa - password: secret # nazwa - ) -``` - -Przy dzieleniu argumentów na wiele linii, użycie przecinków jest opcjonalne. - -Oczywiście jako argumenty mogą być użyte [inne usługi |#Referencing-Services] lub [parametry |configuration#parameters]: - -```neon -services: - - Foo(@anotherService, %appDir%) -``` - -Odpowiada kodowi PHP: - -```php -public function createService01(): Foo -{ - return new Foo($this->getService('anotherService'), '...'); -} + database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` -Jeśli pierwszy argument ma być [autowpisywany |autowiring], a chcemy dołączyć drugi argument, to pomijamy pierwszy argument za pomocą `_`, tedy např. `Foo(_, %appDir%)`. Albo jeszcze lepiej, po prostu przekaż drugi argument jako nazwany parametr, np. `Foo(path: %appDir%)`. - -Nette DI i format NEON dają nam niezwykle potężne zasoby ekspresyjne, które można wykorzystać do napisania niemal wszystkiego. Tak więc argumentem może być nowo utworzony obiekt, można wywoływać metody statyczne, metody innych serwisów, a nawet funkcje globalne przy użyciu specjalnej notacji: +Dla lepszej czytelności możemy wypisać argumenty w osobnych wierszach. W tym formacie użycie przecinków jest opcjonalne: ```neon services: - analyser: My\Analyser( - FilesystemIterator(%appDir%) # vytvoření objektu - DateTime::createFromFormat('Y-m-d') # volání statické metody - @anotherService # předání jiné služby - @http.request::getRemoteAddress() # volání metody jiné služby - ::getenv(NetteMode) # volání globální funkce + database: PDO( + 'mysql:host=127.0.0.1;dbname=test' + root + secret ) ``` -Odpowiada on kodowi PHP: - -```php -public function createServiceAnalyser(): My\Analyser -{ - return new My\Analyser( - new FilesystemIterator('...'), - DateTime::createFromFormat('Y-m-d'), - $this->getService('anotherService'), - $this->getService('http.request')->getRemoteAddress(), - getenv('NetteMode') - ); -} -``` - - -Funkcje specjalne .[#toc-special-functions] -------------------------------------------- - -Możesz również użyć specjalnych funkcji w argumentach, aby zastąpić lub zanegować wartości: - -- `not(%arg%)` negacja -- `bool(%arg%)` lossless override to bool -- `int(%arg%)` bezstratne przepisywanie na int -- `float(%arg%)` bezstratny reflow do float -- `string(%arg%)` bezstratne przepisywanie na ciąg znaków +Można również nazwać argumenty, co pozwala nie martwić się o ich kolejność: ```neon services: - - Foo( - id: int(::getenv('ProjectId')) - productionMode: not(%debugMode%) + database: PDO( + username: root + password: secret + dsn: 'mysql:host=127.0.0.1;dbname=test' ) ``` -Bezstratne repartycjonowanie różni się od normalnego repartycjonowania PHP, np. przy użyciu `(int)`, tym, że rzuca wyjątek dla wartości nienumerycznych. - -Jako argumenty można przekazać wiele usług. Tablicę wszystkich usług danego typu (tj. klasy lub interfejsu) tworzy funkcja `typed()`. Funkcja pomija usługi, które mają wyłączone autowiring, można podać wiele typów oddzielonych przecinkami. +Jeśli chcesz pominąć niektóre argumenty i użyć ich wartości domyślnych lub wstawić usługę poprzez [autowiring |autowiring], użyj podkreślenia: ```neon services: - - BarsDependent( typed(Bar) ) + foo: Foo(_, %appDir%) ``` -Możesz również przekazać tablicę usług automatycznie za pomocą [autowiring |autowiring#Collection-of-Services]. - -Funkcja `tagged()` tworzy tablicę wszystkich usług z określonym [tagiem |#Tags]. Można również podać wiele tagów oddzielonych przecinkiem. - -```neon -services: - - LoggersDependent( tagged(logger) ) -``` +Argumentami mogą być usługi, parametry i wiele innych, patrz [środki wyrazu |#expression means]. -Usługi odsyłania .[#toc-referencing-services] -============================================= +Konfiguracja .[#toc-setup] +========================== -Do usług odwołujemy się za pomocą nazwy usługi i nazwy serwisu, więc na przykład `@database`: - -```neon -services: - - create: Foo(@database) - setup: - - setCacheStorage(@cache.storage) -``` - -Odpowiada kodowi PHP: - -```php -public function createService01(): Foo -{ - $service = new Foo($this->getService('database')); - $service->setCacheStorage($this->getService('cache.storage')); - return $service; -} -``` - -Nawet anonimowe usługi mogą być przywoływane poprzez alias, wystarczy podać typ (klasa lub interfejs) zamiast nazwy. Zwykle jednak nie jest to konieczne ze względu na [autowiring |autowiring]. - -```neon -services: - - create: Foo(@Nette\Database\Connection) - setup: - - setCacheStorage(@cache.storage) -``` - - -Ustawienie .[#toc-setup] -======================== - -W sekcji setup znajduje się lista metod, które należy wywołać podczas tworzenia usługi: +W sekcji `setup` definiujemy metody, które powinny być wywoływane podczas tworzenia usługi. ```neon services: @@ -274,7 +152,7 @@ services: - setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) ``` -Odpowiada kodowi PHP: +W PHP wyglądałoby to następująco: ```php public function createServiceDatabase(): PDO @@ -285,8 +163,7 @@ public function createServiceDatabase(): PDO } ``` -Można również ustawić wartości zmienne. Dodawanie elementu do tablicy jest również obsługiwane, ale musi być napisane w cudzysłowie, aby uniknąć konfliktu ze składnią NEON: - +Oprócz wywoływania metod, można również przekazywać wartości do właściwości. Dodawanie elementu do tablicy jest również obsługiwane, ale należy je ująć w cudzysłów, aby uniknąć kolizji ze składnią NEON: ```neon services: @@ -297,7 +174,7 @@ services: - '$onClick[]' = [@bar, clickHandler] ``` -Odpowiada kodowi PHP: +W PHP tłumaczyłoby się to na: ```php public function createServiceFoo(): Foo @@ -309,8 +186,7 @@ public function createServiceFoo(): Foo } ``` -Jednak metody statyczne lub metody innych usług mogą być wywoływane w konfiguracji. Rzeczywista usługa jest przekazywana do nich jako `@self`: - +W konfiguracji można również wywoływać metody statyczne lub metody innych usług. Jeśli chcesz przekazać bieżącą usługę jako argument, użyj `@self`: ```neon services: @@ -321,7 +197,7 @@ services: - @anotherService::setFoo(@self) ``` -Odpowiada kodowi PHP: +Zauważ, że dla uproszczenia, zamiast `->`, używamy `::`, patrz [środki wyrazu |#expression means]. Spowoduje to wygenerowanie następującej metody fabrycznej: ```php public function createServiceFoo(): Foo @@ -334,23 +210,133 @@ public function createServiceFoo(): Foo ``` -Autowiring .[#toc-autowiring] -============================= +Środki wyrazu .[#toc-expression-means] +====================================== + +Nette DI zapewnia nam wyjątkowo bogate możliwości wyrażania, pozwalając nam wyrazić prawie wszystko. W plikach konfiguracyjnych możemy używać [parametrów |configuration#parameters]: + +```neon +# parametr +%wwwDir% + +# wartość pod kluczem parametru +%mailer.user% + +# parametr w ciągu znaków +'%wwwDir%/images' +``` + +Możemy również tworzyć obiekty, wywoływać metody i funkcje: + +```neon +# utworzyć obiekt +DateTime() + +# wywołać metodę statyczną +Collator::create(%locale%) + +# wywołać funkcję PHP +::getenv(DB_USER) +``` + +Odnosić się do usług poprzez ich nazwę lub typ: + +```neon +# usługa według nazwy +@database + +# usługa według typu +@Nette\Database\Connection +``` + +Użyj stałych: + +```neon +# stała klasy +FilesystemIterator::SKIP_DOTS + +# stała globalna uzyskana przez funkcję PHP constant() +::constant(PHP_VERSION) +``` + +Wywołania metod mogą być łańcuchowane, tak jak w PHP. Dla uproszczenia, zamiast `->`, używamy `::`: + +```neon +DateTime()::format('Y-m-d') +# PHP: (new DateTime())->format('Y-m-d') + +@http.request::getUrl()::getHost() +# PHP: $this->getService('http.request')->getUrl()->getHost() +``` + +Wyrażenia te mogą być używane w dowolnym miejscu podczas [tworzenia usług |#Service Creation], w [argumentach |#Arguments], w sekcji [konfiguracji |#setup] lub w [parametrach |configuration#parameters]: + +```neon +parameters: + ipAddress: @http.request::getRemoteAddress() + +services: + database: + create: DatabaseFactory::create( @anotherService::getDsn() ) + setup: + - initialize( ::getenv('DB_USER') ) +``` + + +Funkcje specjalne .[#toc-special-functions] +------------------------------------------- + +W plikach konfiguracyjnych można korzystać z tych funkcji specjalnych: + +- `not()` dla negacji wartości +- `bool()`, `int()`, `float()`, `string()` do bezstratnego rzutowania typów +- `typed()` do generowania tablicy wszystkich usług określonego typu +- `tagged()` do tworzenia tablicy wszystkich usług z danym tagiem + +```neon +services: + - Foo( + id: int(::getenv('ProjectId')) + productionMode: not(%debugMode%) + ) +``` + +W porównaniu do konwencjonalnego rzutowania typów w PHP, takiego jak `(int)`, bezstratne rzutowanie typów rzuci wyjątek dla wartości nienumerycznych. + +Funkcja `typed()` tworzy tablicę wszystkich usług określonego typu (klasy lub interfejsu). Wyklucza ona usługi z wyłączonym autowiringiem. Można określić wiele typów, oddzielając je przecinkami. + +```neon +services: + - BarsDependent( typed(Bar) ) +``` + +Można również automatycznie przekazać tablicę usług określonego typu jako argument przy użyciu [autowiring |autowiring#Collection of Services]. + +Funkcja `tagged()` tworzy tablicę wszystkich usług z określonym tagiem. Można wymienić wiele tagów, oddzielając je przecinkami. + +```neon +services: + - LoggersDependent( tagged(logger) ) +``` + + +Okablowanie .[#toc-autowiring] +============================== -Możesz użyć klucza autowired, aby wykluczyć usługę z autowiring lub wpłynąć na jej zachowanie. Więcej informacji można znaleźć w [rozdziale dotyczącym autowiring |autowiring]. +Klucz `autowired` pozwala modyfikować zachowanie autoprzewodowania dla określonej usługi. Więcej szczegółów można znaleźć [w |autowiring] rozdziale autowiring. ```neon services: foo: create: Foo - autowired: false # service foo jest wyłączony z autowiring + autowired: false # usługa foo jest wyłączona z automatycznego okablowania ``` Tagi .[#toc-tags] ================= -Informacje o użytkownikach mogą być dodawane do poszczególnych serwisów w postaci tagów: +Tagi służą do dodawania dodatkowych informacji do usług. Do usługi można przypisać jeden lub więcej tagów: ```neon services: @@ -360,7 +346,7 @@ services: - cached ``` -Tagi mogą mieć również wartość: +Tagi mogą również zawierać wartości: ```neon services: @@ -370,26 +356,26 @@ services: logger: monolog.logger.event ``` -Możesz przekazać tablicę usług z określonymi tagami jako argument za pomocą funkcji `tagged()`. Możesz określić wiele tagów oddzielonych przecinkami. +Aby pobrać wszystkie usługi z określonymi tagami, można użyć funkcji `tagged()`: ```neon services: - LoggersDependent( tagged(logger) ) ``` -Nazwy usług można pobrać z kontenera DI za pomocą metody `findByTag()`: +W kontenerze DI można uzyskać nazwy wszystkich usług z określonym tagiem za pomocą metody `findByTag()`: ```php $names = $container->findByTag('logger'); -// $names jest tablicą zawierającą nazwę serwisu i wartość tagu -// np. ['foo' => 'monolog.logger.event', ...] +// $names to tablica zawierająca nazwę usługi i wartość tagu +// np. ['foo' => 'monolog.logger.event', ...]. ``` -Tryb wtrysku .[#toc-inject-mode] -================================ +Tryb wstrzykiwania .[#toc-inject-mode] +====================================== -Flaga `inject: true` służy do aktywowania przekazywania zależności poprzez zmienne publiczne z adnotacją [inject |best-practices:inject-method-attribute#Inject-Attribute] i metodami [inject*() |best-practices:inject-method-attribute#inject-Methods]. +Użycie flagi `inject: true` aktywuje przekazywanie zależności poprzez zmienne publiczne z adnotacją [inject |best-practices:inject-method-attribute#Inject Attributes] i metodami [inject*() |best-practices:inject-method-attribute#inject Methods]. ```neon services: @@ -398,13 +384,13 @@ services: inject: true ``` -Domyślnie strona `inject` jest aktywowana tylko dla prezenterów. +Domyślnie flaga `inject` jest aktywowana tylko dla prezenterów. -Modyfikacja usług .[#toc-modification-of-services] -================================================== +Modyfikacje usługi .[#toc-service-modifications] +================================================ -Istnieje wiele usług w kontenerze DI, które dodały wbudowane lub [twoje rozszerzenia |#rozšíření]. Definicje tych usług mogą być modyfikowane w konfiguracji. Na przykład dla serwisu `application.application`, który domyślnie jest obiektem `Nette\Application\Application`, możemy zmienić klasę: +Kontener DI zawiera wiele usług dodanych przez [rozszerzenia |#extensions] wbudowane lub [użytkownika |#extensions]. Definicje tych usług można modyfikować bezpośrednio w konfiguracji. Na przykład można zmienić klasę usługi `application.application`, która jest konwencjonalnie `Nette\Application\Application`, na coś innego: ```neon services: @@ -413,9 +399,9 @@ services: alteration: true ``` -Flaga `alteration` ma charakter informacyjny i mówi, że właśnie modyfikujemy istniejącą usługę. +Flaga `alteration` ma charakter informacyjny, wskazując, że jedynie modyfikujemy istniejącą usługę. -Możemy również dodać ustawienie: +Możemy również uzupełnić konfigurację: ```neon services: @@ -426,7 +412,7 @@ services: - '$onStartup[]' = [@resource, init] ``` -Podczas przepisywania usługi możemy chcieć usunąć oryginalne argumenty, elementy ustawień lub tagi, do czego służy `reset`: +Podczas nadpisywania usługi może być konieczne usunięcie oryginalnych argumentów, elementów konfiguracji lub tagów, co jest przydatne w przypadku `reset`: ```neon services: @@ -439,7 +425,7 @@ services: - tags ``` -Usługa dodana przez rozszerzenie może być również usunięta z kontenera: +Jeśli chcesz usunąć usługę dodaną przez rozszerzenie, możesz to zrobić w następujący sposób: ```neon services: diff --git a/dependency-injection/pt/services.texy b/dependency-injection/pt/services.texy index 654948c932..7949e54b43 100644 --- a/dependency-injection/pt/services.texy +++ b/dependency-injection/pt/services.texy @@ -2,32 +2,32 @@ Definições de serviço ********************* .[perex] -A configuração é onde colocamos as definições de serviços personalizados. Isto é feito na seção `services`. +A configuração é o local em que instruímos o contêiner DI sobre como montar serviços individuais e como conectá-los a outras dependências. O Nette oferece uma maneira muito clara e elegante de fazer isso. -Por exemplo, é assim que criamos um serviço chamado `database`, que será uma instância da classe `PDO`: +A seção `services` no arquivo de configuração do NEON é onde definimos nossos serviços personalizados e suas configurações. Vamos dar uma olhada em um exemplo simples de definição de um serviço chamado `database`, que representa uma instância da classe `PDO`: ```neon services: database: PDO('sqlite::memory:') ``` -A nomenclatura dos serviços é utilizada para nos permitir [referenciá-los |#Referencing Services]. Se um serviço não é referenciado, não há necessidade de nomeá-lo. Portanto, usamos apenas um ponto em vez de um nome: +Essa configuração resulta no seguinte método de fábrica no [contêiner DI |container]: -```neon -services: - - PDO('sqlite::memory:') # serviço anônimo +```php +public function createServiceDatabase(): PDO +{ + return new PDO('sqlite::memory:'); +} ``` -Uma entrada de uma linha pode ser dividida em várias linhas para permitir que chaves adicionais sejam adicionadas, tais como [configuração |#setup]. O pseudônimo para a chave `create:` é `factory:`. +Os nomes dos serviços nos permitem fazer referência a eles em outras partes do arquivo de configuração, usando o formato `@serviceName`. Se não houver necessidade de nomear o serviço, podemos simplesmente usar um marcador: ```neon services: - database: - create: PDO('sqlite::memory:') - setup: ... + - PDO('sqlite::memory:') ``` -Recuperamos então o serviço do recipiente DI usando o método `getService()` pelo nome, ou melhor ainda, o método `getByType()` pelo tipo: +Para recuperar um serviço do contêiner DI, podemos usar o método `getService()` com o nome do serviço como parâmetro ou o método `getByType()` com o tipo de serviço: ```php $database = $container->getService('database'); @@ -35,236 +35,114 @@ $database = $container->getByType(PDO::class); ``` -Criando um serviço .[#toc-creating-a-service] -============================================= +Criação de serviços .[#toc-service-creation] +============================================ -Na maioria das vezes, nós criamos um serviço simplesmente criando uma instância de uma classe: +Geralmente, criamos um serviço simplesmente instanciando uma classe específica. Por exemplo: ```neon services: database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` -O que gerará um método de fábrica em [contêineres DI |container]: - -```php -public function createServiceDatabase(): PDO -{ - return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret'); -} -``` - -Alternativamente, uma chave `arguments` pode ser usada para passar [argumentos |#Arguments]: +Se precisarmos expandir a configuração com chaves adicionais, a definição poderá ser expandida em várias linhas: ```neon services: database: - create: PDO - arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] -``` - -Um método estático também pode criar um serviço: - -```neon -services: - database: My\Database::create(root, secret) + create: PDO('sqlite::memory:') + setup: ... ``` -Corresponde ao código PHP: +A chave `create` tem um alias `factory`, ambas as versões são comuns na prática. No entanto, recomendamos o uso de `create`. -```php -public function createServiceDatabase(): PDO -{ - return My\Database::create('root', 'secret'); -} -``` - -Presume-se que um método estático `My\Database::create()` tenha um valor de retorno definido que o recipiente DI precisa conhecer. Se não o tiver, escrevemos o tipo na configuração: +Como alternativa, os argumentos do construtor ou o método de criação podem ser escritos na chave `arguments`: ```neon services: database: - create: My\Database::create(root, secret) - type: PDO + create: PDO + arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] ``` -A Nette DI lhe dá facilidades de expressão extremamente poderosas para escrever quase tudo. Por exemplo, para [se referir |#Referencing Services] a outro serviço e chamar seu método. Para simplificar, `::` é usado ao invés de `->`. +Os serviços não precisam ser criados apenas pela simples instanciação de uma classe; eles também podem resultar da chamada de métodos estáticos ou métodos de outros serviços: ```neon services: - routerFactory: App\Router\Factory + database: DatabaseFactory::create() router: @routerFactory::create() ``` -Corresponde ao código PHP: +Observe que, para simplificar, em vez de `->`, usamos `::`, veja a [expressão significa |#expression means]. Esses métodos de fábrica são gerados: ```php -public function createServiceRouterFactory(): App\Router\Factory +public function createServiceDatabase(): PDO { - return new App\Router\Factory; + return DatabaseFactory::create(); } -public function createServiceRouter(): Router +public function createServiceRouter(): RouteList { return $this->getService('routerFactory')->create(); } ``` -As chamadas de métodos podem ser encadeadas como em PHP: +O contêiner DI precisa saber o tipo do serviço criado. Se criarmos um serviço usando um método que não tenha um tipo de retorno especificado, devemos mencionar explicitamente esse tipo na configuração: ```neon services: - foo: FooFactory::build()::get() -``` - -Corresponde ao código PHP: - -```php -public function createServiceFoo() -{ - return FooFactory::build()->get(); -} + database: + create: DatabaseFactory::create() + type: PDO ``` Argumentos .[#toc-arguments] ============================ -Os parâmetros nomeados também podem ser usados para passar argumentos: +Passamos argumentos para construtores e métodos de forma muito semelhante ao PHP comum: ```neon services: - database: PDO( - 'mysql:host=127.0.0.1;dbname=test' # posicional - username: root # named - password: secret # named - ) -``` - -O uso de vírgulas é opcional ao quebrar argumentos em várias linhas. - -Naturalmente, também podemos utilizar [outros serviços |#Referencing Services] ou [parâmetros |configuration#parameters] como argumentos: - -```neon -services: - - Foo(@anotherService, %appDir%) -``` - -Corresponde ao código PHP: - -```php -public function createService01(): Foo -{ - return new Foo($this->getService('anotherService'), '...'); -} + database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` -Se o primeiro argumento for [auto-cablado |autowiring] e você quiser especificar o segundo, omitir o primeiro com o `_` character, for example `Foo(_, %appDir%)`. Ou melhor ainda, passar apenas o segundo argumento como um parâmetro nomeado, por exemplo `Foo(path: %appDir%)`. - -Nette DI e o formato NEON lhe dão facilidades extremamente poderosas para escrever quase tudo. Assim, um argumento pode ser um objeto recém-criado, você pode chamar métodos estáticos, métodos de outros serviços, ou mesmo funções globais usando notação especial: +Para facilitar a leitura, podemos listar os argumentos em linhas separadas. Nesse formato, o uso de vírgulas é opcional: ```neon services: - analisador: Meu Analisador ( - FilesystemIterator(%appDir%) # criar objeto - DateTime::createFromFormat('Y-m-d') # chama método estático - @anotherService # passando outro serviço - @http.request::getRemoteAddress() # chamando outro método de serviço - ::getenv(NetteMode) # chamar uma função global + database: PDO( + 'mysql:host=127.0.0.1;dbname=test' + root + secret ) ``` -Corresponde ao código PHP: - -```php -public function createServiceAnalyser(): My\Analyser -{ - return new My\Analyser( - new FilesystemIterator('...'), - DateTime::createFromFormat('Y-m-d'), - $this->getService('anotherService'), - $this->getService('http.request')->getRemoteAddress(), - getenv('NetteMode') - ); -} -``` - - -Funções especiais .[#toc-special-functions] -------------------------------------------- - -Você também pode usar funções especiais em argumentos para lançar ou negar valores: - -- `not(%arg%)` negação -- `bool(%arg%)` elenco sem perdas a bool -- `int(%arg%)` elenco sem perdas para int -- `float(%arg%)` elenco sem perdas para flutuar -- `string(%arg%)` elenco sem perdas para cordas +Você também pode nomear os argumentos, o que permite que você não se preocupe com a ordem deles: ```neon services: - - Foo( - id: int(::getenv('ProjectId')) - productionMode: not(%debugMode%) + database: PDO( + username: root + password: secret + dsn: 'mysql:host=127.0.0.1;dbname=test' ) ``` -A reescrita sem perdas difere da reescrita normal em PHP, por exemplo, usando `(int)`, na medida em que lança uma exceção para valores não-numéricos. - -Múltiplos serviços podem ser passados como argumentos. Um conjunto de todos os serviços de um determinado tipo (ou seja, classe ou interface) é criado pela função `typed()`. A função omitirá serviços que tenham a fiação automática desativada, e múltiplos tipos separados por uma vírgula podem ser especificados. +Se quiser omitir determinados argumentos e usar seus valores padrão ou inserir um serviço por meio da [conexão automática |autowiring], use um sublinhado: ```neon services: - - BarsDependent( typed(Bar) ) -``` - -Você também pode passar um conjunto de serviços automaticamente usando [a fiação automática |autowiring#Collection of Services]. - -Um conjunto de todos os serviços com uma certa [etiqueta |#tags] é criado pela função `tagged()`. Múltiplas tags separadas por uma vírgula podem ser especificadas. - -```neon -services: - - LoggersDependent( tagged(logger) ) + foo: Foo(_, %appDir%) ``` - -Serviços de referência .[#toc-referencing-services] -=================================================== - -Os serviços individuais são referenciados usando o personagem `@` and name, so for example `@database`: - -```neon -services: - - create: Foo(@database) - setup: - - setCacheStorage(@cache.storage) -``` - -Corresponde ao código PHP: - -```php -public function createService01(): Foo -{ - $service = new Foo($this->getService('database')); - $service->setCacheStorage($this->getService('cache.storage')); - return $service; -} -``` - -Mesmo serviços anônimos podem ser referenciados usando uma chamada de retorno, basta especificar seu tipo (classe ou interface) ao invés de seu nome. No entanto, isto geralmente não é necessário devido ao [cabeamento automático |autowiring]. - -```neon -services: - - create: Foo(@Nette\Database\Connection) - setup: - - setCacheStorage(@cache.storage) -``` +Os argumentos podem ser serviços, parâmetros e muito mais; consulte os [meios de expressão |#expression means]. Configuração .[#toc-setup] ========================== -Na seção de configuração, listamos os métodos a serem chamados ao criar o serviço: +Na seção `setup`, definimos os métodos que devem ser chamados ao criar o serviço. ```neon services: @@ -274,7 +152,7 @@ services: - setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) ``` -Corresponde ao código PHP: +Em PHP, isso seria parecido com: ```php public function createServiceDatabase(): PDO @@ -285,8 +163,7 @@ public function createServiceDatabase(): PDO } ``` -Também é possível definir os locais adequados. A adição de um elemento a uma matriz também é apoiada, e deve ser escrita entre aspas para não entrar em conflito com a sintaxe NEON: - +Além das chamadas de método, você também pode passar valores para as propriedades. A adição de um elemento a uma matriz também é suportada, mas você precisa colocá-la entre aspas para evitar colidir com a sintaxe NEON: ```neon services: @@ -297,7 +174,7 @@ services: - '$onClick[]' = [@bar, clickHandler] ``` -Corresponde ao código PHP: +Em PHP, isso se traduziria em: ```php public function createServiceFoo(): Foo @@ -309,8 +186,7 @@ public function createServiceFoo(): Foo } ``` -No entanto, métodos estáticos ou métodos de outros serviços também podem ser chamados na configuração. Passamos o serviço real a eles como `@self`: - +Na configuração, você também pode chamar métodos estáticos ou métodos de outros serviços. Se você precisar passar o serviço atual como um argumento, use `@self`: ```neon services: @@ -321,7 +197,7 @@ services: - @anotherService::setFoo(@self) ``` -Corresponde ao código PHP: +Observe que, para simplificar, em vez de `->`, usamos `::`, veja a [expressão significa |#expression means]. Isso gera o seguinte método de fábrica: ```php public function createServiceFoo(): Foo @@ -334,23 +210,133 @@ public function createServiceFoo(): Foo ``` -Cablagem automática .[#toc-autowiring] -====================================== +Meios de Expressão .[#toc-expression-means] +=========================================== + +O Nette DI nos fornece recursos de expressão excepcionalmente ricos, o que nos permite articular quase tudo. Nos arquivos de configuração, podemos usar [parâmetros |configuration#parameters]: + +```neon +# parâmetro +%wwwDir% + +# valor em uma chave de parâmetro +%mailer.user% + +# parâmetro em uma cadeia de caracteres +'%wwwDir%/images' +``` + +Também podemos criar objetos, chamar métodos e funções: + +```neon +# criar um objeto +DateTime() + +# chamar um método estático +Collator::create(%locale%) + +# chamar uma função PHP +::getenv(DB_USER) +``` + +Referir-se aos serviços pelo nome ou pelo tipo: + +```neon +# serviço por nome +@database + +# serviço por tipo +@Nette\Database\Connection +``` + +Usar constantes: + +```neon +# constante de classe +FilesystemIterator::SKIP_DOTS + +# constante global obtida pela função constant() do PHP +::constant(PHP_VERSION) +``` + +As chamadas de método podem ser encadeadas, assim como no PHP. Para simplificar, em vez de `->`, usamos `::`: + +```neon +DateTime()::format('Y-m-d') +# PHP: (new DateTime())->format('Y-m-d') + +@http.request::getUrl()::getHost() +# PHP: $this->getService('http.request')->getUrl()->getHost() +``` + +Essas expressões podem ser usadas em qualquer lugar ao [criar serviços |#Service Creation], em [argumentos |#Arguments], na seção de [configuração |#setup] ou em [parâmetros |configuration#parameters]: + +```neon +parameters: + ipAddress: @http.request::getRemoteAddress() + +services: + database: + create: DatabaseFactory::create( @anotherService::getDsn() ) + setup: + - initialize( ::getenv('DB_USER') ) +``` + + +Funções especiais .[#toc-special-functions] +------------------------------------------- + +Nos arquivos de configuração, você pode utilizar essas funções especiais: + +- `not()` para negação de valor +- `bool()`, `int()`, `float()`, `string()` para conversão de tipos sem perdas +- `typed()` para gerar uma matriz de todos os serviços de um tipo especificado +- `tagged()` para criar uma matriz de todos os serviços com uma determinada tag + +```neon +services: + - Foo( + id: int(::getenv('ProjectId')) + productionMode: not(%debugMode%) + ) +``` + +Em comparação com o typecasting convencional em PHP, como `(int)`, o lossless type casting lançará uma exceção para valores não numéricos. + +A função `typed()` cria uma matriz de todos os serviços de um tipo específico (classe ou interface). Ela exclui os serviços com o autowiring desativado. Vários tipos podem ser especificados, separados por vírgulas. + +```neon +services: + - BarsDependent( typed(Bar) ) +``` + +Você também pode passar automaticamente uma matriz de serviços de um tipo específico como um argumento usando o [autowiring |autowiring#Collection of Services]. + +A função `tagged()` cria uma matriz de todos os serviços com uma tag especificada. Várias tags podem ser listadas, separadas por vírgulas. + +```neon +services: + - LoggersDependent( tagged(logger) ) +``` + + +Fiação automática .[#toc-autowiring] +==================================== -A chave autowired pode ser usada para excluir um serviço da autowired ou para influenciar seu comportamento. Consulte o [capítulo sobre a fiação automática |autowiring] para obter mais informações. +A chave `autowired` permite modificar o comportamento de conexão automática de um serviço específico. Para obter mais detalhes, consulte [o capítulo Aut |autowiring]owiring. ```neon services: foo: create: Foo - autowired: false # foo é removido do autowiring + autowired: false # O serviço foo está excluído da autocablagem ``` -Etiquetas .[#toc-tags] -====================== +Tags .[#toc-tags] +================= -As informações do usuário podem ser adicionadas aos serviços individuais sob a forma de tags: +As tags são usadas para adicionar informações suplementares aos serviços. Você pode atribuir uma ou mais tags a um serviço: ```neon services: @@ -360,7 +346,7 @@ services: - cached ``` -As etiquetas também podem ter um valor: +As tags também podem conter valores: ```neon services: @@ -370,26 +356,26 @@ services: logger: monolog.logger.event ``` -Uma série de serviços com determinadas tags pode ser passada como argumento usando a função `tagged()`. Múltiplas tags separadas por uma vírgula também podem ser especificadas. +Para recuperar todos os serviços com tags específicas, você pode usar a função `tagged()`: ```neon services: - LoggersDependent( tagged(logger) ) ``` -Os nomes dos serviços podem ser obtidos no recipiente DI usando o método `findByTag()`: +No contêiner DI, você pode obter os nomes de todos os serviços com uma tag específica usando o método `findByTag()`: ```php $names = $container->findByTag('logger'); -// $names é um array contendo o nome do serviço e o valor da etiqueta -// i.e. ['foo' => 'monolog.logger.event', ...] +// $names é uma matriz que contém o nome do serviço e o valor da tag +// Por exemplo, ['foo' => 'monolog.logger.event', ...] ``` -Modo injetado .[#toc-inject-mode] -================================= +Modo de injeção .[#toc-inject-mode] +=================================== -A bandeira `inject: true` é usada para ativar a passagem de dependências através de variáveis públicas com a anotação de [injeção |best-practices:inject-method-attribute#Inject Attributes] e os métodos de [injeção*() |best-practices:inject-method-attribute#inject Methods]. +O uso do sinalizador `inject: true` ativa a passagem de dependências por meio de variáveis públicas com a anotação [inject |best-practices:inject-method-attribute#Inject Attributes] e os métodos [inject*() |best-practices:inject-method-attribute#inject Methods]. ```neon services: @@ -398,13 +384,13 @@ services: inject: true ``` -Por padrão, `inject` é ativado somente para apresentadores. +Por padrão, o `inject` só é ativado para apresentadores. -Modificação de serviços .[#toc-modification-of-services] -======================================================== +Modificações no serviço .[#toc-service-modifications] +===================================================== -Há uma série de serviços no contêiner DI que foram acrescentados por embutido ou por [sua extensão |#di-extensions]. As definições desses serviços podem ser modificadas na configuração. Por exemplo, para o serviço `application.application`, que é por padrão um objeto `Nette\Application\Application`, podemos alterar a classe: +O contêiner DI contém muitos serviços adicionados por [extensões |#extensions] internas ou [de usuário |#extensions]. Você pode modificar as definições desses serviços diretamente na configuração. Por exemplo, você pode alterar a classe do serviço `application.application`, que é convencionalmente `Nette\Application\Application`, para outra: ```neon services: @@ -413,9 +399,9 @@ services: alteration: true ``` -A bandeira `alteration` é informativa e diz que estamos apenas modificando um serviço existente. +O sinalizador `alteration` é informativo, indicando que estamos apenas modificando um serviço existente. -Também podemos acrescentar uma configuração: +Também podemos complementar a configuração: ```neon services: @@ -426,7 +412,7 @@ services: - '$onStartup[]' = [@resource, init] ``` -Ao reescrever um serviço, podemos querer remover os argumentos originais, itens de configuração ou tags, que é para isso que serve `reset`: +Ao substituir um serviço, talvez você queira remover argumentos, itens de configuração ou tags originais, e é aí que o `reset` se torna útil: ```neon services: @@ -439,7 +425,7 @@ services: - tags ``` -Um serviço adicionado por extensão também pode ser removido do container: +Se quiser remover um serviço adicionado por uma extensão, você pode fazer isso da seguinte forma: ```neon services: diff --git a/dependency-injection/ro/services.texy b/dependency-injection/ro/services.texy index 5651246252..5332833006 100644 --- a/dependency-injection/ro/services.texy +++ b/dependency-injection/ro/services.texy @@ -2,32 +2,32 @@ Definiții ale serviciilor ************************* .[perex] -Configurația este locul în care se plasează definițiile serviciilor personalizate. Acest lucru se face în secțiunea `services`. +Configurația este locul în care instruim containerul DI cu privire la modul de asamblare a serviciilor individuale și la modul de conectare a acestora cu alte dependențe. Nette oferă o modalitate foarte clară și elegantă de a realiza acest lucru. -De exemplu, astfel creăm un serviciu numit `database`, care va fi o instanță a clasei `PDO`: +Secțiunea `services` din fișierul de configurare NEON este locul în care definim serviciile noastre personalizate și configurațiile lor. Să analizăm un exemplu simplu de definire a unui serviciu numit `database`, care reprezintă o instanță a clasei `PDO`: ```neon services: database: PDO('sqlite::memory:') ``` -Denumirea serviciilor este utilizată pentru a ne permite să le [referim |#Referencing Services] la acestea. În cazul în care un serviciu nu este menționat, nu este necesar să îl denumim. Prin urmare, folosim doar un punct în loc de un nume: +Această configurație are ca rezultat următoarea metodă factory în [containerul DI |container]: -```neon -services: - - PDO('sqlite::memory:') # serviciu anonim +```php +public function createServiceDatabase(): PDO +{ + return new PDO('sqlite::memory:'); +} ``` -O intrare pe o singură linie poate fi împărțită în mai multe linii pentru a permite adăugarea de chei suplimentare, cum ar fi [configurare |#setup]. Pseudonimul pentru tasta `create:` este `factory:`. +Numele serviciilor ne permit să facem referire la acestea în alte părți ale fișierului de configurare, folosind formatul `@serviceName`. Dacă nu este nevoie să denumim serviciul, putem folosi pur și simplu un punct: ```neon services: - database: - create: PDO('sqlite::memory:') - setup: ... + - PDO('sqlite::memory:') ``` -Apoi, recuperăm serviciul din containerul DI folosind metoda `getService()` după nume sau, mai bine, metoda `getByType()` după tip: +Pentru a prelua un serviciu din containerul DI, putem utiliza metoda `getService()` cu numele serviciului ca parametru sau metoda `getByType()` cu tipul serviciului: ```php $database = $container->getService('database'); @@ -35,236 +35,114 @@ $database = $container->getByType(PDO::class); ``` -Crearea unui serviciu .[#toc-creating-a-service] -================================================ +Crearea de servicii .[#toc-service-creation] +============================================ -Cel mai adesea, creăm un serviciu prin simpla creare a unei instanțe a unei clase: +Cel mai adesea, creăm un serviciu prin simpla instanțiere a unei clase specifice. De exemplu: ```neon services: database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` -Ceea ce va genera o metodă factory în [containerul DI |container]: - -```php -public function createServiceDatabase(): PDO -{ - return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret'); -} -``` - -Alternativ, o cheie `arguments` poate fi utilizată pentru a transmite [argumente |#Arguments]: +Dacă trebuie să extindem configurația cu chei suplimentare, definiția poate fi extinsă în mai multe linii: ```neon services: database: - create: PDO - arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] -``` - -O metodă statică poate crea, de asemenea, un serviciu: - -```neon -services: - database: My\Database::create(root, secret) + create: PDO('sqlite::memory:') + setup: ... ``` -Corespunde codului PHP: +Cheia `create` are un pseudonim `factory`, ambele versiuni sunt comune în practică. Cu toate acestea, recomandăm utilizarea `create`. -```php -public function createServiceDatabase(): PDO -{ - return My\Database::create('root', 'secret'); -} -``` - -O metodă statică `My\Database::create()` se presupune că are o valoare de returnare definită pe care containerul DI trebuie să o cunoască. Dacă nu o are, scriem tipul în configurație: +Argumentele constructorului sau metoda de creare pot fi scrise alternativ în cheia `arguments`: ```neon services: database: - create: My\Database::create(root, secret) - type: PDO + create: PDO + arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] ``` -Nette DI vă oferă facilități de exprimare extrem de puternice pentru a scrie aproape orice. De exemplu, pentru a face [referire |#Referencing Services] la un alt serviciu și a apela metoda acestuia. Pentru simplificare, se folosește `::` în loc de `->`. +Serviciile nu trebuie să fie create doar prin simpla instanțiere a unei clase; ele pot rezulta, de asemenea, din apelarea unor metode statice sau a unor metode ale altor servicii: ```neon services: - routerFactory: App\Router\Factory + database: DatabaseFactory::create() router: @routerFactory::create() ``` -Corespunde codului PHP: +Rețineți că, pentru simplificare, în loc de `->`, folosim `::`, a se vedea [expresia înseamnă |#expression means]. Aceste metode fabrică sunt generate: ```php -public function createServiceRouterFactory(): App\Router\Factory +public function createServiceDatabase(): PDO { - return new App\Router\Factory; + return DatabaseFactory::create(); } -public function createServiceRouter(): Router +public function createServiceRouter(): RouteList { return $this->getService('routerFactory')->create(); } ``` -Apelurile la metode pot fi înlănțuite ca în PHP: +Containerul DI trebuie să cunoască tipul serviciului creat. Dacă creăm un serviciu folosind o metodă care nu are un tip de returnare specificat, trebuie să menționăm explicit acest tip în configurație: ```neon services: - foo: FooFactory::build()::get() -``` - -Corespunde codului PHP: - -```php -public function createServiceFoo() -{ - return FooFactory::build()->get(); -} + database: + create: DatabaseFactory::create() + type: PDO ``` Argumente .[#toc-arguments] =========================== -Parametrii numiți pot fi utilizați și pentru a transmite argumente: +Trecem argumente către constructori și metode într-o manieră foarte asemănătoare cu cea din PHP obișnuit: ```neon services: - database: PDO( - 'mysql:host=127.0.0.1;dbname=test' # pozițional - username: root # numit - password: secret # numit - ) -``` - -Utilizarea virgulelor este opțională atunci când argumentele sunt împărțite pe mai multe linii. - -Bineînțeles, putem folosi și [alte servicii |#Referencing Services] sau [parametri |configuration#parameters] ca argumente: - -```neon -services: - - Foo(@anotherService, %appDir%) -``` - -Corespunde codului PHP: - -```php -public function createService01(): Foo -{ - return new Foo($this->getService('anotherService'), '...'); -} + database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` -Dacă primul argument este [autowired |autowiring] și doriți să îl specificați pe al doilea, omiteți-l pe primul cu `_` character, for example `Foo(_, %appDir%)`. Sau, mai bine, treceți doar al doilea argument ca parametru numit, de exemplu `Foo(path: %appDir%)`. - -Nette DI și formatul NEON vă oferă facilități expresive extrem de puternice pentru a scrie aproape orice. Astfel, un argument poate fi un obiect nou creat, puteți apela metode statice, metode ale altor servicii sau chiar funcții globale folosind o notație specială: +Pentru o mai bună lizibilitate, putem lista argumentele pe linii separate. În acest format, utilizarea virgulelor este opțională: ```neon services: - analyser: My\Analyser( - FilesystemIterator(%appDir%) # creați un obiect - DateTime::createFromFormat('Y-m-d') # apelați metoda statică - @anotherService # trecerea unui alt serviciu - @http.request::getRemoteAddress() # apelarea unei alte metode de serviciu - ::getenv(NetteMode) # apelarea unei funcții globale + database: PDO( + 'mysql:host=127.0.0.1;dbname=test' + root + secret ) ``` -Corespunde codului PHP: - -```php -public function createServiceAnalyser(): My\Analyser -{ - return new My\Analyser( - new FilesystemIterator('...'), - DateTime::createFromFormat('Y-m-d'), - $this->getService('anotherService'), - $this->getService('http.request')->getRemoteAddress(), - getenv('NetteMode') - ); -} -``` - - -Funcții speciale .[#toc-special-functions] ------------------------------------------- - -Puteți utiliza, de asemenea, funcții speciale în argumente pentru a transforma sau nega valori: - -- `not(%arg%)` negarea -- `bool(%arg%)` cast fără pierderi în bool -- `int(%arg%)` lossless cast to int -- `float(%arg%)` lossless cast to float -- `string(%arg%)` lossless cast to string +Puteți, de asemenea, să denumiți argumentele, ceea ce vă permite să nu vă faceți griji cu privire la ordinea lor: ```neon services: - - Foo( - id: int(::getenv('ProjectId')) - productionMode: not(%debugMode%) + database: PDO( + username: root + password: secret + dsn: 'mysql:host=127.0.0.1;dbname=test' ) ``` -Rescrierea fără pierderi diferă de rescrierea normală din PHP, de exemplu, folosind `(int)`, prin faptul că aruncă o excepție pentru valorile nenumerice. - -Mai multe servicii pot fi trecute ca argumente. Un tablou al tuturor serviciilor de un anumit tip (de exemplu, clasă sau interfață) este creat de funcția `typed()`. Funcția va omite serviciile care au cablarea automată dezactivată și pot fi specificate mai multe tipuri separate prin virgulă. +Dacă doriți să omiteți anumite argumente și să folosiți valorile lor implicite sau să introduceți un serviciu prin [autocablare |autowiring], utilizați un semn de subliniere: ```neon services: - - BarsDependent( typed(Bar) ) -``` - -De asemenea, puteți transmite automat o matrice de servicii utilizând [autowiring |autowiring#Collection of Services]. - -O matrice a tuturor serviciilor cu o anumită [etichetă |#tags] este creată de funcția `tagged()`. Se pot specifica mai multe etichete separate prin virgulă. - -```neon -services: - - LoggersDependent( tagged(logger) ) + foo: Foo(_, %appDir%) ``` - -Servicii de referință .[#toc-referencing-services] -================================================== - -Serviciile individuale sunt referite folosind caracterul `@` and name, so for example `@database`: - -```neon -services: - - create: Foo(@database) - setup: - - setCacheStorage(@cache.storage) -``` - -Corespunde codului PHP: - -```php -public function createService01(): Foo -{ - $service = new Foo($this->getService('database')); - $service->setCacheStorage($this->getService('cache.storage')); - return $service; -} -``` - -Chiar și serviciile anonime pot fi referite folosind un callback, trebuie doar să specificați tipul lor (clasă sau interfață) în loc de numele lor. Cu toate acestea, acest lucru nu este de obicei necesar din cauza [cablării automate |autowiring]. - -```neon -services: - - create: Foo(@Nette\Database\Connection) - setup: - - setCacheStorage(@cache.storage) -``` +Argumentele pot fi servicii, parametri și multe altele, a se vedea [mijloacele de exprimare |#expression means]. Configurare .[#toc-setup] ========================= -În secțiunea de configurare, enumerăm metodele care trebuie apelate la crearea serviciului: +În secțiunea `setup`, se definesc metodele care trebuie apelate la crearea serviciului. ```neon services: @@ -274,7 +152,7 @@ services: - setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) ``` -Corespunde codului PHP: +În PHP, acest lucru ar arăta astfel: ```php public function createServiceDatabase(): PDO @@ -285,8 +163,7 @@ public function createServiceDatabase(): PDO } ``` -Proprietățile pot fi, de asemenea, setate. Adăugarea unui element la o matrice este, de asemenea, acceptată și trebuie scrisă între ghilimele pentru a nu intra în conflict cu sintaxa NEON: - +În plus față de apelurile la metode, puteți, de asemenea, să transmiteți valori la proprietăți. Adăugarea unui element la o matrice este, de asemenea, acceptată, dar trebuie să îl includeți între ghilimele pentru a evita coliziunea cu sintaxa NEON: ```neon services: @@ -297,7 +174,7 @@ services: - '$onClick[]' = [@bar, clickHandler] ``` -Corespunde codului PHP: +În PHP, acest lucru s-ar traduce prin: ```php public function createServiceFoo(): Foo @@ -309,8 +186,7 @@ public function createServiceFoo(): Foo } ``` -Cu toate acestea, metodele statice sau metodele altor servicii pot fi, de asemenea, apelate în configurare. Le transmitem serviciul real ca `@self`: - +În configurare, puteți apela și metode statice sau metode ale altor servicii. Dacă aveți nevoie să treceți serviciul curent ca argument, utilizați `@self`: ```neon services: @@ -321,7 +197,7 @@ services: - @anotherService::setFoo(@self) ``` -Corespunde codului PHP: +Rețineți că, pentru simplificare, în loc de `->`, folosim `::`, a se vedea [expresia înseamnă |#expression means]. Aceasta generează următoarea metodă de fabrică: ```php public function createServiceFoo(): Foo @@ -334,23 +210,133 @@ public function createServiceFoo(): Foo ``` +Mijloace de exprimare .[#toc-expression-means] +============================================== + +Nette DI ne oferă capacități de exprimare excepțional de bogate, permițându-ne să articulăm aproape orice. În fișierele de configurare, putem utiliza [parametri |configuration#parameters]: + +```neon +# parametru +%wwwDir% + +# valoarea unui parametru sub o cheie de parametru +%mailer.user% + +# parametru în cadrul unui șir de caractere +'%wwwDir%/images' +``` + +De asemenea, putem crea obiecte, apela metode și funcții: + +```neon +# creați un obiect +DateTime() + +# apelarea unei metode statice +Collator::create(%locale%) + +# apelarea unei funcții PHP +::getenv(DB_USER) +``` + +Faceți referire la servicii fie prin numele lor, fie prin tipul lor: + +```neon +# serviciu după nume +@database + +# serviciu după tip +@Nette\Database\Connection +``` + +Utilizați constante: + +```neon +# constantă de clasă +FilesystemIterator::SKIP_DOTS + +# constantă globală obținută prin funcția PHP constant() +::constant(PHP_VERSION) +``` + +Apelurile la metode pot fi înlănțuite, la fel ca în PHP. Pentru simplitate, în loc de `->`, folosim `::`: + +```neon +DateTime()::format('Y-m-d') +# PHP: (new DateTime())->format('Y-m-d') + +@http.request::getUrl()::getHost() +# PHP: $this->getService('http.request')->getUrl()->getHost() +``` + +Aceste expresii pot fi utilizate oriunde la [crearea serviciilor |#Service Creation], în [argumente |#Arguments], în secțiunea de [configurare |#setup] sau în [parametri |configuration#parameters]: + +```neon +parameters: + ipAddress: @http.request::getRemoteAddress() + +services: + database: + create: DatabaseFactory::create( @anotherService::getDsn() ) + setup: + - initialize( ::getenv('DB_USER') ) +``` + + +Funcții speciale .[#toc-special-functions] +------------------------------------------ + +În cadrul fișierelor de configurare, puteți utiliza aceste funcții speciale: + +- `not()` pentru negarea valorilor +- `bool()`, `int()`, `float()`, `string()` pentru turnarea fără pierderi a tipurilor +- `typed()` pentru a genera o matrice a tuturor serviciilor de un tip specificat +- `tagged()` pentru a crea o matrice a tuturor serviciilor cu o anumită etichetă + +```neon +services: + - Foo( + id: int(::getenv('ProjectId')) + productionMode: not(%debugMode%) + ) +``` + +În comparație cu tipizarea convențională în PHP, cum ar fi `(int)`, tipizarea fără pierderi va arunca o excepție pentru valorile nenumerice. + +Funcția `typed()` creează o matrice cu toate serviciile de un anumit tip (clasă sau interfață). Aceasta exclude serviciile cu cablarea automată dezactivată. Se pot specifica mai multe tipuri, separate prin virgule. + +```neon +services: + - BarsDependent( typed(Bar) ) +``` + +De asemenea, puteți transmite automat o matrice de servicii de un anumit tip ca argument, utilizând [autowiring |autowiring#Collection of Services]. + +Funcția `tagged()` creează o matrice a tuturor serviciilor cu o etichetă specificată. Pot fi enumerate mai multe etichete, separate prin virgulă. + +```neon +services: + - LoggersDependent( tagged(logger) ) +``` + + Cablare automată .[#toc-autowiring] =================================== -Cheia autowired poate fi utilizată pentru a exclude un serviciu de la autowiring sau pentru a influența comportamentul acestuia. Pentru mai multe informații, consultați [capitolul despre autowiring |autowiring]. +Tasta `autowired` vă permite să modificați comportamentul de cablare automată pentru un anumit serviciu. Pentru mai multe detalii, consultați [capitolul privind cablarea automată |autowiring]. ```neon services: foo: create: Foo - autowired: false # foo este eliminat din autocablarea + autowired: false # serviciul foo este exclus de la cablarea automată ``` Etichete .[#toc-tags] ===================== -Informațiile despre utilizatori pot fi adăugate la serviciile individuale sub formă de etichete: +Etichetele sunt utilizate pentru a adăuga informații suplimentare la servicii. Puteți atribui una sau mai multe etichete unui serviciu: ```neon services: @@ -360,7 +346,7 @@ services: - cached ``` -Etichetele pot avea, de asemenea, o valoare: +Etichetele pot avea și valori: ```neon services: @@ -370,26 +356,26 @@ services: logger: monolog.logger.event ``` -O matrice de servicii cu anumite etichete poate fi transmisă ca argument cu ajutorul funcției `tagged()`. De asemenea, se pot specifica mai multe etichete separate prin virgulă. +Pentru a prelua toate serviciile cu anumite etichete, puteți utiliza funcția `tagged()`: ```neon services: - LoggersDependent( tagged(logger) ) ``` -Numele serviciilor pot fi obținute din containerul DI folosind metoda `findByTag()`: +În containerul DI, puteți obține numele tuturor serviciilor cu o anumită etichetă utilizând metoda `findByTag()`: ```php $names = $container->findByTag('logger'); // $names este o matrice care conține numele serviciului și valoarea etichetei. -// adică ['foo' => 'monolog.logger.event', ...] +// de exemplu, ['foo' => 'monolog.logger.event', ...] ``` Modul de injectare .[#toc-inject-mode] ====================================== -Indicatorul `inject: true` este utilizat pentru a activa trecerea dependențelor prin intermediul variabilelor publice cu adnotarea [inject |best-practices:inject-method-attribute#Inject Attributes] și metodele [inject*() |best-practices:inject-method-attribute#inject Methods]. +Utilizarea indicatorului `inject: true` activează trecerea dependențelor prin intermediul variabilelor publice cu adnotarea [inject |best-practices:inject-method-attribute#Inject Attributes] și metodele [inject*() |best-practices:inject-method-attribute#inject Methods]. ```neon services: @@ -401,10 +387,10 @@ services: În mod implicit, `inject` este activat numai pentru prezentatori. -Modificarea serviciilor .[#toc-modification-of-services] +Modificări ale serviciului .[#toc-service-modifications] ======================================================== -Există o serie de servicii în containerul DI care au fost adăugate prin încorporare sau prin [extensia dumneavoastră |#di-extensions]. Definițiile acestor servicii pot fi modificate în configurație. De exemplu, pentru serviciul `application.application`, care este în mod implicit un obiect `Nette\Application\Application`, putem modifica clasa: +Containerul DI conține multe servicii adăugate fie prin [extensii |#extensions] încorporate, fie prin [extensii de utilizator |#extensions]. Puteți modifica definițiile acestor servicii direct în configurație. De exemplu, puteți schimba clasa serviciului `application.application`, care este în mod convențional `Nette\Application\Application`, în altceva: ```neon services: @@ -413,9 +399,9 @@ services: alteration: true ``` -Steagul `alteration` este informativ și spune că nu facem decât să modificăm un serviciu existent. +Semnul `alteration` este informativ, indicând că nu facem decât să modificăm un serviciu existent. -De asemenea, putem adăuga o configurare: +De asemenea, putem completa configurația: ```neon services: @@ -426,7 +412,7 @@ services: - '$onStartup[]' = [@resource, init] ``` -Atunci când rescriem un serviciu, este posibil să dorim să eliminăm argumentele, elementele de configurare sau etichetele inițiale, pentru aceasta existând `reset`: +Atunci când suprascrieți un serviciu, este posibil să doriți să eliminați argumentele, elementele de configurare sau etichetele originale, și aici `reset` este util: ```neon services: @@ -439,7 +425,7 @@ services: - tags ``` -Un serviciu adăugat prin extensie poate fi, de asemenea, eliminat din container: +Dacă doriți să eliminați un serviciu adăugat de o extensie, puteți face acest lucru în felul următor: ```neon services: diff --git a/dependency-injection/ru/services.texy b/dependency-injection/ru/services.texy index 5566611a0f..93be5ce8ef 100644 --- a/dependency-injection/ru/services.texy +++ b/dependency-injection/ru/services.texy @@ -2,32 +2,32 @@ ******************** .[perex] -Конфигурация — это место, где мы размещаем определения пользовательских сервисов. Делается это в секции `services`. +Конфигурация - это место, где мы указываем DI-контейнеру, как собирать отдельные сервисы и как связывать их с другими зависимостями. Nette предоставляет очень понятный и элегантный способ достижения этой цели. -Например, вот как мы создаем сервис с именем `database`, который будет экземпляром класса `PDO`: +Секция `services` в конфигурационном файле NEON - это место, где мы определяем наши пользовательские сервисы и их конфигурации. Рассмотрим простой пример определения сервиса с именем `database`, который представляет собой экземпляр класса `PDO`: ```neon services: database: PDO('sqlite::memory:') ``` -Именование служб используется для того, чтобы мы могли [ссылаться|#Referencing-Services] на них. Если на сервис не ссылаются, нет необходимости давать ему имя. Поэтому вместо имени мы просто используем двоеточие: +Эта конфигурация приводит к появлению следующего фабричного метода в [контейнере DI |container]: -```neon -services: - - PDO('sqlite::memory:') # анонимный сервис +```php +public function createServiceDatabase(): PDO +{ + return new PDO('sqlite::memory:'); +} ``` -Однострочная запись может быть разбита на несколько строк, чтобы можно было добавить дополнительные ключи, например [#setup]. Псевдоним для ключа `create:` - `factory:`. +Имена сервисов позволяют ссылаться на них в других частях конфигурационного файла, используя формат `@serviceName`. Если нет необходимости присваивать сервису имя, можно просто использовать пулевую точку: ```neon services: - database: - create: PDO('sqlite::memory:') - setup: ... + - PDO('sqlite::memory:') ``` -Затем мы получаем сервис из контейнера DI, используя метод `getService()` по имени, или, что ещё лучше, метод `getByType()` по типу: +Для получения сервиса из DI-контейнера можно использовать метод `getService()` с именем сервиса в качестве параметра или метод `getByType()` с типом сервиса: ```php $database = $container->getService('database'); @@ -35,236 +35,114 @@ $database = $container->getByType(PDO::class); ``` -Создание сервиса .[#toc-creating-a-service] -=========================================== +Создание сервиса .[#toc-service-creation] +========================================= -Чаще всего мы создаем сервис, просто создавая экземпляр класса: +Чаще всего мы создаем сервис, просто инстанцируя определенный класс. Например: ```neon services: database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` -Что создаст фабричный метод в [DI-контейнере|container]: - -```php -public function createServiceDatabase(): PDO -{ - return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret'); -} -``` - -Альтернативно, ключ `arguments` может быть использован для передачи [аргументов|#Arguments]: +Если нам необходимо расширить конфигурацию дополнительными ключами, то определение может быть разложено на несколько строк: ```neon services: database: - create: PDO - arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] -``` - -Статический метод также может создать сервис: - -```neon -services: - database: My\Database::create(root, secret) + create: PDO('sqlite::memory:') + setup: ... ``` -Это эквивалентно коду PHP: +Ключ `create` имеет псевдоним `factory`, оба варианта распространены на практике. Однако мы рекомендуем использовать `create`. -```php -public function createServiceDatabase(): PDO -{ - return My\Database::create('root', 'secret'); -} -``` - -Предполагается, что статический метод `My\Database::create()` имеет определенное возвращаемое значение, которое должен знать контейнер DI. Если у него его нет, мы записываем тип в конфигурацию: +В качестве альтернативы аргументы конструктора или метод создания могут быть записаны в ключе `arguments`: ```neon services: database: - create: My\Database::create(root, secret) - type: PDO + create: PDO + arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] ``` -Nette DI предоставляет вам чрезвычайно мощные средства выражения, позволяющие написать практически всё, что угодно. Например, чтобы [обратиться|#Referencing-Services] к другой службе и вызвать её метод. Для простоты вместо `->` используется `::`. +Сервисы не обязательно должны создаваться только простым инстанцированием класса; они также могут возникать в результате вызова статических методов или методов других сервисов: ```neon services: - routerFactory: App\Router\Factory + database: DatabaseFactory::create() router: @routerFactory::create() ``` -Это эквивалентно коду PHP: +Заметим, что для простоты вместо `->`, мы используем `::`, см. [выражения |#expression means]. Эти фабричные методы генерируются: ```php -public function createServiceRouterFactory(): App\Router\Factory +public function createServiceDatabase(): PDO { - return new App\Router\Factory; + return DatabaseFactory::create(); } -public function createServiceRouter(): Router +public function createServiceRouter(): RouteList { return $this->getService('routerFactory')->create(); } ``` -Вызовы методов можно объединять в цепочки, как в PHP: +DI-контейнер должен знать тип создаваемого сервиса. Если мы создаем сервис с помощью метода, который не имеет заданного возвращаемого типа, то мы должны явно указать этот тип в конфигурации: ```neon services: - foo: FooFactory::build()::get() -``` - -Это эквивалентно коду PHP: - -```php -public function createServiceFoo() -{ - return FooFactory::build()->get(); -} + database: + create: DatabaseFactory::create() + type: PDO ``` Аргументы .[#toc-arguments] =========================== -Именованные параметры также могут использоваться для передачи аргументов: +Передача аргументов конструкторам и методам осуществляется аналогично обычному PHP: ```neon services: - database: PDO( - 'mysql:host=127.0.0.1;dbname=test' # позиционный - username: root # именованный - password: secret # именованный - ) -``` - -Использование запятых необязательно при разбиении аргументов на несколько строк. - -Конечно, мы также можем использовать [другие сервисы|#Referencing-Services] или [параметры|configuration#Parameters] в качестве аргументов: - -```neon -services: - - Foo(@anotherService, %appDir%) -``` - -Соответствует коду PHP: - -```php -public function createService01(): Foo -{ - return new Foo($this->getService('anotherService'), '...'); -} + database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` -Если первый аргумент - [автомонтируемый|autowiring], а вы хотите указать второй, опустите первый с помощью символа `_`, например `Foo(_, %appDir%)`. Или, что ещё лучше, передавайте только второй аргумент в качестве именованного параметра, например: `Foo(path: %appDir%)`. - -Nette DI и формат NEON дают вам чрезвычайно мощные выразительные средства, позволяющие написать практически всё, что угодно. Таким образом, аргументом может быть вновь созданный объект, вы можете вызывать статические методы, методы других сервисов или даже глобальные функции, используя специальную нотацию: +Для лучшей читабельности мы можем перечислять аргументы в отдельных строках. В этом формате использование запятых необязательно: ```neon services: - analyser: My\Analyser( - FilesystemIterator(%appDir%) # создаем объект - DateTime::createFromFormat('Y-m-d') # вызываем статический метод - @anotherService # передаём другой сервис - @http.request::getRemoteAddress() # вызываем метод другого сервиса - ::getenv(NetteMode) # вызываем глобальную функцию + database: PDO( + 'mysql:host=127.0.0.1;dbname=test' + root + secret ) ``` -Соответствует коду PHP: - -```php -public function createServiceAnalyser(): My\Analyser -{ - return new My\Analyser( - new FilesystemIterator('...'), - DateTime::createFromFormat('Y-m-d'), - $this->getService('anotherService'), - $this->getService('http.request')->getRemoteAddress(), - getenv('NetteMode') - ); -} -``` - - -Специальные функции .[#toc-special-functions] ---------------------------------------------- - -Вы также можете использовать специальные функции в аргументах для приведения или отрицания значений: - -- `not(%arg%)` отрицание -- `bool(%arg%)` приведение к bool без потерь -- `int(%arg%)` приведение к int без потерь -- `float(%arg%)` приведение к плавающему состоянию без потерь -- `string(%arg%)` приведение к строке без потерь +Можно также назвать аргументы, и тогда можно не заботиться об их порядке: ```neon services: - - Foo( - id: int(::getenv('ProjectId')) - productionMode: not(%debugMode%) + database: PDO( + username: root + password: secret + dsn: 'mysql:host=127.0.0.1;dbname=test' ) ``` -Переписывание без потерь отличается от обычного переписывания в PHP, например используя `(int)`, в том, что оно выбрасывает исключение для нечисловых значений. - -В качестве аргументов можно передавать несколько сервисов. Массив всех сервисов определенного типа (т. е. класса или интерфейса) создается функцией `typed()`. Функция будет опускать сервисы, у которых отключено автоподключение, при этом можно указать несколько типов, разделенных запятой. +Если вы хотите опустить некоторые аргументы и использовать их значения по умолчанию или вставить функцию с помощью [автоподключения |autowiring], используйте символ подчеркивания: ```neon services: - - BarsDependent( typed(Bar) ) + foo: Foo(_, %appDir%) ``` -Вы также можете передать массив сервисов автоматически, используя [автосвязывание|autowiring#Collection-of-Services]. - -Массив всех сервисов с определенным [тегом|#Tags] создается функцией `tagged()`. Можно указать несколько тегов, разделенных запятой. - -```neon -services: - - LoggersDependent( tagged(logger) ) -``` +Аргументами могут быть сервисы, параметры и многое другое, см. [средства выражения |#expression means]. -Ссылки на сервисы .[#toc-referencing-services] -============================================== +Настройка .[#toc-setup] +======================= -Ссылки на отдельные сервисы используются с помощью символа `@` и имени, например `@database`: - -```neon -services: - - create: Foo(@database) - setup: - - setCacheStorage(@cache.storage) -``` - -Соответствует коду PHP: - -```php -public function createService01(): Foo -{ - $service = new Foo($this->getService('database')); - $service->setCacheStorage($this->getService('cache.storage')); - return $service; -} -``` - -Даже на анонимные сервисы можно ссылаться с помощью обратного вызова, просто укажите их тип (класс или интерфейс) вместо имени. Однако обычно в этом нет необходимости из-за [автосвязывания|autowiring]. - -```neon -services: - - create: Foo(@Nette\Database\Connection) - setup: - - setCacheStorage(@cache.storage) -``` - - -Setup -===== - -В секции `setup` мы перечисляем методы, которые будут вызываться при создании сервиса: +В разделе `setup` мы определяем методы, которые должны вызываться при создании сервиса. ```neon services: @@ -274,7 +152,7 @@ services: - setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) ``` -Соответствует коду PHP: +На языке PHP это выглядит следующим образом: ```php public function createServiceDatabase(): PDO @@ -285,8 +163,7 @@ public function createServiceDatabase(): PDO } ``` -Также можно установить свойства. Добавление элемента в массив также поддерживается, и его следует писать в кавычках, чтобы не конфликтовать с синтаксисом NEON: - +Помимо вызовов методов, можно передавать значения в свойства. Добавление элемента в массив также поддерживается, но его необходимо заключать в кавычки, чтобы избежать столкновения с синтаксисом NEON: ```neon services: @@ -297,7 +174,7 @@ services: - '$onClick[]' = [@bar, clickHandler] ``` -Соответствует коду PHP: +В PHP это будет выглядеть так: ```php public function createServiceFoo(): Foo @@ -309,8 +186,7 @@ public function createServiceFoo(): Foo } ``` -Однако статические методы или методы других сервисов также могут быть вызваны в настройке. Мы передаем им фактический сервис как `@self`: - +В настройке можно также вызывать статические методы или методы других сервисов. Если необходимо передать текущий сервис в качестве аргумента, используйте `@self`: ```neon services: @@ -321,7 +197,7 @@ services: - @anotherService::setFoo(@self) ``` -Соответствует коду PHP: +Обратите внимание, что для простоты вместо `->` мы используем `::`, см. [средства выражения |#expression means]. В результате формируется следующий фабричный метод: ```php public function createServiceFoo(): Foo @@ -334,23 +210,133 @@ public function createServiceFoo(): Foo ``` -Автосвязывание .[#toc-autowiring] -================================= +Средства выражения .[#toc-expression-means] +=========================================== + +Nette DI предоставляет нам исключительно богатые возможности выражения, позволяющие сформулировать практически все, что угодно. В конфигурационных файлах мы можем использовать [параметры |configuration#parameters]: + +```neon +# параметр +%wwwDir% + +# значение под ключом параметра +%mailer.user% + +# параметр в строке +'%wwwDir%/images' +``` + +Мы также можем создавать объекты, вызывать методы и функции: + +```neon +# создать объект +DateTime() + +# вызов статического метода +Collator::create(%locale%) + +# вызвать функцию PHP +::getenv(DB_USER) +``` + +Ссылайтесь на сервисы либо по их имени, либо по типу: + +```neon +# услуга по названию +@database + +# услуга по типу +@Nette\Database\Connection +``` + +Использовать константы: + +```neon +# константа класса +FilesystemIterator::SKIP_DOTS + +# глобальная константа, получаемая с помощью PHP-функции constant() +::constant(PHP_VERSION) +``` + +Вызовы методов, как и в PHP, можно объединять в цепочки. Для простоты вместо `->` мы используем `::`: + +```neon +DateTime()::format('Y-m-d') +# PHP: (new DateTime())->format('Y-m-d') + +@http.request::getUrl()::getHost() +# PHP: $this->getService('http.request')->getUrl()->getHost() +``` + +Эти выражения можно использовать в любом месте при [создании сервисов |#Service Creation], в [аргументах |#Arguments], в секции [настройки |#setup] или [параметрах |configuration#parameters]: + +```neon +parameters: + ipAddress: @http.request::getRemoteAddress() + +services: + database: + create: DatabaseFactory::create( @anotherService::getDsn() ) + setup: + - initialize( ::getenv('DB_USER') ) +``` + + +Специальные функции .[#toc-special-functions] +--------------------------------------------- + +В конфигурационных файлах можно использовать эти специальные функции: + +- `not()` для отрицания значений +- `bool()`, `int()`, `float()`, `string()` для приведения типов без потерь +- `typed()` для создания массива всех сервисов заданного типа +- `tagged()` для создания массива всех сервисов с заданным тегом + +```neon +services: + - Foo( + id: int(::getenv('ProjectId')) + productionMode: not(%debugMode%) + ) +``` + +По сравнению с обычным приведением типов в PHP, например, `(int)`, при приведении типов без потерь будет возникать исключение для нечисловых значений. + +Функция `typed()` создает массив всех сервисов определенного типа (класса или интерфейса). При этом исключаются сервисы с выключенным автоподключением. Можно указать несколько типов, разделяя их запятыми. + +```neon +services: + - BarsDependent( typed(Bar) ) +``` + +Также можно автоматически передать массив сервисов определенного типа в качестве аргумента при использовании [автоподключения |autowiring#Collection of Services]. + +Функция `tagged()` создает массив всех сервисов с указанным тегом. Можно перечислить несколько тегов, разделяя их запятыми. + +```neon +services: + - LoggersDependent( tagged(logger) ) +``` + + +Автоэлектрика .[#toc-autowiring] +================================ -Ключ `autowired` можно использовать для исключения сервиса из автосвязывания или для влияния на его поведение. Более подробную информацию см. в главе [Автосвязывание|autowiring]. +Ключ `autowired` позволяет модифицировать поведение автоподключения для конкретного сервиса. Более подробная информация приведена в [главе, посвященной автоподключению |autowiring]. ```neon services: foo: create: Foo - autowired: false # foo удаляется из автосвязывания + autowired: false # служба foo исключена из автоподключения ``` Теги .[#toc-tags] ================= -Информация о пользователе может быть добавлена к отдельным сервисам в виде тегов: +Теги используются для добавления дополнительной информации к сервисам. Вы можете назначить сервису один или несколько тегов: ```neon services: @@ -360,7 +346,7 @@ services: - cached ``` -Теги также могут иметь значение: +Теги также могут иметь значения: ```neon services: @@ -370,26 +356,26 @@ services: logger: monolog.logger.event ``` -Массив сервисов с определенными тегами может быть передан в качестве аргумента с помощью функции `tagged()`. Можно также указать несколько тегов, разделенных запятой. +Чтобы получить все услуги с определенными тегами, можно воспользоваться функцией `tagged()`: ```neon services: - LoggersDependent( tagged(logger) ) ``` -Имена служб можно получить из контейнера DI с помощью метода `findByTag()`: +В контейнере DI можно получить имена всех сервисов с определенным тегом с помощью метода `findByTag()`: ```php $names = $container->findByTag('logger'); // $names - массив, содержащий имя сервиса и значение тега -// например ['foo' => 'monolog.logger.event', ...] +// например, ['foo' => 'monolog.logger.event', ...]. ``` -Режим внедрения .[#toc-inject-mode] -=================================== +Режим инжекции .[#toc-inject-mode] +================================== -Флаг `inject: true` используется для активации передачи зависимостей через публичные переменные с помощью аннотации [inject |best-practices:inject-method-attribute#Inject Attributes] и методов [inject*() |best-practices:inject-method-attribute#inject Methods]. +Использование флага `inject: true` активизирует передачу зависимостей через публичные переменные с помощью аннотации [inject |best-practices:inject-method-attribute#Inject Attributes] и методов [inject*() |best-practices:inject-method-attribute#inject Methods]. ```neon services: @@ -398,13 +384,13 @@ services: inject: true ``` -По умолчанию `inject` активируется только для презентеров. +По умолчанию `inject` активизируется только для ведущих. -Модификация сервисов .[#toc-modification-of-services] -===================================================== +Модификации сервиса .[#toc-service-modifications] +================================================= -В контейнере DI есть ряд сервисов, которые были добавлены встроенным или [вашим расширением|#di-extension]. Определения этих сервисов могут быть изменены в конфигурации. Например, для сервиса `application.application`, который по умолчанию является объектом `Nette\Application\Application`, мы можем изменить класс: +Контейнер DI содержит множество сервисов, добавленных как встроенными, так и [пользовательскими расширениями |#extensions]. Определения этих сервисов можно изменять непосредственно в конфигурации. Например, можно изменить класс сервиса `application.application`, который условно называется `Nette\Application\Application`, на другой: ```neon services: @@ -413,9 +399,9 @@ services: alteration: true ``` -Флаг `alteration` является информативным и говорит о том, что мы просто изменяем существующий сервис. +Флаг `alteration` является информативным и указывает на то, что мы просто модифицируем существующий сервис. -Мы также можем добавить `setup`: +Мы также можем дополнить настройку: ```neon services: @@ -426,7 +412,7 @@ services: - '$onStartup[]' = [@resource, init] ``` -При перезаписи сервиса мы можем удалить исходные аргументы, элементы `setup` или теги, для которых `reset` является: +При перезаписи сервиса может потребоваться удалить исходные аргументы, элементы настройки или теги, и здесь пригодится `reset`: ```neon services: @@ -439,7 +425,7 @@ services: - tags ``` -Сервис, добавленный расширением, также может быть удален из контейнера: +Если необходимо удалить сервис, добавленный расширением, это можно сделать следующим образом: ```neon services: diff --git a/dependency-injection/sl/services.texy b/dependency-injection/sl/services.texy index fa55afbb89..d13e9b3505 100644 --- a/dependency-injection/sl/services.texy +++ b/dependency-injection/sl/services.texy @@ -2,32 +2,32 @@ Opredelitve storitev ******************** .[perex] -Konfiguracija je mesto, kamor postavimo opredelitve storitev po meri. To storimo v razdelku `services`. +Konfiguracija je mesto, kjer vsebniku DI naročimo, kako naj sestavi posamezne storitve in kako naj jih poveže z drugimi odvisnostmi. Nette ponuja zelo jasen in eleganten način za doseganje tega cilja. -Tako na primer ustvarimo storitev z imenom `database`, ki bo primerek razreda `PDO`: +V razdelku `services` v konfiguracijski datoteki NEON opredelimo svoje storitve po meri in njihove konfiguracije. Oglejmo si preprost primer opredelitve storitve z imenom `database`, ki predstavlja primerek razreda `PDO`: ```neon services: database: PDO('sqlite::memory:') ``` -Poimenovanje storitev se uporablja zato, da [se |#Referencing Services] lahko nanje [sklicujemo |#Referencing Services]. Če se na storitev ne sklicujemo, je ni treba poimenovati. Zato namesto imena uporabimo le točko: +Rezultat te konfiguracije je naslednja tovarniška metoda v [vsebniku DI |container]: -```neon -services: - - PDO('sqlite::memory:') # anonimna storitev +```php +public function createServiceDatabase(): PDO +{ + return new PDO('sqlite::memory:'); +} ``` -Enovrstični vnos lahko razdelimo v več vrstic, da lahko dodamo dodatne tipke, kot je [nastavitev |#setup]. Vzdevek za ključ `create:` je `factory:`. +Imena storitev nam omogočajo sklicevanje nanje v drugih delih konfiguracijske datoteke v obliki `@serviceName`. Če storitve ni treba poimenovati, lahko preprosto uporabimo točko: ```neon services: - database: - create: PDO('sqlite::memory:') - setup: ... + - PDO('sqlite::memory:') ``` -Storitev nato prikličemo iz vsebnika DI z metodo `getService()` po imenu ali, še bolje, z metodo `getByType()` po vrsti: +Za pridobitev storitve iz vsebnika DI lahko uporabimo metodo `getService()` z imenom storitve kot parametrom ali metodo `getByType()` s tipom storitve: ```php $database = $container->getService('database'); @@ -35,236 +35,114 @@ $database = $container->getByType(PDO::class); ``` -Ustvarjanje storitve .[#toc-creating-a-service] -=============================================== +Ustvarjanje storitev .[#toc-service-creation] +============================================= -Storitev najpogosteje ustvarimo tako, da preprosto ustvarimo primerek razreda: +Najpogosteje ustvarimo storitev tako, da instanciramo določen razred. Na primer: ```neon services: database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` -To ustvari tovarniško metodo v [vsebniku DI |container]: - -```php -public function createServiceDatabase(): PDO -{ - return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret'); -} -``` - -Za posredovanje [argumentov |#Arguments] se lahko uporabi tudi ključ `arguments`: +Če moramo konfiguracijo razširiti z dodatnimi ključi, lahko definicijo razširimo v več vrstic: ```neon services: database: - create: PDO - arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] -``` - -Statična metoda lahko ustvari tudi storitev: - -```neon -services: - database: My\Database::create(root, secret) + create: PDO('sqlite::memory:') + setup: ... ``` -Ustreza kodi PHP: +Ključ `create` ima vzdevek `factory`, obe različici sta v praksi pogosti. Vendar priporočamo uporabo ključa `create`. -```php -public function createServiceDatabase(): PDO -{ - return My\Database::create('root', 'secret'); -} -``` - -Predpostavlja se, da ima statična metoda `My\Database::create()` določeno povratno vrednost, ki jo mora vsebnik DI poznati. Če je nima, zapišemo tip v konfiguracijo: +Argumente konstruktorja ali metodo ustvarjanja lahko alternativno zapišete v ključu `arguments`: ```neon services: database: - create: My\Database::create(root, secret) - type: PDO + create: PDO + arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] ``` -Nette DI vam omogoča izjemno zmogljive izrazne zmogljivosti za zapisovanje skoraj vsega. Na primer za [sklicevanje na |#Referencing Services] drugo storitev in klic njene metode. Zaradi enostavnosti se namesto `->` uporablja `::`. +Storitve niso nujno ustvarjene samo z enostavno instanciacijo razreda; lahko so tudi posledica klica statičnih metod ali metod drugih storitev: ```neon services: - routerFactory: App\Router\Factory + database: DatabaseFactory::create() router: @routerFactory::create() ``` -Ustreza kodi PHP: +Upoštevajte, da zaradi enostavnosti namesto `->` uporabljamo `::`, glej [izrazna sredstva |#expression means]. Te tovarniške metode so ustvarjene: ```php -public function createServiceRouterFactory(): App\Router\Factory +public function createServiceDatabase(): PDO { - return new App\Router\Factory; + return DatabaseFactory::create(); } -public function createServiceRouter(): Router +public function createServiceRouter(): RouteList { return $this->getService('routerFactory')->create(); } ``` -klice metod je mogoče verižno povezati kot v PHP: +vsebnik DI mora poznati vrsto ustvarjene storitve. Če ustvarimo storitev z metodo, ki nima določene vrnitvene vrste, moramo to vrsto izrecno navesti v konfiguraciji: ```neon services: - foo: FooFactory::build()::get() -``` - -Ustreza kodi PHP: - -```php -public function createServiceFoo() -{ - return FooFactory::build()->get(); -} + database: + create: DatabaseFactory::create() + type: PDO ``` Argumenti .[#toc-arguments] =========================== -Poimenovane parametre lahko uporabite tudi za posredovanje argumentov: +Argumente konstruktorjem in metodam posredujemo na zelo podoben način kot v običajnem jeziku PHP: ```neon services: - database: PDO( - 'mysql:host=127.0.0.1;dbname=test' # pozicijski - username: root # poimenovani - password: secret # named - ) -``` - -Uporaba vejic ni obvezna, če se argumenti razdelijo v več vrstic. - -Seveda lahko kot argumente uporabimo tudi [druge storitve |#Referencing Services] ali [parametre |configuration#parameters]: - -```neon -services: - - Foo(@anotherService, %appDir%) -``` - -Ustreza kodi PHP: - -```php -public function createService01(): Foo -{ - return new Foo($this->getService('anotherService'), '...'); -} + database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` -Če je prvi argument [samodejen |autowiring] in želite navesti drugega, izpustite prvega z `_` character, for example `Foo(_, %appDir%)`. Ali še bolje, samo drugi argument predajte kot poimenovani parameter, npr. `Foo(path: %appDir%)`. - -Nette DI in format NEON vam omogočata izjemno močne izrazne možnosti za zapisovanje skoraj vsega. Tako je lahko argument novo ustvarjen objekt, s posebnim zapisom lahko kličete statične metode, metode drugih storitev ali celo globalne funkcije: +Za boljšo berljivost lahko argumente navedemo v ločenih vrsticah. V tej obliki je uporaba vejic neobvezna: ```neon services: - analyser: My\Analyser( - FilesystemIterator(%appDir%) # ustvariti predmet - DateTime::createFromFormat('Y-m-d') # klic statične metode - @anotherService # posredovanje druge storitve - @http.request::getRemoteAddress() # klic druge metode storitve - ::getenv(NetteMode) # klic globalne funkcije + database: PDO( + 'mysql:host=127.0.0.1;dbname=test' + root + secret ) ``` -Ustreza kodi PHP: - -```php -public function createServiceAnalyser(): My\Analyser -{ - return new My\Analyser( - new FilesystemIterator('...'), - DateTime::createFromFormat('Y-m-d'), - $this->getService('anotherService'), - $this->getService('http.request')->getRemoteAddress(), - getenv('NetteMode') - ); -} -``` - - -Posebne funkcije .[#toc-special-functions] ------------------------------------------- - -Posebne funkcije lahko uporabite tudi v argumentih za izločanje ali zanikanje vrednosti: - -- `not(%arg%)` zanikanje -- `bool(%arg%)` brez izgub odlitek v bool -- `int(%arg%)` brez izgub v int -- `float(%arg%)` brez izgub v float -- `string(%arg%)` brez izgube v niz +Argumente lahko tudi poimenujete, kar vam omogoča, da se ne ukvarjate z njihovim vrstnim redom: ```neon services: - - Foo( - id: int(::getenv('ProjectId')) - productionMode: not(%debugMode%) + database: PDO( + username: root + password: secret + dsn: 'mysql:host=127.0.0.1;dbname=test' ) ``` -Brezizgubno prepisovanje se razlikuje od običajnega prepisovanja v PHP, npr. z uporabo `(int)`, po tem, da vrže izjemo za neštevilčne vrednosti. - -Kot argumente je mogoče posredovati več storitev. Polje vseh storitev določene vrste (tj. razreda ali vmesnika) ustvari funkcija `typed()`. Funkcija bo izpustila storitve, ki imajo onemogočeno samodejno napeljavo, lahko pa se določi več vrst, ločenih z vejico. +Če želite določene argumente izpustiti in uporabiti njihove privzete vrednosti ali vstaviti storitev prek [samodejnega napeljevanja |autowiring], uporabite podčrtaj: ```neon services: - - BarsDependent( typed(Bar) ) -``` - -Polje storitev lahko posredujete tudi samodejno z uporabo [samodejnega napeljevanja |autowiring#Collection of Services]. - -Polje vseh storitev z določeno [oznako |#tags] ustvari funkcija `tagged()`. Navedete lahko več oznak, ločenih z vejico. - -```neon -services: - - LoggersDependent( tagged(logger) ) + foo: Foo(_, %appDir%) ``` - -Sklicevanje na storitve .[#toc-referencing-services] -==================================================== - -Na posamezne storitve se sklicujemo z uporabo znakov `@` and name, so for example `@database`: - -```neon -services: - - create: Foo(@database) - setup: - - setCacheStorage(@cache.storage) -``` - -Ustreza kodi PHP: - -```php -public function createService01(): Foo -{ - $service = new Foo($this->getService('database')); - $service->setCacheStorage($this->getService('cache.storage')); - return $service; -} -``` - -Tudi na anonimne storitve se lahko sklicujete s povratnim klicem, le namesto imena navedite njihovo vrsto (razred ali vmesnik). Vendar to običajno ni potrebno zaradi [samodejnega povezovanja |autowiring]. - -```neon -services: - - create: Foo(@Nette\Database\Connection) - setup: - - setCacheStorage(@cache.storage) -``` +Argumenti so lahko storitve, parametri in še veliko več, glejte [izrazna sredstva |#expression means]. Nastavitev .[#toc-setup] ======================== -V razdelku nastavitev so naštete metode, ki jih je treba poklicati pri ustvarjanju storitve: +V razdelku `setup` opredelimo metode, ki jih je treba poklicati pri ustvarjanju storitve. ```neon services: @@ -274,7 +152,7 @@ services: - setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) ``` -Ustreza kodi PHP: +V jeziku PHP bi bilo to videti takole: ```php public function createServiceDatabase(): PDO @@ -285,8 +163,7 @@ public function createServiceDatabase(): PDO } ``` -Nastavite lahko tudi lastnosti. Podprto je tudi dodajanje elementa v polje, ki ga je treba zapisati v narekovajih, da ne bo v nasprotju s sintakso NEON: - +Poleg klicev metod lahko lastnostim posredujete tudi vrednosti. Podprto je tudi dodajanje elementa v polje, vendar ga morate zapreti v narekovaje, da ne pride do kolizije s sintakso NEON: ```neon services: @@ -297,7 +174,7 @@ services: - '$onClick[]' = [@bar, clickHandler] ``` -Ustreza kodi PHP: +V jeziku PHP bi to pomenilo: ```php public function createServiceFoo(): Foo @@ -309,8 +186,7 @@ public function createServiceFoo(): Foo } ``` -Vendar pa se lahko v nastavitvi kličejo tudi statične metode ali metode drugih storitev. Dejansko storitev jim posredujemo kot `@self`: - +V nastavitvi lahko kličete tudi statične metode ali metode drugih storitev. Če morate kot argument posredovati trenutno storitev, uporabite `@self`: ```neon services: @@ -321,7 +197,7 @@ services: - @anotherService::setFoo(@self) ``` -Ustreza kodi PHP: +Upoštevajte, da zaradi enostavnosti namesto `->` uporabimo `::`, glejte [izrazna sredstva |#expression means]. To ustvari naslednjo tovarniško metodo: ```php public function createServiceFoo(): Foo @@ -334,23 +210,133 @@ public function createServiceFoo(): Foo ``` +Sredstva za izražanje .[#toc-expression-means] +============================================== + +Nette DI nam zagotavlja izjemno bogate izrazne možnosti, s katerimi lahko izrazimo skoraj vse. V konfiguracijskih datotekah lahko uporabljamo [parametre |configuration#parameters]: + +```neon +# parameter +%wwwDir% + +# vrednost pod ključem parametra +%mailer.user% + +# parameter v nizu +'%wwwDir%/images' +``` + +Prav tako lahko ustvarjamo predmete, kličemo metode in funkcije: + +```neon +# ustvariti predmet +DateTime() + +# klic statične metode +Collator::create(%locale%) + +# klic funkcije PHP +::getenv(DB_USER) +``` + +Na storitve se lahko sklicujemo po imenu ali vrsti: + +```neon +# storitev po imenu +@database + +# storitev po vrsti +@Nette\Database\Connection +``` + +Uporabite konstante: + +```neon +# razred stalnica +FilesystemIterator::SKIP_DOTS + +# globalna konstanta, pridobljena s funkcijo PHP constant() +::constant(PHP_VERSION) +``` + +Tako kot v PHP lahko klice metod verižite. Zaradi preprostosti namesto `->` uporabimo `::`: + +```neon +DateTime()::format('Y-m-d') +# PHP: (new DateTime())->format('Y-m-d') + +@http.request::getUrl()::getHost() +# PHP: $this->getService('http.request')->getUrl()->getHost() +``` + +Te izraze lahko pri [ustvarjanju storitev |#Service Creation] uporabite kjer koli, v [argumentih |#Arguments], v [nastavitvenem |#setup] delu ali [parametrih |configuration#parameters]: + +```neon +parameters: + ipAddress: @http.request::getRemoteAddress() + +services: + database: + create: DatabaseFactory::create( @anotherService::getDsn() ) + setup: + - initialize( ::getenv('DB_USER') ) +``` + + +Posebne funkcije .[#toc-special-functions] +------------------------------------------ + +V konfiguracijskih datotekah lahko uporabite te posebne funkcije: + +- `not()` za zanikanje vrednosti +- `bool()`, `int()`, `float()`, `string()` za brezizgubno ulivanje tipov +- `typed()` za ustvarjanje polja vseh storitev določenega tipa +- `tagged()` za ustvarjanje polja vseh storitev z določeno oznako + +```neon +services: + - Foo( + id: int(::getenv('ProjectId')) + productionMode: not(%debugMode%) + ) +``` + +V primerjavi z običajnim tipiziranjem v PHP, kot je `(int)`, bo brezizgubno tipiziranje vrglo izjemo za neštevilčne vrednosti. + +Funkcija `typed()` ustvari polje vseh storitev določene vrste (razreda ali vmesnika). Izključuje storitve z izklopljenim samodejnim vgrajevanjem. Določite lahko več vrst, ki jih ločite z vejicami. + +```neon +services: + - BarsDependent( typed(Bar) ) +``` + +Kot argument lahko samodejno posredujete tudi polje storitev določene vrste z uporabo [samodejnega napeljevanja |autowiring#Collection of Services]. + +Funkcija `tagged()` ustvari polje vseh storitev z določeno oznako. Navedete lahko več oznak, ki jih ločite z vejicami. + +```neon +services: + - LoggersDependent( tagged(logger) ) +``` + + Avtomatska napeljava .[#toc-autowiring] ======================================= -Ključ za samodejno ožičenje lahko uporabite za izključitev storitve iz samodejnega ožičenja ali za vplivanje na njeno obnašanje. Za več informacij glejte [poglavje o samodejnem ožičenju |autowiring]. +Ključ `autowired` omogoča spreminjanje obnašanja samodejnega ožičenja za določeno storitev. Za več podrobnosti glejte [poglavje o samodejnem ožičenju |autowiring]. ```neon services: foo: create: Foo - autowired: false # foo je odstranjen iz samodejne napeljave + autowired: false # storitev foo je izključena iz samodejnega ožičenja ``` Oznake .[#toc-tags] =================== -Posameznim storitvam je mogoče dodati informacije o uporabniku v obliki oznak: +Oznake se uporabljajo za dodajanje dodatnih informacij storitvam. Storitvi lahko dodelite eno ali več oznak: ```neon services: @@ -360,7 +346,7 @@ services: - cached ``` -Oznake imajo lahko tudi vrednost: +Oznake lahko nosijo tudi vrednosti: ```neon services: @@ -370,14 +356,14 @@ services: logger: monolog.logger.event ``` -Polje storitev z določenimi oznakami lahko posredujete kot argument s funkcijo `tagged()`. Določite lahko tudi več oznak, ki so ločene z vejico. +Če želite priklicati vse storitve z določenimi oznakami, lahko uporabite funkcijo `tagged()`: ```neon services: - LoggersDependent( tagged(logger) ) ``` -Imena storitev je mogoče pridobiti iz vsebnika DI z uporabo metode `findByTag()`: +V vsebniku DI lahko z metodo `findByTag()` pridobite imena vseh storitev z določeno oznako: ```php $names = $container->findByTag('logger'); @@ -386,10 +372,10 @@ $names = $container->findByTag('logger'); ``` -Inject Mode .[#toc-inject-mode] -=============================== +Način vbrizgavanja .[#toc-inject-mode] +====================================== -Z zastavico `inject: true` se aktivira posredovanje odvisnosti prek javnih spremenljivk z opombo [inject |best-practices:inject-method-attribute#Inject Attributes] in metodami [inject*( |best-practices:inject-method-attribute#inject Methods] ). +Uporaba oznake `inject: true` aktivira posredovanje odvisnosti prek javnih spremenljivk z opombo [inject |best-practices:inject-method-attribute#Inject Attributes] in metodami [inject*( |best-practices:inject-method-attribute#inject Methods] ). ```neon services: @@ -401,10 +387,10 @@ services: Privzeto je funkcija `inject` aktivirana samo za predstavnike. -Spreminjanje storitev .[#toc-modification-of-services] -====================================================== +Spremembe storitev .[#toc-service-modifications] +================================================ -V vsebniku DI so številne storitve, ki jih je dodala vgrajena ali [vaša razširitev |#di-extensions]. Definicije teh storitev lahko spremenite v konfiguraciji. Na primer, za storitev `application.application`, ki je privzeto objekt `Nette\Application\Application`, lahko spremenimo razred: +Vsebnik DI vsebuje številne storitve, ki so dodane z vgrajenimi ali [uporabniškimi razširitvami |#extensions]. Definicije teh storitev lahko spreminjate neposredno v konfiguraciji. Tako lahko na primer spremenite razred storitve `application.application`, ki je običajno `Nette\Application\Application`, v drug razred: ```neon services: @@ -413,9 +399,9 @@ services: alteration: true ``` -Oznaka `alteration` je informativna in pove, da samo spreminjamo obstoječo storitev. +Oznaka `alteration` je informativna in pomeni, da zgolj spreminjamo obstoječo storitev. -Dodamo lahko tudi nastavitev: +Nastavitev lahko tudi dopolnimo: ```neon services: @@ -426,7 +412,7 @@ services: - '$onStartup[]' = [@resource, init] ``` -Pri ponovnem pisanju storitve bomo morda želeli odstraniti prvotne argumente, elemente nastavitev ali oznake, za kar je namenjen naslov `reset`: +Pri prepisovanju storitve boste morda želeli odstraniti prvotne argumente, nastavitvene elemente ali oznake, pri čemer vam pride prav `reset`: ```neon services: @@ -439,7 +425,7 @@ services: - tags ``` -Storitev, ki je bila dodana z razširitvijo, lahko tudi odstranimo iz vsebnika: +Če želite odstraniti storitev, ki jo je dodala razširitev, lahko to storite na naslednji način: ```neon services: diff --git a/dependency-injection/tr/services.texy b/dependency-injection/tr/services.texy index 13eabfd4c8..f93c888647 100644 --- a/dependency-injection/tr/services.texy +++ b/dependency-injection/tr/services.texy @@ -2,32 +2,32 @@ Hizmet Tanımları **************** .[perex] -Yapılandırma, özel hizmetlerin tanımlarını yerleştirdiğimiz yerdir. Bu `services` bölümünde yapılır. +Yapılandırma, DI konteynerine tek tek hizmetlerin nasıl bir araya getirileceği ve diğer bağımlılıklarla nasıl bağlanacağı konusunda talimat verdiğimiz yerdir. Nette bunu başarmak için çok açık ve zarif bir yol sunar. -Örneğin, `PDO` sınıfının bir örneği olacak olan `database` adlı bir hizmeti bu şekilde oluşturuyoruz: +NEON yapılandırma dosyasındaki `services` bölümü, özel hizmetlerimizi ve yapılandırmalarını tanımladığımız yerdir. `PDO` sınıfının bir örneğini temsil eden `database` adlı bir hizmetin tanımlanmasına ilişkin basit bir örneğe bakalım: ```neon services: database: PDO('sqlite::memory:') ``` -Hizmetlerin isimlendirilmesi, onlara [referans |#Referencing Services] vermemizi sağlamak için kullanılır. Bir hizmete referans verilmiyorsa, onu adlandırmaya gerek yoktur. Bu yüzden isim yerine sadece bir madde işareti kullanırız: +Bu yapılandırma [DI konteynerinde |container] aşağıdaki fabrika yöntemiyle sonuçlanır: -```neon -services: - - PDO('sqlite::memory:') # anonymous service +```php +public function createServiceDatabase(): PDO +{ + return new PDO('sqlite::memory:'); +} ``` -Tek satırlık bir giriş, [kurulum |#setup] gibi ek anahtarların eklenmesine izin vermek için birden fazla satıra bölünebilir. `create:` tuşu için takma ad `factory:` şeklindedir. +Hizmet adları, `@serviceName` biçimini kullanarak yapılandırma dosyasının diğer bölümlerinde bunlara başvurmamızı sağlar. Hizmeti adlandırmaya gerek yoksa, sadece bir madde işareti kullanabiliriz: ```neon services: - database: - create: PDO('sqlite::memory:') - setup: ... + - PDO('sqlite::memory:') ``` -Daha sonra `getService()` yöntemini isme göre ya da daha iyisi `getByType()` yöntemini türe göre kullanarak hizmeti DI konteynerinden alırız: +DI konteynerinden bir hizmeti almak için, parametre olarak hizmet adıyla birlikte `getService()` yöntemini veya hizmet türüyle birlikte `getByType()` yöntemini kullanabiliriz: ```php $database = $container->getService('database'); @@ -35,236 +35,114 @@ $database = $container->getByType(PDO::class); ``` -Hizmet Oluşturma .[#toc-creating-a-service] -=========================================== +Hizmet Oluşturma .[#toc-service-creation] +========================================= -Çoğu zaman, sadece bir sınıfın örneğini oluşturarak bir hizmet yaratırız: +En yaygın olarak, sadece belirli bir sınıfı örnekleyerek bir hizmet oluştururuz. Örneğin: ```neon services: database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` -Bu da [DI konteynerinde |container] bir fabrika yöntemi oluşturacaktır: - -```php -public function createServiceDatabase(): PDO -{ - return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret'); -} -``` - -Alternatif olarak, [argümanları |#Arguments] iletmek için bir anahtar `arguments` kullanılabilir: +Yapılandırmayı ek anahtarlarla genişletmemiz gerekirse, tanım birden fazla satıra genişletilebilir: ```neon services: database: - create: PDO - arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] -``` - -Statik bir yöntem de bir hizmet oluşturabilir: - -```neon -services: - database: My\Database::create(root, secret) + create: PDO('sqlite::memory:') + setup: ... ``` -PHP koduna karşılık gelir: + `create` anahtarının bir takma adı vardır `factory`, her iki sürüm de pratikte yaygındır. Ancak biz `create` adresini kullanmanızı öneririz. -```php -public function createServiceDatabase(): PDO -{ - return My\Database::create('root', 'secret'); -} -``` - -Statik bir yöntemin `My\Database::create()` DI konteynerinin bilmesi gereken tanımlı bir dönüş değerine sahip olduğu varsayılır. Eğer yoksa, türü yapılandırmaya yazarız: +Kurucu argümanları veya oluşturma yöntemi alternatif olarak `arguments` anahtarına yazılabilir: ```neon services: database: - create: My\Database::create(root, secret) - type: PDO + create: PDO + arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] ``` -Nette DI size neredeyse her şeyi yazmanız için son derece güçlü ifade olanakları sunar. Örneğin, başka bir servise [başvurmak |#Referencing Services] ve onun metodunu çağırmak için. Basitlik için `->` yerine `::` kullanılır. +Hizmetler sadece bir sınıfın basit bir şekilde örneklenmesiyle oluşturulmak zorunda değildir; statik yöntemlerin veya diğer hizmetlerin yöntemlerinin çağrılmasıyla da ortaya çıkabilirler: ```neon services: - routerFactory: App\Router\Factory + database: DatabaseFactory::create() router: @routerFactory::create() ``` -PHP koduna karşılık gelir: +Basitlik için `->` yerine `::` kullandığımızı unutmayın, [ifade araçlarına |#expression means] bakın. Bu fabrika yöntemleri oluşturulur: ```php -public function createServiceRouterFactory(): App\Router\Factory +public function createServiceDatabase(): PDO { - return new App\Router\Factory; + return DatabaseFactory::create(); } -public function createServiceRouter(): Router +public function createServiceRouter(): RouteList { return $this->getService('routerFactory')->create(); } ``` -PHP'de olduğu gibi yöntem çağrıları zincirleme olarak birbirine eklenebilir: +DI konteynerinin oluşturulan hizmetin türünü bilmesi gerekir. Belirtilen bir dönüş türüne sahip olmayan bir yöntem kullanarak bir hizmet oluşturursak, yapılandırmada bu türden açıkça bahsetmeliyiz: ```neon services: - foo: FooFactory::build()::get() -``` - -PHP koduna karşılık gelir: - -```php -public function createServiceFoo() -{ - return FooFactory::build()->get(); -} + database: + create: DatabaseFactory::create() + type: PDO ``` Argümanlar .[#toc-arguments] ============================ -Adlandırılmış parametreler argümanları iletmek için de kullanılabilir: +Normal PHP'ye çok benzer bir şekilde kuruculara ve yöntemlere argümanlar aktarırız: ```neon services: - database: PDO( - 'mysql:host=127.0.0.1;dbname=test' # konumsal - username: root # named - password: secret # named - ) -``` - -Argümanları birden fazla satıra bölerken virgül kullanımı isteğe bağlıdır. - -Elbette, [diğer hizmetleri |#Referencing Services] veya [parametreleri |configuration#parameters] de argüman olarak kullanabiliriz: - -```neon -services: - - Foo(@anotherService, %appDir%) -``` - -PHP koduna karşılık gelir: - -```php -public function createService01(): Foo -{ - return new Foo($this->getService('anotherService'), '...'); -} + database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` -İlk bağımsız değişken [otomatik olarak bağlanmışsa |autowiring] ve ikincisini belirtmek istiyorsanız, ilkini `_` character, for example `Foo(_, %appDir%)` ile atlayın. Ya da daha iyisi, yalnızca ikinci bağımsız değişkeni [adlandırılmış |autowiring] bir parametre olarak iletin, örneğin `Foo(path: %appDir%)`. - -Nette DI ve NEON formatı size neredeyse her şeyi yazmanız için son derece güçlü ifade olanakları sağlar. Böylece bir argüman yeni oluşturulmuş bir nesne olabilir, statik metotları, diğer servislerin metotlarını ve hatta özel gösterim kullanarak global fonksiyonları çağırabilirsiniz: +Daha iyi okunabilirlik için, argümanları ayrı satırlarda listeleyebiliriz. Bu formatta virgül kullanımı isteğe bağlıdır: ```neon services: - analyser: My\Analyser( - FilesystemIterator(%appDir%) # nesne oluştur - DateTime::createFromFormat('Y-m-d') # statik yöntemi çağırın - @anotherService # başka bir hizmet geçirme - @http.request::getRemoteAddress() # başka bir hizmet yöntemini çağırma - ::getenv(NetteMode) # global bir fonksiyon çağırın + database: PDO( + 'mysql:host=127.0.0.1;dbname=test' + root + secret ) ``` -PHP koduna karşılık gelir: - -```php -public function createServiceAnalyser(): My\Analyser -{ - return new My\Analyser( - new FilesystemIterator('...'), - DateTime::createFromFormat('Y-m-d'), - $this->getService('anotherService'), - $this->getService('http.request')->getRemoteAddress(), - getenv('NetteMode') - ); -} -``` - - -Özel Fonksiyonlar .[#toc-special-functions] -------------------------------------------- - -Değerleri atamak veya olumsuzlamak için argümanlarda özel fonksiyonlar da kullanabilirsiniz: - -- `not(%arg%)` olumsuzlama -- `bool(%arg%)` bool'a kayıpsız döküm -- `int(%arg%)` int'e kayıpsız döküm -- `float(%arg%)` float'a kayıpsız döküm -- `string(%arg%)` dizeye kayıpsız döküm +Argümanlara isim de verebilirsiniz, böylece sıraları konusunda endişelenmenize gerek kalmaz: ```neon services: - - Foo( - id: int(::getenv('ProjectId')) - productionMode: not(%debugMode%) + database: PDO( + username: root + password: secret + dsn: 'mysql:host=127.0.0.1;dbname=test' ) ``` -Kayıpsız yeniden yazım, normal PHP yeniden yazımından farklıdır, örneğin `(int)`, sayısal olmayan değerler için bir istisna atar. - -Birden fazla hizmet argüman olarak aktarılabilir. Belirli bir türdeki (yani, sınıf veya arayüz) tüm hizmetlerin bir dizisi `typed()` işlevi tarafından oluşturulur. İşlev, otomatik kablolamanın devre dışı bırakıldığı hizmetleri atlar ve virgülle ayrılmış birden fazla tür belirtilebilir. +Belirli bağımsız değişkenleri atlamak ve varsayılan değerlerini kullanmak veya [otomatik |autowiring] bağlantı yoluyla bir hizmet eklemek istiyorsanız, bir alt çizgi kullanın: ```neon services: - - BarsDependent( typed(Bar) ) -``` - -[Otomatik kablolamayı |autowiring#Collection of Services] kullanarak bir dizi hizmeti otomatik olarak da geçirebilirsiniz. - -Belirli bir [etikete |#tags] sahip tüm hizmetlerin bir dizisi `tagged()` işlevi tarafından oluşturulur. Virgülle ayrılmış birden fazla etiket belirtilebilir. - -```neon -services: - - LoggersDependent( tagged(logger) ) + foo: Foo(_, %appDir%) ``` - -Referanslama Hizmetleri .[#toc-referencing-services] -==================================================== - -Bireysel hizmetlere `@` and name, so for example `@database` karakteri kullanılarak atıfta bulunulur: - -```neon -services: - - create: Foo(@database) - setup: - - setCacheStorage(@cache.storage) -``` - -PHP koduna karşılık gelir: - -```php -public function createService01(): Foo -{ - $service = new Foo($this->getService('database')); - $service->setCacheStorage($this->getService('cache.storage')); - return $service; -} -``` - -Anonim hizmetlere bile bir geri arama kullanılarak başvurulabilir, sadece adları yerine türlerini (sınıf veya arayüz) belirtin. Ancak, [otomatik |autowiring] bağlantı nedeniyle bu genellikle gerekli değildir. - -```neon -services: - - create: Foo(@Nette\Database\Connection) - setup: - - setCacheStorage(@cache.storage) -``` +Bağımsız değişkenler hizmetler, parametreler ve çok daha fazlası olabilir, [ifade araçlarına |#expression means] bakın. Kurulum .[#toc-setup] ===================== -Kurulum bölümünde, hizmet oluşturulurken çağrılacak yöntemleri listeliyoruz: + `setup` bölümünde, hizmet oluşturulurken çağrılması gereken yöntemleri tanımlıyoruz. ```neon services: @@ -274,7 +152,7 @@ services: - setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) ``` -PHP koduna karşılık gelir: +PHP'de bu şöyle görünecektir: ```php public function createServiceDatabase(): PDO @@ -285,8 +163,7 @@ public function createServiceDatabase(): PDO } ``` -Özellikler de ayarlanabilir. Bir diziye eleman eklemek de desteklenir ve NEON sözdizimiyle çakışmaması için tırnak içinde yazılmalıdır: - +Yöntem çağrılarına ek olarak, özelliklere değer de aktarabilirsiniz. Bir diziye eleman eklemek de desteklenir, ancak NEON sözdizimiyle çakışmasını önlemek için bunu tırnak içine almanız gerekir: ```neon services: @@ -297,7 +174,7 @@ services: - '$onClick[]' = [@bar, clickHandler] ``` -PHP koduna karşılık gelir: +PHP'de bu şu anlama gelir: ```php public function createServiceFoo(): Foo @@ -309,8 +186,7 @@ public function createServiceFoo(): Foo } ``` -Ancak, statik yöntemler veya diğer hizmetlerin yöntemleri de kurulumda çağrılabilir. Onlara asıl servisi `@self` olarak iletiyoruz: - +Kurulumda, statik yöntemleri veya diğer hizmetlerin yöntemlerini de çağırabilirsiniz. Geçerli hizmeti argüman olarak geçirmeniz gerekiyorsa, `@self` adresini kullanın: ```neon services: @@ -321,7 +197,7 @@ services: - @anotherService::setFoo(@self) ``` -PHP koduna karşılık gelir: +Basitlik için `->` yerine `::` kullandığımızı unutmayın, [ifade araçlarına |#expression means] bakın. Bu, aşağıdaki fabrika yöntemini oluşturur: ```php public function createServiceFoo(): Foo @@ -334,23 +210,133 @@ public function createServiceFoo(): Foo ``` +İfade Araçları .[#toc-expression-means] +======================================= + +Nette DI bize son derece zengin ifade yetenekleri sunarak neredeyse her şeyi ifade etmemize olanak tanır. Yapılandırma dosyalarında [parametreler |configuration#parameters] kullanabiliriz: + +```neon +# parametresi +%wwwDir% + +# bir parametre anahtarı altındaki değer +%mailer.user% + +# bir dize içindeki parametre +'%wwwDir%/images' +``` + +Ayrıca nesneler oluşturabilir, yöntemler ve fonksiyonlar çağırabiliriz: + +```neon +# bir nesne oluşturun +DateTime() + +# statik bir yöntem çağırma +Collator::create(%locale%) + +# bir PHP işlevini çağırır +::getenv(DB_USER) +``` + +Hizmetlere ya adlarıyla ya da türlerine göre atıfta bulunun: + +```neon +# isme göre hizmet +@database + +# türe göre hi̇zmet +@Nette\Database\Connection +``` + +Sabitleri kullanın: + +```neon +# sınıf sabiti +FilesystemIterator::SKIP_DOTS + +# constant() PHP işlevi tarafından elde edilen küresel sabit +::constant(PHP_VERSION) +``` + +Metot çağrıları PHP'de olduğu gibi zincirleme yapılabilir. Basitlik için `->` yerine `::` kullanacağız: + +```neon +DateTime()::format('Y-m-d') +# PHP: (new DateTime())->format('Y-m-d') + +@http.request::getUrl()::getHost() +# PHP: $this->getService('http.request')->getUrl()->getHost() +``` + +Bu ifadeler [hizmetler oluşturulurken |#Service Creation] herhangi bir yerde, [argümanlarda |#Arguments], [kurulum |#setup] bölümünde veya [parametrelerde |configuration#parameters] kullanılabilir: + +```neon +parameters: + ipAddress: @http.request::getRemoteAddress() + +services: + database: + create: DatabaseFactory::create( @anotherService::getDsn() ) + setup: + - initialize( ::getenv('DB_USER') ) +``` + + +Özel Fonksiyonlar .[#toc-special-functions] +------------------------------------------- + +Yapılandırma dosyaları içinde bu özel işlevleri kullanabilirsiniz: + +- Değer olumsuzlama için `not()` +- Kayıpsız tip dökümü için `bool()`, `int()`, `float()`, `string()` +- `typed()` belirtilen türdeki tüm hizmetlerin bir dizisini oluşturmak için +- `tagged()` belirli bir etikete sahip tüm hizmetlerin bir dizisini oluşturmak için + +```neon +services: + - Foo( + id: int(::getenv('ProjectId')) + productionMode: not(%debugMode%) + ) +``` + +PHP'deki `(int)` gibi geleneksel tip atamayla karşılaştırıldığında, kayıpsız tip atama sayısal olmayan değerler için bir istisna oluşturur. + + `typed()` işlevi, belirli bir türdeki (sınıf veya arayüz) tüm hizmetlerin bir dizisini oluşturur. Otomatik kablolaması kapalı olan hizmetleri hariç tutar. Virgülle ayrılarak birden fazla tür belirtilebilir. + +```neon +services: + - BarsDependent( typed(Bar) ) +``` + + [Otomatik kab |autowiring#Collection of Services]lolamayı kullanarak belirli bir türdeki bir dizi hizmeti otomatik olarak argüman olarak da iletebilirsiniz. + + `tagged()` işlevi, belirtilen etikete sahip tüm hizmetlerin bir dizisini oluşturur. Birden fazla etiket virgülle ayrılarak listelenebilir. + +```neon +services: + - LoggersDependent( tagged(logger) ) +``` + + Otomatik Kablolama .[#toc-autowiring] ===================================== -Otomatik bağlama anahtarı, bir hizmeti otomatik bağlamanın dışında tutmak veya davranışını etkilemek için kullanılabilir. Daha fazla bilgi için otomatik kablolama [bölümüne |autowiring] bakın. + `autowired` tuşu, belirli bir hizmet için otomatik kablolama davranışını değiştirmenize olanak tanır. Daha fazla ayrıntı için otomatik kablolama [bölümüne |autowiring] bakın. ```neon services: foo: create: Foo - autowired: false # foo otomatik bağlantıdan kaldırılır + autowired: false # foo hizmeti otomatik kablolamanın dışında tutulur ``` Etiketler .[#toc-tags] ====================== -Kullanıcı bilgileri tek tek hizmetlere etiket şeklinde eklenebilir: +Etiketler hizmetlere ek bilgi eklemek için kullanılır. Bir hizmete bir veya daha fazla etiket atayabilirsiniz: ```neon services: @@ -360,7 +346,7 @@ services: - cached ``` -Etiketler bir değere de sahip olabilir: +Etiketler değer de taşıyabilir: ```neon services: @@ -370,26 +356,26 @@ services: logger: monolog.logger.event ``` -Belirli etiketlere sahip bir dizi hizmet, `tagged()` işlevi kullanılarak argüman olarak aktarılabilir. Virgülle ayrılmış birden fazla etiket de belirtilebilir. +Belirli etiketlere sahip tüm hizmetleri almak için `tagged()` işlevini kullanabilirsiniz: ```neon services: - LoggersDependent( tagged(logger) ) ``` -Hizmet adları `findByTag()` yöntemi kullanılarak DI konteynerinden elde edilebilir: +DI konteynerinde, `findByTag()` yöntemini kullanarak belirli bir etikete sahip tüm hizmetlerin adlarını elde edebilirsiniz: ```php $names = $container->findByTag('logger'); // $names, hizmet adını ve etiket değerini içeren bir dizidir -// i.e. ['foo' => 'monolog.logger.event', ...] +// örneğin ['foo' => 'monolog.logger.event', ...] ``` Enjeksiyon Modu .[#toc-inject-mode] =================================== -`inject: true` bayrağı, bağımlılıkların [inject |best-practices:inject-method-attribute#Inject Attributes] ek açıklaması ve [inject*() |best-practices:inject-method-attribute#inject Methods] yöntemleri ile genel değişkenler aracılığıyla aktarılmasını etkinleştirmek için kullanılır. + `inject: true` bayrağının kullanılması, bağımlılıkların [inject |best-practices:inject-method-attribute#Inject Attributes] ek açıklaması ve [inject*() |best-practices:inject-method-attribute#inject Methods] yöntemleri ile genel değişkenler aracılığıyla aktarılmasını etkinleştirir. ```neon services: @@ -401,10 +387,10 @@ services: Varsayılan olarak, `inject` yalnızca sunum yapanlar için etkinleştirilir. -Hizmetlerin Değiştirilmesi .[#toc-modification-of-services] -=========================================================== +Hizmet Değişiklikleri .[#toc-service-modifications] +=================================================== -DI konteynerinde yerleşik veya [uzantınız |#di-extensions] tarafından eklenen bir dizi hizmet vardır. Bu hizmetlerin tanımları yapılandırmada değiştirilebilir. Örneğin, varsayılan olarak bir nesne olan `application.application` hizmeti için `Nette\Application\Application` sınıfını değiştirebiliriz: +DI konteyneri, yerleşik veya [kullanıcı uzantıları |#extensions] tarafından eklenen birçok hizmet içerir. Bu hizmetlerin tanımlarını doğrudan yapılandırma içinde değiştirebilirsiniz. Örneğin, geleneksel olarak `Nette\Application\Application` olan `application.application` hizmetinin sınıfını başka bir şeyle değiştirebilirsiniz: ```neon services: @@ -413,9 +399,9 @@ services: alteration: true ``` -`alteration` bayrağı bilgilendiricidir ve sadece mevcut bir hizmeti değiştirdiğimizi söyler. + `alteration` bayrağı bilgilendiricidir ve yalnızca mevcut bir hizmeti değiştirdiğimizi gösterir. -Ayrıca bir kurulum da ekleyebiliriz: +Kurulumu da tamamlayabiliriz: ```neon services: @@ -426,7 +412,7 @@ services: - '$onStartup[]' = [@resource, init] ``` -Bir hizmeti yeniden yazarken, orijinal argümanları, kurulum öğelerini veya etiketleri kaldırmak isteyebiliriz, `reset` bunun içindir: +Bir hizmetin üzerine yazarken, orijinal argümanları, kurulum öğelerini veya etiketleri kaldırmak isteyebilirsiniz, işte bu noktada `reset` kullanışlı hale gelir: ```neon services: @@ -439,7 +425,7 @@ services: - tags ``` -Uzantı ile eklenen bir hizmet konteynerden de kaldırılabilir: +Bir uzantı tarafından eklenen bir hizmeti kaldırmak isterseniz, bunu şu şekilde yapabilirsiniz: ```neon services: diff --git a/dependency-injection/uk/services.texy b/dependency-injection/uk/services.texy index 85879327de..9578919b3d 100644 --- a/dependency-injection/uk/services.texy +++ b/dependency-injection/uk/services.texy @@ -2,32 +2,32 @@ ******************* .[perex] -Конфігурація - це місце, де ми розміщуємо визначення користувацьких сервісів. Робиться це в секції `services`. +Конфігурація - це місце, де ми вказуємо DI контейнеру, як зібрати окремі сервіси і як з'єднати їх з іншими залежностями. Nette надає дуже чіткий та елегантний спосіб досягти цього. -Наприклад, ось як ми створюємо сервіс з іменем `database`, який буде екземпляром класу `PDO`: +Секція `services` у файлі конфігурації NEON - це місце, де ми визначаємо наші кастомні сервіси та їхні конфігурації. Давайте розглянемо простий приклад визначення сервісу з ім'ям `database`, який представляє екземпляр класу `PDO`: ```neon services: database: PDO('sqlite::memory:') ``` -Іменування служб використовується для того, щоб ми могли [посилатися |#Referencing-Services] на них. Якщо на сервіс не посилаються, немає необхідності давати йому ім'я. Тому замість імені ми просто використовуємо двокрапку: +Ця конфігурація призводить до наступного заводського методу в контейнері [DI |container]: -```neon -services: - - PDO('sqlite::memory:') # анонімний сервіс +```php +public function createServiceDatabase(): PDO +{ + return new PDO('sqlite::memory:'); +} ``` -Однорядковий запис може бути розбитий на кілька рядків, щоб можна було додати додаткові ключі, наприклад [setup |#setup]. Псевдонім для ключа `create:` - `factory:`. +Назви сервісів дозволяють нам посилатися на них в інших частинах конфігураційного файлу, використовуючи формат `@serviceName`. Якщо немає необхідності називати службу, ми можемо просто використовувати маркер: ```neon services: - database: - create: PDO('sqlite::memory:') - setup: ... + - PDO('sqlite::memory:') ``` -Потім ми отримуємо сервіс із контейнера DI, використовуючи метод `getService()` за ім'ям, або, що ще краще, метод `getByType()` за типом: +Щоб отримати сервіс з контейнера DI, ми можемо використовувати метод `getService()` з назвою сервісу як параметром або метод `getByType()` з типом сервісу: ```php $database = $container->getService('database'); @@ -35,236 +35,114 @@ $database = $container->getByType(PDO::class); ``` -Створення сервісу .[#toc-creating-a-service] -============================================ +Створення сервісу .[#toc-service-creation] +========================================== -Найчастіше ми створюємо сервіс, просто створюючи екземпляр класу: +Найчастіше ми створюємо сервіс, просто створюючи екземпляр певного класу. Наприклад: ```neon services: database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` -Що створить фабричний метод у [DI-контейнері |container]: - -```php -public function createServiceDatabase(): PDO -{ - return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret'); -} -``` - -Альтернативно, ключ `arguments` може бути використаний для передачі [аргументів |#Arguments]: +Якщо нам потрібно розширити конфігурацію за допомогою додаткових ключів, визначення можна розгорнути на кілька рядків: ```neon services: database: - create: PDO - arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] -``` - -Статичний метод також може створити сервіс: - -```neon -services: - database: My\Database::create(root, secret) + create: PDO('sqlite::memory:') + setup: ... ``` -Це еквівалентно коду PHP: +Ключ `create` має псевдонім `factory`, обидві версії поширені на практиці. Однак ми рекомендуємо використовувати `create`. -```php -public function createServiceDatabase(): PDO -{ - return My\Database::create('root', 'secret'); -} -``` - -Передбачається, що статичний метод `My\Database::create()` має певне значення, що повертається, яке повинен знати контейнер DI. Якщо у нього його немає, ми записуємо тип у конфігурацію: +Аргументи конструктора або метод створення можна також записати в ключі `arguments`: ```neon services: database: - create: My\Database::create(root, secret) - type: PDO + create: PDO + arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret] ``` -Nette DI надає вам надзвичайно потужні засоби вираження, що дозволяють написати практично все, що завгодно. Наприклад, щоб [звернутися |#Referencing-Services] до іншої служби і викликати її метод. Для простоти замість `->` використовується `::`. +Сервіси не обов'язково створювати простим екземпляром класу; вони також можуть бути результатом виклику статичних методів або методів інших сервісів: ```neon services: - routerFactory: App\Router\Factory + database: DatabaseFactory::create() router: @routerFactory::create() ``` -Це еквівалентно коду PHP: +Зауважте, що для простоти замість `->` ми використовуємо `::`, див. [засоби вираження |#expression means]. Ці фабричні методи генеруються: ```php -public function createServiceRouterFactory(): App\Router\Factory +public function createServiceDatabase(): PDO { - return new App\Router\Factory; + return DatabaseFactory::create(); } -public function createServiceRouter(): Router +public function createServiceRouter(): RouteList { return $this->getService('routerFactory')->create(); } ``` -Виклики методів можна об'єднувати в ланцюжки, як у PHP: +Контейнер DI повинен знати тип створюваного сервісу. Якщо ми створюємо сервіс за допомогою методу, який не має визначеного типу повернення, ми повинні явно вказати цей тип у конфігурації: ```neon services: - foo: FooFactory::build()::get() -``` - -Це еквівалентно коду PHP: - -```php -public function createServiceFoo() -{ - return FooFactory::build()->get(); -} + database: + create: DatabaseFactory::create() + type: PDO ``` Аргументи .[#toc-arguments] =========================== -Іменовані параметри також можуть використовуватися для передачі аргументів: +Ми передаємо аргументи конструкторам і методам у спосіб, дуже схожий на звичайний PHP: ```neon services: - database: PDO( - 'mysql:host=127.0.0.1;dbname=test' # позиційний - username: root # іменований - password: secret # іменований - ) -``` - -Використання ком необов'язкове при розбитті аргументів на кілька рядків. - -Звичайно, ми також можемо використовувати [інші сервіси |#Referencing-Services] або [параметри |configuration#Parameters] як аргументи: - -```neon -services: - - Foo(@anotherService, %appDir%) -``` - -Відповідає коду PHP: - -```php -public function createService01(): Foo -{ - return new Foo($this->getService('anotherService'), '...'); -} + database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret) ``` -Якщо перший аргумент - [автомонтований |autowiring], а ви хочете вказати другий, опустіть перший за допомогою символу `_`, например `Foo(_, %appDir%)`. Або, що ще краще, передавайте тільки другий аргумент як іменований параметр, наприклад: `Foo(path: %appDir%)`. - -Nette DI і формат NEON дають вам надзвичайно потужні виразні засоби, що дозволяють написати практично все, що завгодно. Таким чином, аргументом може бути новостворений об'єкт, ви можете викликати статичні методи, методи інших сервісів або навіть глобальні функції, використовуючи спеціальну нотацію: +Для кращої читабельності ми можемо перераховувати аргументи в окремих рядках. У цьому форматі використання ком не є обов'язковим: ```neon services: - analyser: My\Analyser( - FilesystemIterator(%appDir%) # створюємо об'єкт - DateTime::createFromFormat('Y-m-d') # викликаємо статичний метод - @anotherService # передаємо інший сервіс - @http.request::getRemoteAddress() # викликаємо метод іншого сервісу - ::getenv(NetteMode) # викликаємо глобальну функцію + database: PDO( + 'mysql:host=127.0.0.1;dbname=test' + root + secret ) ``` -Відповідає коду PHP: - -```php -public function createServiceAnalyser(): My\Analyser -{ - return new My\Analyser( - new FilesystemIterator('...'), - DateTime::createFromFormat('Y-m-d'), - $this->getService('anotherService'), - $this->getService('http.request')->getRemoteAddress(), - getenv('NetteMode') - ); -} -``` - - -Спеціальні функції .[#toc-special-functions] --------------------------------------------- - -Ви також можете використовувати спеціальні функції в аргументах для приведення або заперечення значень: - -- `not(%arg%)` заперечення -- `bool(%arg%)` приведення до bool без втрат -- `int(%arg%)` приведення до int без втрат -- `float(%arg%)` приведення до плаваючого стану без втрат -- `string(%arg%)` приведення до рядка без втрат +Ви також можете назвати аргументи, що дозволить вам не турбуватися про їх порядок: ```neon services: - - Foo( - id: int(::getenv('ProjectId')) - productionMode: not(%debugMode%) + database: PDO( + username: root + password: secret + dsn: 'mysql:host=127.0.0.1;dbname=test' ) ``` -Переписування без втрат відрізняється від звичайного переписування в PHP, наприклад використовуючи `(int)`, у тому, що воно викидає виняток для нечислових значень. - -Як аргументи можна передавати кілька сервісів. Масив усіх сервісів певного типу (тобто класу або інтерфейсу) створюється функцією `typed()`. Функція буде опускати сервіси, у яких відключено автопідключення, при цьому можна вказати кілька типів, розділених комою. +Якщо ви хочете пропустити певні аргументи і використовувати їхні значення за замовчуванням або вставити сервіс за допомогою [автопідключення |autowiring], використовуйте символ підкреслення: ```neon services: - - BarsDependent( typed(Bar) ) + foo: Foo(_, %appDir%) ``` -Ви також можете передати масив сервісів автоматично, використовуючи [автозв'язування |autowiring#Collection-of-Services]. +Аргументами можуть бути сервіси, параметри та багато іншого, див. розділ [Засоби вираження |#expression means]. -Масив усіх сервісів із певним [тегом |#Tags] створюється функцією `tagged()`. Можна вказати кілька тегів, розділених комою. - -```neon -services: - - LoggersDependent( tagged(logger) ) -``` +Налаштування .[#toc-setup] +========================== -Посилання на сервіси .[#toc-referencing-services] -================================================= - -Посилання на окремі сервіси використовуються за допомогою символу `@` и имени, например `@database`: - -```neon -services: - - create: Foo(@database) - setup: - - setCacheStorage(@cache.storage) -``` - -Відповідає коду PHP: - -```php -public function createService01(): Foo -{ - $service = new Foo($this->getService('database')); - $service->setCacheStorage($this->getService('cache.storage')); - return $service; -} -``` - -Навіть на анонімні сервіси можна посилатися за допомогою зворотного виклику, просто вкажіть їхній тип (клас або інтерфейс) замість імені. Однак зазвичай у цьому немає потреби через [автозв'язування |autowiring]. - -```neon -services: - - create: Foo(@Nette\Database\Connection) - setup: - - setCacheStorage(@cache.storage) -``` - - -Setup .[#toc-setup] -=================== - -У секції `setup` ми перераховуємо методи, які будуть викликатися під час створення сервісу: +У розділі `setup` ми визначаємо методи, які слід викликати при створенні сервісу. ```neon services: @@ -274,7 +152,7 @@ services: - setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) ``` -Відповідає коду PHP: +На PHP це буде виглядати так: ```php public function createServiceDatabase(): PDO @@ -285,8 +163,7 @@ public function createServiceDatabase(): PDO } ``` -Також можна встановити властивості. Додавання елемента в масив також підтримується, і його слід писати в лапках, щоб не конфліктувати із синтаксисом NEON: - +Крім викликів методів, ви також можете передавати значення властивостям. Додавання елемента до масиву також підтримується, але його потрібно брати в лапки, щоб уникнути конфлікту з синтаксисом NEON: ```neon services: @@ -297,7 +174,7 @@ services: - '$onClick[]' = [@bar, clickHandler] ``` -Відповідає коду PHP: +У PHP це матиме вигляд: ```php public function createServiceFoo(): Foo @@ -309,8 +186,7 @@ public function createServiceFoo(): Foo } ``` -Однак статичні методи або методи інших сервісів також можуть бути викликані в налаштуванні. Ми передаємо їм фактичний сервіс як `@self`: - +У налаштуванні ви також можете викликати статичні методи або методи інших сервісів. Якщо вам потрібно передати поточний сервіс як аргумент, використовуйте `@self`: ```neon services: @@ -321,7 +197,7 @@ services: - @anotherService::setFoo(@self) ``` -Відповідає коду PHP: +Зауважте, що для простоти замість `->` ми використовуємо `::`, див. [засоби вираження |#expression means]. Це генерує наступний заводський метод: ```php public function createServiceFoo(): Foo @@ -334,23 +210,133 @@ public function createServiceFoo(): Foo ``` -Автозв'язування .[#toc-autowiring] -================================== +Засоби вираження .[#toc-expression-means] +========================================= + +Nette DI надає нам надзвичайно багаті можливості для вираження, що дозволяє сформулювати майже все, що завгодно. У конфігураційних файлах ми можемо використовувати [параметри |configuration#parameters]: + +```neon +# параметр +%wwwDir% + +# значення під ключем параметра +%mailer.user% + +# параметр у рядку +'%wwwDir%/images' +``` + +Ми також можемо створювати об'єкти, викликати методи та функції: + +```neon +# створити об'єкт +DateTime() + +# викликати статичний метод +Collator::create(%locale%) + +# виклик функції PHP +::getenv(DB_USER) +``` + +Звертайтеся до сервісів за назвою або за типом: + +```neon +# послуга за назвою +@database + +# послуга за типом +@Nette\Database\Connection +``` + +Використовуйте константи: + +```neon +# константа класу +FilesystemIterator::SKIP_DOTS + +# глобальна константа, отримана функцією PHP constant() +::constant(PHP_VERSION) +``` + +Виклики методів можна об'єднувати в ланцюжок, так само як і в PHP. Для простоти, замість `->` ми використовуємо `::`: + +```neon +DateTime()::format('Y-m-d') +# PHP: (new DateTime())->format('Y-m-d') + +@http.request::getUrl()::getHost() +# PHP: $this->getService('http.request')->getUrl()->getHost() +``` + +Ці вирази можна використовувати будь-де при [створенні сервісів |#Service Creation], в [аргументах |#Arguments], в розділі [налаштувань |#setup] або [параметрах |configuration#parameters]: + +```neon +parameters: + ipAddress: @http.request::getRemoteAddress() + +services: + database: + create: DatabaseFactory::create( @anotherService::getDsn() ) + setup: + - initialize( ::getenv('DB_USER') ) +``` + + +Спеціальні функції .[#toc-special-functions] +-------------------------------------------- + +У файлах конфігурації ви можете використовувати ці спеціальні функції: -Ключ `autowired` можна використовувати для виключення сервісу з автозв'язування або для впливу на його поведінку. Детальнішу інформацію див. у розділі [Автозв'язування |autowiring]. +- `not()` для заперечення значення +- `bool()`, `int()`, `float()`, `string()` для приведення типів без втрат +- `typed()` для створення масиву всіх сервісів заданого типу +- `tagged()` для створення масиву всіх сервісів із заданим тегом + +```neon +services: + - Foo( + id: int(::getenv('ProjectId')) + productionMode: not(%debugMode%) + ) +``` + +У порівнянні зі звичайним приведенням типів у PHP, наприклад, `(int)`, приведення типів без втрат згенерує виключення для нечислових значень. + +Функція `typed()` створює масив усіх сервісів певного типу (класу або інтерфейсу). Вона виключає сервіси з вимкненим автопідключенням. Можна вказати декілька типів, розділених комами. + +```neon +services: + - BarsDependent( typed(Bar) ) +``` + +Ви також можете автоматично передати масив сервісів певного типу як аргумент за допомогою [автопідключення |autowiring#Collection of Services]. + +Функція `tagged()` створює масив усіх сервісів із зазначеним тегом. Можна перерахувати декілька тегів, розділених комами. + +```neon +services: + - LoggersDependent( tagged(logger) ) +``` + + +Автопроводка .[#toc-autowiring] +=============================== + +За допомогою ключа `autowired` ви можете змінити поведінку автопідключення для певного сервісу. Для більш детальної інформації дивіться [розділ про автопідключення |autowiring]. ```neon services: foo: create: Foo - autowired: false # foo видаляється з автозв'язування + autowired: false # сервіс foo виключено з автопідключення ``` Теги .[#toc-tags] ================= -Інформація про користувача може бути додана до окремих сервісів у вигляді тегів: +Теги використовуються для додавання додаткової інформації до послуг. Ви можете призначити послузі один або декілька тегів: ```neon services: @@ -360,7 +346,7 @@ services: - cached ``` -Теги також можуть мати значення: +Мітки також можуть мати значення: ```neon services: @@ -370,26 +356,26 @@ services: logger: monolog.logger.event ``` -Масив сервісів з певними тегами може бути переданий як аргумент за допомогою функції `tagged()`. Можна також вказати кілька тегів, розділених комою. +Щоб отримати всі сервіси з певними тегами, ви можете скористатися функцією `tagged()`: ```neon services: - LoggersDependent( tagged(logger) ) ``` -Імена служб можна отримати з контейнера DI за допомогою методу `findByTag()`: +У контейнері DI ви можете отримати назви всіх сервісів з певним тегом за допомогою методу `findByTag()`: ```php $names = $container->findByTag('logger'); -// $names - масив, що містить ім'я сервісу і значення тега -// наприклад ['foo' => 'monolog.logger.event', ...] +// $names - масив, що містить назву сервісу та значення тегу +// наприклад, ['foo' => 'monolog.logger.event', ...] ``` -Режим впровадження .[#toc-inject-mode] +Режим впорскування .[#toc-inject-mode] ====================================== -Прапор `inject: true` використовується для активації передавання залежностей через публічні змінні за допомогою анотації [inject |best-practices:inject-method-attribute#Inject Attributes] і методів [inject*() |best-practices:inject-method-attribute#inject Methods]. +Використання прапора `inject: true` активує передачу залежностей через загальнодоступні змінні з анотацією [inject |best-practices:inject-method-attribute#Inject Attributes] та методами [inject*( |best-practices:inject-method-attribute#inject Methods] ). ```neon services: @@ -398,13 +384,13 @@ services: inject: true ``` -За замовчуванням `inject` активується тільки для презентерів. +За замовчуванням прапорець `inject` активовано лише для доповідачів. -Модифікація сервісів .[#toc-modification-of-services] -===================================================== +Модифікації сервісу .[#toc-service-modifications] +================================================= -У контейнері DI є низка сервісів, які були додані вбудованим або [вашим розширенням |#di-extension]. Визначення цих сервісів можуть бути змінені в конфігурації. Наприклад, для сервісу `application.application`, який за замовчуванням є об'єктом `Nette\Application\Application`, ми можемо змінити клас: +Контейнер DI містить багато сервісів, доданих за допомогою вбудованих або [користувацьких розширень |#extensions]. Ви можете змінювати визначення цих сервісів безпосередньо в конфігурації. Наприклад, ви можете змінити клас сервісу `application.application`, який умовно називається `Nette\Application\Application`, на щось інше: ```neon services: @@ -413,9 +399,9 @@ services: alteration: true ``` -Прапор `alteration` є інформативним і говорить про те, що ми просто змінюємо існуючий сервіс. +Прапорець `alteration` є інформативним, вказуючи на те, що ми просто змінюємо існуючий сервіс. -Ми також можемо додати `setup`: +Ми також можемо доповнити налаштування: ```neon services: @@ -426,7 +412,7 @@ services: - '$onStartup[]' = [@resource, init] ``` -Під час перезапису сервісу ми можемо видалити вихідні аргументи, елементи `setup` або теги, для яких `reset` є: +При перезаписуванні сервісу ви можете захотіти видалити оригінальні аргументи, елементи налаштувань або теги, і саме тут у нагоді стане `reset`: ```neon services: @@ -439,7 +425,7 @@ services: - tags ``` -Сервіс, доданий розширенням, також може бути видалено з контейнера: +Якщо ви хочете видалити сервіс, доданий розширенням, ви можете зробити це так: ```neon services: From 71f5cfb58069cefa7ec75fe0d52ae414f142983c Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sun, 15 Oct 2023 14:44:46 +0200 Subject: [PATCH 023/137] form validation: improved --- forms/bg/validation.texy | 30 +++++++++++++++++++++--------- forms/cs/validation.texy | 30 +++++++++++++++++++++--------- forms/de/validation.texy | 30 +++++++++++++++++++++--------- forms/el/validation.texy | 30 +++++++++++++++++++++--------- forms/en/validation.texy | 30 +++++++++++++++++++++--------- forms/es/validation.texy | 30 +++++++++++++++++++++--------- forms/fr/validation.texy | 30 +++++++++++++++++++++--------- forms/hu/validation.texy | 30 +++++++++++++++++++++--------- forms/it/validation.texy | 30 +++++++++++++++++++++--------- forms/pl/validation.texy | 30 +++++++++++++++++++++--------- forms/pt/validation.texy | 30 +++++++++++++++++++++--------- forms/ro/validation.texy | 30 +++++++++++++++++++++--------- forms/ru/validation.texy | 30 +++++++++++++++++++++--------- forms/sl/validation.texy | 30 +++++++++++++++++++++--------- forms/tr/validation.texy | 30 +++++++++++++++++++++--------- forms/uk/validation.texy | 30 +++++++++++++++++++++--------- 16 files changed, 336 insertions(+), 144 deletions(-) diff --git a/forms/bg/validation.texy b/forms/bg/validation.texy index 246cd77d16..6b0881de4e 100644 --- a/forms/bg/validation.texy +++ b/forms/bg/validation.texy @@ -23,9 +23,9 @@ $form->addPassword('password', 'Пароль:') ->addRule($form::MinLength, 'Пароль должен состоять не менее чем из %d символов', 8); ``` -Nette разполага с редица вградени правила, чиито имена са константи от класа `Nette\Forms\Form`: +**Правилата за валидиране се проверяват само ако потребителят е попълнил елемента.** -Можем да използваме следните правила за всички контроли: +Nette се предлага с редица предварително дефинирани правила, чиито имена са константи от класа `Nette\Forms\Form`. Можем да прилагаме тези правила към всички елементи: | константа | описание | аргументи |------- @@ -38,6 +38,10 @@ Nette разполага с редица вградени правила, чии | `IsNotIn` | стойността не е равна на нито един елемент от масива | `array` | `Valid` | записът преминава валидиране (за [Условие |#Условия]) | - + +Въвеждане на текст +------------------ + За елементите `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` могат да се приложат и някои от следните правила: | `MinLength` | минимална дължина на реда `int` @@ -57,6 +61,20 @@ Nette разполага с редица вградени правила, чии Правилата `Integer`, `Numeric` и `Float` автоматично преобразуват стойността в цяло число (или съответно в число с плаваща запетая). Освен това правилото `URL` приема и адрес без схема (напр. `nette.org`) и допълва схемата (`https://nette.org`). Изразите в `Pattern` и `PatternInsensitive` трябва да са валидни за цялата стойност, т.е. все едно са обвити в `^` и `$`. + +Брой на елементите .[#toc-number-of-items] +------------------------------------------ + +За елементите `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` можете да използвате и следните правила, за да ограничите броя на избраните елементи или качените файлове: + +| `MinLength` | минимален брой | `int` +| `MaxLength` | максимален брой | `int` +| `Length` | брой в диапазон или точен брой | двойки `[int, int]` или `int` + + +Качване на файлове +------------------ + Следните правила могат да се използват и за контроли `addUpload()`, `addMultiUpload()`: | `MaxFileSize` | максимален размер на файла | `int` @@ -67,15 +85,9 @@ Nette разполага с редица вградени правила, чии За `MimeType` и `Image` се изисква разширението на PHP `fileinfo`. Правилният тип на файла или изображението се определя от неговия подпис. Целостта на целия файл не се проверява. Можете да проверите дали дадено изображение е повредено, например като се опитате да [го заредите |http:request#toImage]. -За контролите `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` могат да се използват и следните правила, за да се ограничи броят на избраните елементи, съответно изтеглените файлове: - -| `MinLength` | минимален брой | `int` -| `MaxLength` | максимален брой | `int` -| `Length` | сума в диапазон или точна сума | параграф `[int, int]` или `int` - Съобщения за грешки .[#toc-error-messages] ------------------------------------------- +========================================== Всички предварително дефинирани правила, с изключение на `Pattern` и `PatternInsensitive`, имат съобщение за грешка по подразбиране, така че можете да ги пропуснете. Въпреки това, като предавате и формулирате всички отделни съобщения, ще направите формуляра по-удобен за ползване. diff --git a/forms/cs/validation.texy b/forms/cs/validation.texy index fd4179c8de..300f13d6e1 100644 --- a/forms/cs/validation.texy +++ b/forms/cs/validation.texy @@ -23,9 +23,9 @@ $form->addPassword('password', 'Heslo:') ->addRule($form::MinLength, 'Heslo musí mít alespoň %d znaků', 8); ``` -Nette přichází s celou řadu předdefinovaných pravidel, jejichž názvy jsou konstanty třídy `Nette\Forms\Form`. +**Validační pravidla se ověřují pouze v případě, že uživatel prvek vyplnil.** -U všech prvků můžeme použít tyto pravidla: +Nette přichází s celou řadu předdefinovaných pravidel, jejichž názvy jsou konstanty třídy `Nette\Forms\Form`. U všech prvků můžeme použít tyto pravidla: | konstanta | popis | typ argumentu |------- @@ -38,6 +38,10 @@ U všech prvků můžeme použít tyto pravidla: | `IsNotIn` | hodnota se nerovná žádné položce v poli | `array` | `Valid` | je prvek vyplněn správně? (pro [#podmínky]) | - + +Textové vstupy +-------------- + U prvků `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` lze použít i některá následující pravidla: | `MinLength` | minimální délka textu | `int` @@ -57,6 +61,20 @@ U prvků `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addIntege Validační pravidla `Integer`, `Numeric` a `Float` rovnou převádí hodnotu na integer resp. float. A dále pravidlo `URL` akceptuje i adresu bez schématu (např. `nette.org`) a schéma doplní (`https://nette.org`). Výraz v `Pattern` a `PatternIcase` musí platit pro celou hodnotu, tj. jako by byl obalen znaky `^` a `$`. + +Počet položek +------------- + +U prvků `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` lze použít i následující pravidla pro omezení počtu vybraných položek resp. uploadovaných souborů: + +| `MinLength` | minimální počet | `int` +| `MaxLength` | maximální počet | `int` +| `Length` | počet v rozsahu nebo přesný počet | dvojice `[int, int]` nebo `int` + + +Upload souborů +-------------- + U prvků `addUpload()`, `addMultiUpload()` lze použít i následující pravidla: | `MaxFileSize` | maximální velikost souboru | `int` @@ -67,15 +85,9 @@ U prvků `addUpload()`, `addMultiUpload()` lze použít i následující pravidl `MimeType` a `Image` vyžadují PHP rozšíření `fileinfo`. Že je soubor či obrázek požadovaného typu detekují na základě jeho signatury a **neověřují integritu celého souboru.** Zda není obrázek poškozený lze zjistit například pokusem o jeho [načtení|http:request#toImage]. -U prvků `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` lze použít i následující pravidla pro omezení počtu vybraných položek resp. uploadovaných souborů: - -| `MinLength` | minimální počet | `int` -| `MaxLength` | maximální počet | `int` -| `Length` | počet v rozsahu nebo přesný počet | dvojice `[int, int]` nebo `int` - Chybové hlášky --------------- +============== Všechny předdefinované pravidla s výjimkou `Pattern` a `PatternInsensitive` mají výchozí chybovou hlášku, takže ji lze vynechat. Nicméně uvedením a formulací všech hlášek na míru uděláte formulář uživatelsky přívětivější. diff --git a/forms/de/validation.texy b/forms/de/validation.texy index ea282ded2f..5bbcdb66e5 100644 --- a/forms/de/validation.texy +++ b/forms/de/validation.texy @@ -23,9 +23,9 @@ $form->addPassword('password', 'Password:') ->addRule($form::MinLength, 'Password must be at least %d characters', 8); ``` -Nette verfügt über eine Reihe von eingebauten Regeln, deren Namen Konstanten der Klasse `Nette\Forms\Form` sind: +**Validierungsregeln werden nur dann überprüft, wenn der Benutzer das Element ausgefüllt hat.** -Wir können die folgenden Regeln für alle Steuerelemente verwenden: +Nette verfügt über eine Reihe von vordefinierten Regeln, deren Namen Konstanten der Klasse `Nette\Forms\Form` sind. Wir können diese Regeln auf alle Elemente anwenden: | Konstante | Beschreibung | Argumente |------- @@ -38,6 +38,10 @@ Wir können die folgenden Regeln für alle Steuerelemente verwenden: | `IsNotIn` | Wert ist nicht gleich einem Element im Array | `array` | `Valid` | Eingabe besteht Validierung (für [Bedingungen |#conditions]) | - + +Texteingaben +------------ + Für die Elemente `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` können auch einige der folgenden Regeln angewendet werden: | `MinLength` | minimale Stringlänge | `int` @@ -57,6 +61,20 @@ Für die Elemente `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, ` Die Regeln `Integer`, `Numeric` und `Float` konvertieren den Wert automatisch in Ganzzahl (bzw. Gleitkommazahl). Außerdem akzeptiert die Regel `URL` auch eine Adresse ohne Schema (z. B. `nette.org`) und vervollständigt das Schema (`https://nette.org`). Die Ausdrücke in `Pattern` und `PatternInsensitive` müssen für den gesamten Wert gültig sein, d. h. so, als ob er in die Zeichen `^` and `$` eingeschlossen wäre. + +Anzahl der Artikel .[#toc-number-of-items] +------------------------------------------ + +Für die Elemente `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` können Sie auch die folgenden Regeln verwenden, um die Anzahl der ausgewählten Elemente oder hochgeladenen Dateien zu begrenzen: + +| `MinLength` | Mindestanzahl | `int` +| `MaxLength` | maximale Anzahl | `int` +| `Length` | Anzahl im Bereich oder genaue Anzahl | Paare `[int, int]` oder `int` + + +Datei hochladen +--------------- + Für die Steuerelemente `addUpload()`, `addMultiUpload()` können auch die folgenden Regeln verwendet werden: | `MaxFileSize` | maximale Dateigröße | `int` @@ -67,15 +85,9 @@ Für die Steuerelemente `addUpload()`, `addMultiUpload()` können auch die folge Für `MimeType` und `Image` ist die PHP-Erweiterung `fileinfo` erforderlich. Ob eine Datei oder ein Bild dem erforderlichen Typ entspricht, wird anhand ihrer Signatur erkannt. Die Integrität der gesamten Datei wird nicht geprüft. Sie können herausfinden, ob ein Bild nicht beschädigt ist, indem Sie beispielsweise versuchen, [es zu laden |http:request#toImage]. -Für die Steuerelemente `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` können auch die folgenden Regeln verwendet werden, um die Anzahl der ausgewählten Elemente bzw. hochgeladenen Dateien zu begrenzen: - -| `MinLength` | minimale Anzahl | `int` -| `MaxLength` | maximale Anzahl | `int` -| `Length` | Anzahl im Bereich oder genaue Anzahl | Paar `[int, int]` oder `int` - Fehlermeldungen .[#toc-error-messages] --------------------------------------- +====================================== Alle vordefinierten Regeln außer `Pattern` und `PatternInsensitive` haben eine Standard-Fehlermeldung, so dass sie weggelassen werden können. Wenn Sie jedoch alle benutzerdefinierten Meldungen übergeben und formulieren, wird das Formular benutzerfreundlicher. diff --git a/forms/el/validation.texy b/forms/el/validation.texy index cfb89effb6..2ae2e83d6e 100644 --- a/forms/el/validation.texy +++ b/forms/el/validation.texy @@ -23,9 +23,9 @@ $form->addPassword('password', 'Password:') ->addRule($form::MinLength, 'Password must be at least %d characters', 8); ``` -Η Nette έρχεται με έναν αριθμό ενσωματωμένων κανόνων των οποίων τα ονόματα είναι σταθερές της κλάσης `Nette\Forms\Form`: +**Οι κανόνες επαλήθευσης ελέγχονται μόνο αν ο χρήστης συμπλήρωσε το στοιχείο.** -Μπορούμε να χρησιμοποιήσουμε τους ακόλουθους κανόνες για όλα τα στοιχεία ελέγχου: +Η Nette διαθέτει έναν αριθμό προκαθορισμένων κανόνων, τα ονόματα των οποίων είναι σταθερές της κλάσης `Nette\Forms\Form`. Μπορούμε να εφαρμόσουμε αυτούς τους κανόνες σε όλα τα στοιχεία: | σταθερά | περιγραφή | επιχειρήματα |------- @@ -38,6 +38,10 @@ $form->addPassword('password', 'Password:') | `IsNotIn` | η τιμή δεν είναι ίση με κάποιο στοιχείο του πίνακα | `array` | `Valid` | η είσοδος περνάει την επικύρωση (για τις [συνθήκες |#conditions]) | - + +Είσοδοι κειμένου +---------------- + Για τα στοιχεία `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` μπορούν επίσης να εφαρμοστούν ορισμένοι από τους ακόλουθους κανόνες: | `MinLength` | ελάχιστο μήκος συμβολοσειράς | `int` @@ -57,6 +61,20 @@ $form->addPassword('password', 'Password:') Οι κανόνες `Integer`, `Numeric` και `Float` μετατρέπουν αυτόματα την τιμή σε ακέραιο (ή float αντίστοιχα). Επιπλέον, ο κανόνας `URL` δέχεται επίσης μια διεύθυνση χωρίς σχήμα (π.χ. `nette.org`) και συμπληρώνει το σχήμα (`https://nette.org`). Οι εκφράσεις στους κανόνες `Pattern` και `PatternInsensitive` πρέπει να ισχύουν για ολόκληρη την τιμή, δηλαδή σαν να ήταν τυλιγμένη στους χαρακτήρες `^` and `$`. + +Αριθμός στοιχείων .[#toc-number-of-items] +----------------------------------------- + +Για τα στοιχεία `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` μπορείτε επίσης να χρησιμοποιήσετε τους ακόλουθους κανόνες για να περιορίσετε τον αριθμό των επιλεγμένων στοιχείων ή των ανεβασμένων αρχείων: + +| `MinLength` | ελάχιστος αριθμός | `int` +| `MaxLength` | μέγιστος αριθμός | `int` +| `Length` | αριθμός σε εύρος ή ακριβής αριθμός | ζεύγη `[int, int]` ή `int` + + +Ανέβασμα αρχείου +---------------- + Για τους ελέγχους `addUpload()`, `addMultiUpload()` μπορούν επίσης να χρησιμοποιηθούν οι ακόλουθοι κανόνες: | `MaxFileSize` | μέγιστο μέγεθος αρχείου | `int` @@ -67,15 +85,9 @@ $form->addPassword('password', 'Password:') Τα `MimeType` και `Image` απαιτούν την επέκταση PHP `fileinfo`. Το αν ένα αρχείο ή μια εικόνα είναι του απαιτούμενου τύπου ανιχνεύεται από την υπογραφή του. Η ακεραιότητα ολόκληρου του αρχείου δεν ελέγχεται. Μπορείτε να διαπιστώσετε αν μια εικόνα δεν είναι κατεστραμμένη, για παράδειγμα, προσπαθώντας να [τη φορτώσετε |http:request#toImage]. -Για τα στοιχεία ελέγχου `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` μπορούν επίσης να χρησιμοποιηθούν οι ακόλουθοι κανόνες για τον περιορισμό του αριθμού των επιλεγμένων στοιχείων, αντίστοιχα των φορτωμένων αρχείων: - -| `MinLength` | minimal count | `int` -| `MaxLength` | μέγιστος αριθμός | `int` -| `Length` | count in range or exact count | ζεύγος `[int, int]` ή `int` - Μηνύματα σφάλματος .[#toc-error-messages] ------------------------------------------ +========================================= Όλοι οι προκαθορισμένοι κανόνες εκτός από τους `Pattern` και `PatternInsensitive` έχουν ένα προεπιλεγμένο μήνυμα σφάλματος, οπότε μπορούν να παραλειφθούν. Ωστόσο, περνώντας και διατυπώνοντας όλα τα προσαρμοσμένα μηνύματα, θα κάνετε τη φόρμα πιο φιλική προς το χρήστη. diff --git a/forms/en/validation.texy b/forms/en/validation.texy index 58db4d7535..684510f24b 100644 --- a/forms/en/validation.texy +++ b/forms/en/validation.texy @@ -23,9 +23,9 @@ $form->addPassword('password', 'Password:') ->addRule($form::MinLength, 'Password must be at least %d characters', 8); ``` -Nette comes with a number of built-in rules whose names are constants of the `Nette\Forms\Form` class: +**Validation rules are checked only if the user filled in the element.** -We can use the following rules for all controls: +Nette comes with a number of predefined rules whose names are constants of the class `Nette\Forms\Form`. We can apply these rules to all elements: | constant | description | arguments |------- @@ -38,6 +38,10 @@ We can use the following rules for all controls: | `IsNotIn` | value does not equal any element in the array | `array` | `Valid` | input passes validation (for [#conditions]) | - + +Text inputs +----------- + For elements `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` some of the following rules can also be applied: | `MinLength` | minimal string length | `int` @@ -57,6 +61,20 @@ For elements `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addIn The `Integer`, `Numeric` a `Float` rules automatically convert the value to integer (or float respectively). Furthermore, the `URL` rule also accepts an address without a schema (eg `nette.org`) and completes the schema (`https://nette.org`). The expressions in `Pattern` and `PatternInsensitive` must be valid for the whole value, ie as if it were wrapped in the characters `^` and `$`. + +Number of Items +--------------- + +For the elements `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` you can also use the following rules to limit the number of selected items or uploaded files: + +| `MinLength` | minimum number | `int` +| `MaxLength` | maximum number | `int` +| `Length` | number in range or exact number | pairs `[int, int]` or `int` + + +File Upload +----------- + For controls `addUpload()`, `addMultiUpload()` the following rules can also be used: | `MaxFileSize` | maximal file size | `int` @@ -67,15 +85,9 @@ For controls `addUpload()`, `addMultiUpload()` the following rules can also be u The `MimeType` and `Image` require PHP extension `fileinfo`. Whether a file or image is of the required type is detected by its signature. The integrity of the entire file is not checked. You can find out if an image is not corrupted for example by trying to [load it|http:request#toImage]. -For controls `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` the following rules can also be used to limit the number of selected items, respectively uploaded files: - -| `MinLength` | minimal count | `int` -| `MaxLength` | maximal count | `int` -| `Length` | count in range or exact count | pair `[int, int]` or `int` - Error Messages --------------- +============== All predefined rules except `Pattern` and `PatternInsensitive` have a default error message, so they it be omitted. However, by passing and formulating all customized messages, you will make the form more user-friendly. diff --git a/forms/es/validation.texy b/forms/es/validation.texy index dee7fac958..51896dd549 100644 --- a/forms/es/validation.texy +++ b/forms/es/validation.texy @@ -23,9 +23,9 @@ $form->addPassword('password', 'Contraseña:') ->addRule($form::MinLength, 'La contraseña debe tener al menos %d caracteres', 8); ``` -Nette viene con una serie de reglas incorporadas cuyos nombres son constantes de la clase `Nette\Forms\Form`: +**Las reglas de validación sólo se comprueban si el usuario ha rellenado el elemento. -Podemos utilizar las siguientes reglas para todos los controles: +Nette viene con una serie de reglas predefinidas cuyos nombres son constantes de la clase `Nette\Forms\Form`. Podemos aplicar estas reglas a todos los elementos: | constante | descripción | argumentos |------- @@ -38,6 +38,10 @@ Podemos utilizar las siguientes reglas para todos los controles: | `IsNotIn` | El valor no es igual a ningún elemento de la matriz. `array` | `Valid` | la entrada pasa la validación (para [condiciones |#conditions]) | - + +Entradas de texto +----------------- + Para los elementos `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` también se pueden aplicar algunas de las siguientes reglas: | `MinLength` | longitud mínima de cadena | `int` @@ -57,6 +61,20 @@ Para los elementos `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, Las reglas `Integer`, `Numeric` a `Float` convierten automáticamente el valor a entero (o flotante respectivamente). Además, la regla `URL` también acepta una dirección sin esquema (por ejemplo, `nette.org`) y completa el esquema (`https://nette.org`). Las expresiones de `Pattern` y `PatternInsensitive` deben ser válidas para todo el valor, es decir, como si estuviera envuelto en los caracteres `^` and `$`. + +Número de artículos .[#toc-number-of-items] +------------------------------------------- + +Para los elementos `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` también puede utilizar las siguientes reglas para limitar el número de elementos seleccionados o archivos cargados: + +| `MinLength` | número mínimo | `int` +| `MaxLength` Número máximo `int` +| `Length` | número en rango o número exacto | pares `[int, int]` o `int` + + +Carga de archivos +----------------- + Para los controles `addUpload()`, `addMultiUpload()` también se pueden utilizar las siguientes reglas: | `MaxFileSize` | tamaño máximo del archivo | `int` @@ -67,15 +85,9 @@ Para los controles `addUpload()`, `addMultiUpload()` también se pueden utilizar `MimeType` y `Image` requieren la extensión PHP `fileinfo`. Si un archivo o imagen es del tipo requerido se detecta por su firma. No se comprueba la integridad de todo el archivo. Puede averiguar si una imagen no está dañada, por ejemplo, intentando [cargarla |http:request#toImage]. -Para los controles `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` también se pueden utilizar las siguientes reglas para limitar el número de elementos seleccionados, respectivamente archivos cargados: - -| `MinLength` | recuento mínimo | `int` -| `MaxLength` | recuento máximo `int` -| `Length` | recuento en rango o recuento exacto | par `[int, int]` o `int` - Mensajes de error .[#toc-error-messages] ----------------------------------------- +======================================== Todas las reglas predefinidas excepto `Pattern` y `PatternInsensitive` tienen un mensaje de error por defecto, por lo que pueden omitirse. Sin embargo, al pasar y formular todos los mensajes personalizados, hará que el formulario sea más fácil de usar. diff --git a/forms/fr/validation.texy b/forms/fr/validation.texy index 3ba5a0e0cf..aa78326bed 100644 --- a/forms/fr/validation.texy +++ b/forms/fr/validation.texy @@ -23,9 +23,9 @@ $form->addPassword('password', 'Password:') ->addRule($form::MinLength, 'Password must be at least %d characters', 8); ``` -Nette est livré avec un certain nombre de règles intégrées dont les noms sont des constantes de la classe `Nette\Forms\Form`: +**Les règles de validation ne sont vérifiées que si l'utilisateur a rempli l'élément. -Nous pouvons utiliser les règles suivantes pour tous les contrôles : +Nette est livré avec un certain nombre de règles prédéfinies dont les noms sont des constantes de la classe `Nette\Forms\Form`. Nous pouvons appliquer ces règles à tous les éléments : | constante | description | arguments |------- @@ -38,6 +38,10 @@ Nous pouvons utiliser les règles suivantes pour tous les contrôles : | `IsNotIn` | la valeur n'est égale à aucun élément du tableau | `array` | `Valid` | L'entrée passe la validation (pour les [conditions |#conditions]) | - + +Entrées de texte +---------------- + Pour les éléments `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()`, certaines des règles suivantes peuvent également être appliquées : | `MinLength` | longueur minimale de la chaîne | `int` @@ -57,6 +61,20 @@ Pour les éléments `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, Les règles `Integer`, `Numeric` et `Float` convertissent automatiquement la valeur en nombre entier (ou flottant respectivement). En outre, la règle `URL` accepte également une adresse sans schéma (par exemple `nette.org`) et complète le schéma (`https://nette.org`). Les expressions de `Pattern` et `PatternInsensitive` doivent être valables pour la valeur entière, c'est-à-dire comme si elle était enveloppée dans les caractères `^` and `$`. + +Nombre d'articles .[#toc-number-of-items] +----------------------------------------- + +Pour les éléments `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` vous pouvez également utiliser les règles suivantes pour limiter le nombre d'éléments sélectionnés ou de fichiers téléchargés : + + `MinLength` | nombre minimum | | nombre maximum `int` +| `MaxLength` | nombre maximum `int` +| `Length` | nombre dans l'intervalle ou nombre exact | paires `[int, int]` ou `int` + + +Téléchargement de fichiers +-------------------------- + Pour les contrôles `addUpload()`, `addMultiUpload()`, les règles suivantes peuvent également être utilisées : | `MaxFileSize` | taille maximale du fichier | `int` @@ -67,15 +85,9 @@ Pour les contrôles `addUpload()`, `addMultiUpload()`, les règles suivantes peu Les sites `MimeType` et `Image` nécessitent l'extension PHP `fileinfo`. Le fait qu'un fichier ou une image soit du type requis est détecté par sa signature. L'intégrité de l'ensemble du fichier n'est pas vérifiée. Vous pouvez savoir si une image n'est pas corrompue, par exemple en essayant de [la charger |http:request#toImage]. -Pour les contrôles `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()`, les règles suivantes peuvent également être utilisées pour limiter le nombre d'éléments sélectionnés, respectivement de fichiers téléchargés : - -| `MinLength` | compte minimal | `int` -| `MaxLength` | compte maximal | `int` -| `Length` | compte dans l'intervalle ou compte exact | paire `[int, int]` ou `int` - Messages d'erreur .[#toc-error-messages] ----------------------------------------- +======================================== Toutes les règles prédéfinies, à l'exception de `Pattern` et `PatternInsensitive`, ont un message d'erreur par défaut ; elles peuvent donc être omises. Toutefois, en passant et en formulant tous les messages personnalisés, vous rendrez le formulaire plus convivial. diff --git a/forms/hu/validation.texy b/forms/hu/validation.texy index 30b92e0171..1a042600bc 100644 --- a/forms/hu/validation.texy +++ b/forms/hu/validation.texy @@ -23,9 +23,9 @@ $form->addPassword('password', 'Password:') ->addRule($form::MinLength, 'Password must be at least %d characters', 8); ``` -A Nette számos beépített szabályt tartalmaz, amelyek neve a `Nette\Forms\Form` osztály konstansa: +**A hitelesítési szabályok csak akkor kerülnek ellenőrzésre, ha a felhasználó kitöltötte az elemet.** -A következő szabályokat használhatjuk az összes vezérlőelemhez: +A Nette számos előre definiált szabályt tartalmaz, amelyek neve a `Nette\Forms\Form` osztály konstanciái. Ezeket a szabályokat minden elemre alkalmazhatjuk: | konstans | leírás | érvek |------- @@ -38,6 +38,10 @@ A következő szabályokat használhatjuk az összes vezérlőelemhez: | `IsNotIn` | érték nem egyenlő a tömb egyetlen elemével sem | `array` | `Valid` | a bemenet átmegy az érvényesítésen ( [feltételek |#conditions] esetén) | - + +Szöveges bemenetek +------------------ + A `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` elemekre a következő szabályok közül néhányat is lehet alkalmazni: | `MinLength` | minimális karakterlánc-hossz | `int` @@ -57,6 +61,20 @@ A `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, ` A `Integer`, `Numeric` és `Float` szabályok automatikusan egész számra (illetve lebegőszámra) konvertálják az értéket. Továbbá a `URL` szabály elfogad egy séma nélküli címet is (pl. `nette.org`), és kiegészíti a sémát (`https://nette.org`). A `Pattern` és a `PatternInsensitive` kifejezéseknek a teljes értékre érvényesnek kell lenniük, azaz mintha a `^` and `$` karakterekbe lenne csomagolva. + +Tételek száma .[#toc-number-of-items] +------------------------------------- + +A `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` elemek esetében a következő szabályokkal is korlátozhatja a kiválasztott elemek vagy feltöltött fájlok számát: + +| `MinLength` | minimális szám | `int` +| `MaxLength` | maximális szám | `int` +| `Length` | szám tartományon belül vagy pontos szám | párok `[int, int]` vagy `int` + + +Fájl feltöltés +-------------- + A `addUpload()`, `addMultiUpload()` vezérlőkre a következő szabályok is alkalmazhatók: | `MaxFileSize` | maximális fájlméret | `int` @@ -67,15 +85,9 @@ A `addUpload()`, `addMultiUpload()` vezérlőkre a következő szabályok is alk A `MimeType` és a `Image` a `fileinfo` PHP kiterjesztést igényli. Az, hogy egy fájl vagy kép a kívánt típusba tartozik-e, az aláírás alapján állapítható meg. A teljes fájl sértetlenségét nem ellenőrzi a rendszer. Azt, hogy egy kép nem sérült-e, például úgy lehet megállapítani, ha megpróbáljuk [betölteni |http:request#toImage]. -A `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` vezérlőkhöz a következő szabályok is használhatók a kiválasztott elemek, illetve a feltöltött fájlok számának korlátozására: - -| `MinLength` | minimális szám | `int` -| `MaxLength` | maximális szám | `int` -| `Length` | szám a tartományban vagy pontos szám | pár `[int, int]` vagy `int` - Hibaüzenetek .[#toc-error-messages] ------------------------------------ +=================================== A `Pattern` és a `PatternInsensitive` kivételével minden előre definiált szabály rendelkezik alapértelmezett hibaüzenettel, így ezek elhagyhatók. Az összes testreszabott üzenet átadásával és megfogalmazásával azonban felhasználóbarátabbá teszi az űrlapot. diff --git a/forms/it/validation.texy b/forms/it/validation.texy index 7de87fa18d..b2c3c91c2d 100644 --- a/forms/it/validation.texy +++ b/forms/it/validation.texy @@ -23,9 +23,9 @@ $form->addPassword('password', 'Password:') ->addRule($form::MinLength, 'Password must be at least %d characters', 8); ``` -Nette dispone di una serie di regole incorporate, i cui nomi sono costanti della classe `Nette\Forms\Form`: +**Le regole di validazione vengono controllate solo se l'utente ha compilato l'elemento **. -Possiamo utilizzare le seguenti regole per tutti i controlli: +Nette dispone di una serie di regole predefinite i cui nomi sono costanti della classe `Nette\Forms\Form`. Possiamo applicare queste regole a tutti gli elementi: | costante | descrizione | argomenti |------- @@ -38,6 +38,10 @@ Possiamo utilizzare le seguenti regole per tutti i controlli: | `IsNotIn` | il valore non è uguale a nessun elemento dell'array | `array` | `Valid` | l'input supera la convalida (per le [condizioni |#conditions]) | - + +Ingressi di testo +----------------- + Per gli elementi `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` si possono applicare anche alcune delle seguenti regole: | `MinLength` | lunghezza minima della stringa | `int` @@ -57,6 +61,20 @@ Per gli elementi `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `a Le regole `Integer`, `Numeric` e `Float` convertono automaticamente il valore in numero intero (o in virgola mobile, rispettivamente). Inoltre, la regola `URL` accetta anche un indirizzo senza schema (ad esempio `nette.org`) e completa lo schema (`https://nette.org`). Le espressioni in `Pattern` e `PatternInsensitive` devono essere valide per l'intero valore, cioè come se fosse avvolto nei caratteri `^` and `$`. + +Numero di articoli .[#toc-number-of-items] +------------------------------------------ + +Per gli elementi `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` è possibile utilizzare anche le seguenti regole per limitare il numero di elementi selezionati o di file caricati: + +| `MinLength` | numero minimo | `int` +| `MaxLength` | numero massimo | `int` +| `Length` | numero nell'intervallo o numero esatto | coppie `[int, int]` o `int` + + +Caricamento file +---------------- + Per i controlli `addUpload()`, `addMultiUpload()` si possono utilizzare anche le seguenti regole: | `MaxFileSize` | dimensione massima del file | `int` @@ -67,15 +85,9 @@ Per i controlli `addUpload()`, `addMultiUpload()` si possono utilizzare anche le `MimeType` e `Image` richiedono l'estensione PHP `fileinfo`. Il fatto che un file o un'immagine sia del tipo richiesto viene rilevato dalla sua firma. L'integrità dell'intero file non viene controllata. È possibile scoprire se un'immagine non è danneggiata, ad esempio provando a [caricarla |http:request#toImage]. -Per i controlli `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` è possibile utilizzare le seguenti regole per limitare il numero di elementi selezionati, rispettivamente di file caricati: - -| `MinLength` | conteggio minimo | `int` -| `MaxLength` | conteggio massimo | `int` -| `Length` | conteggio nell'intervallo o conteggio esatto | coppia `[int, int]` o `int` - Messaggi di errore .[#toc-error-messages] ------------------------------------------ +========================================= Tutte le regole predefinite, tranne `Pattern` e `PatternInsensitive`, hanno un messaggio di errore predefinito, quindi possono essere omesse. Tuttavia, passando e formulando tutti i messaggi personalizzati, si renderà il modulo più facile da usare. diff --git a/forms/pl/validation.texy b/forms/pl/validation.texy index 1c04ec9a97..02b0a1d8ec 100644 --- a/forms/pl/validation.texy +++ b/forms/pl/validation.texy @@ -23,9 +23,9 @@ $form->addPassword('password', 'Heslo:') ->addRule($form::MinLength, 'Heslo musí mít alespoň %d znaků', 8); ``` -Nette posiada szereg predefiniowanych reguł, których nazwy są stałymi klasy `Nette\Forms\Form`. +**Reguły walidacji są sprawdzane tylko wtedy, gdy użytkownik wypełnił dany element. -Zasady te możemy stosować dla wszystkich elementów: +Nette posiada szereg predefiniowanych reguł, których nazwy są stałymi klasy `Nette\Forms\Form`. Możemy zastosować te reguły do wszystkich elementów: | stały | opis | typ argumentu |------- @@ -38,6 +38,10 @@ Zasady te możemy stosować dla wszystkich elementów: | `IsNotIn` | wartość nie jest równa żadnej pozycji w tablicy |. `array` | `Valid` | czy element został wypełniony poprawnie? (dla [warunków |#Conditions]) | - + +Wejścia tekstowe +---------------- + W przypadku elementów `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` można również zastosować niektóre z poniższych reguł: | `MinLength` | minimalna długość tekstu | `int` @@ -57,6 +61,20 @@ W przypadku elementów `addText()`, `addPassword()`, `addTextArea()`, `addEmail( Reguły walidacji `Integer`, `Numeric` i `Float` bezpośrednio konwertują wartość na liczbę całkowitą i float odpowiednio. Ponadto reguła `URL` przyjmuje adres bez schematu (np. `nette.org`) i dodaje schemat (`https://nette.org`). Wyrażenie w `Pattern` i `PatternIcase` musi być ważne dla całej wartości, czyli tak jakby było zawinięte przez `^` a `$`. + +Liczba elementów .[#toc-number-of-items] +---------------------------------------- + +W przypadku elementów `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` można również użyć następujących reguł, aby ograniczyć liczbę wybranych elementów lub przesłanych plików: + +| `MinLength` | minimalna liczba | `int` +| `MaxLength` | maksymalna liczba | `int` +| `Length` | liczba w zakresie lub dokładna liczba | pary `[int, int]` lub `int` + + +Przesyłanie plików +------------------ + Poniższe zasady mogą być również stosowane dla elementów `addUpload()`, `addMultiUpload()`: | `MaxFileSize` | maksymalny rozmiar pliku | `int` @@ -67,15 +85,9 @@ Poniższe zasady mogą być również stosowane dla elementów `addUpload()`, `a `MimeType` i `Image` wymagają rozszerzenia PHP `fileinfo`. Wykrywają one, że plik lub obraz jest pożądanego typu na podstawie jego sygnatury i **nie sprawdzają integralności całego pliku.** Możesz powiedzieć, czy obraz jest uszkodzony, próbując go [załadować |http:request#toImage], na przykład. -Dla elementów `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` można również zastosować następujące reguły, aby ograniczyć liczbę wybranych elementów lub przesłanych plików: - -| `MinLength` | minimalna liczba | `int` -| `MaxLength` | maksymalna liczba | `int` -| `Length` | liczba w zakresie lub dokładna liczba | par `[int, int]` lub `int` - Komunikaty o błędach .[#toc-error-messages] -------------------------------------------- +=========================================== Wszystkie predefiniowane reguły oprócz `Pattern` i `PatternInsensitive` mają domyślny komunikat o błędzie, więc można go pominąć. Jednak wymieniając i formułując wszystkie wiadomości w niestandardowy sposób, sprawisz, że formularz będzie bardziej przyjazny dla użytkownika. diff --git a/forms/pt/validation.texy b/forms/pt/validation.texy index ab9e50be73..959ad82fff 100644 --- a/forms/pt/validation.texy +++ b/forms/pt/validation.texy @@ -23,9 +23,9 @@ $form->addPassword('password', 'Password:') ->addRule($form::MinLength, 'Password must be at least %d characters', 8); ``` -Nette vem com uma série de regras embutidas cujos nomes são constantes da classe `Nette\Forms\Form`: +**As regras de validação são verificadas somente se o usuário tiver preenchido o elemento. -Podemos utilizar as seguintes regras para todos os controles: +O Nette vem com várias regras predefinidas cujos nomes são constantes da classe `Nette\Forms\Form`. Podemos aplicar essas regras a todos os elementos: | constante | descrição | argumentos |------- @@ -38,6 +38,10 @@ Podemos utilizar as seguintes regras para todos os controles: | `IsNotIn` | valor não é igual a nenhum elemento da matriz | `array` | `Valid` | validação dos passes de entrada (para [condições |#conditions]) | - + +Entradas de texto +----------------- + Para os elementos `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()`, algumas das regras a seguir também podem ser aplicadas: | `MinLength` | comprimento mínimo das cordas | `int` @@ -57,6 +61,20 @@ Para os elementos `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, ` As regras `Integer`, `Numeric` a `Float` convertem automaticamente o valor em inteiro (ou float, respectivamente). Além disso, a regra `URL` também aceita um endereço sem esquema (por exemplo `nette.org`) e completa o esquema (`https://nette.org`). As expressões em `Pattern` e `PatternInsensitive` devem ser válidas para todo o valor, ou seja, como se estivesse embrulhado nos caracteres `^` and `$`. + +Número de itens .[#toc-number-of-items] +--------------------------------------- + +Para os elementos `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` você também pode usar as seguintes regras para limitar o número de itens selecionados ou arquivos carregados: + +| `MinLength` | número mínimo | `int` +| `MaxLength` | número máximo | `int` +| `Length` | número no intervalo ou número exato | pares `[int, int]` ou `int` + + +Upload de arquivos +------------------ + Para controles `addUpload()`, `addMultiUpload()` as seguintes regras também podem ser usadas: | `MaxFileSize` | tamanho máximo do arquivo | `int` @@ -67,15 +85,9 @@ Para controles `addUpload()`, `addMultiUpload()` as seguintes regras também pod Os sites `MimeType` e `Image` requerem extensão PHP `fileinfo`. Se um arquivo ou imagem é do tipo requerido é detectado por sua assinatura. A integridade do arquivo inteiro não é verificada. Você pode descobrir se uma imagem não está corrompida, por exemplo, ao tentar [carregá-la |http:request#toImage]. -Para os controles `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` as seguintes regras também podem ser usadas para limitar o número de itens selecionados, respectivamente arquivos carregados: - -| `MinLength` | contagem mínima | `int` -| `MaxLength` | contagem máxima | `int` -| `Length` | contagem no intervalo ou contagem exata | par `[int, int]` ou `int` - Mensagens de erro .[#toc-error-messages] ----------------------------------------- +======================================== Todas as regras predefinidas, exceto `Pattern` e `PatternInsensitive`, têm uma mensagem de erro padrão, portanto, ela é omitida. Entretanto, ao passar e formular todas as mensagens personalizadas, você tornará o formulário mais fácil de usar. diff --git a/forms/ro/validation.texy b/forms/ro/validation.texy index b40fd76d8e..4e100b2877 100644 --- a/forms/ro/validation.texy +++ b/forms/ro/validation.texy @@ -23,9 +23,9 @@ $form->addPassword('password', 'Password:') ->addRule($form::MinLength, 'Password must be at least %d characters', 8); ``` -Nette vine cu un număr de reguli încorporate ale căror nume sunt constante ale clasei `Nette\Forms\Form`: +**Regula de validare este verificată numai dacă utilizatorul a completat elementul.** -Putem utiliza următoarele reguli pentru toate controalele: +Nette vine cu un număr de reguli predefinite ale căror nume sunt constante din clasa `Nette\Forms\Form`. Putem aplica aceste reguli la toate elementele: | constantă | descriere | argumente |------- @@ -38,6 +38,10 @@ Putem utiliza următoarele reguli pentru toate controalele: | `IsNotIn` | valoarea nu este egală cu nici un element din matrice | `array` | `Valid` | input passes validation (for [conditions |#conditions]) | - + +Intrări de text +--------------- + Pentru elementele `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` se pot aplica, de asemenea, unele dintre următoarele reguli: | `MinLength` | lungime minimă a șirului de caractere | `int` @@ -57,6 +61,20 @@ Pentru elementele `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, ` Regulile `Integer`, `Numeric` și `Float` convertesc automat valoarea în număr întreg (sau, respectiv, flotant). În plus, regula `URL` acceptă și o adresă fără o schemă (de exemplu, `nette.org`) și completează schema (`https://nette.org`). Expresiile din `Pattern` și `PatternInsensitive` trebuie să fie valabile pentru întreaga valoare, adică ca și cum ar fi înfășurată în caracterele `^` and `$`. + +Număr de articole .[#toc-number-of-items] +----------------------------------------- + +Pentru elementele `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` puteți utiliza, de asemenea, următoarele reguli pentru a limita numărul de elemente selectate sau de fișiere încărcate: + +| `MinLength` | număr minim | `int` +| `MaxLength` | număr maxim | `int` +| `Length` | număr în interval sau număr exact | perechi `[int, int]` sau `int` + + +Încărcare fișier +---------------- + Pentru controalele `addUpload()`, `addMultiUpload()` se pot utiliza, de asemenea, următoarele reguli: | `MaxFileSize` | dimensiunea maximă a fișierului | `int` @@ -67,15 +85,9 @@ Pentru controalele `addUpload()`, `addMultiUpload()` se pot utiliza, de asemenea `MimeType` și `Image` necesită extensia PHP `fileinfo`. Dacă un fișier sau o imagine este de tipul cerut este detectat prin semnătura sa. Integritatea întregului fișier nu este verificată. Puteți afla dacă o imagine nu este coruptă, de exemplu, încercând să [o încărcați |http:request#toImage]. -Pentru controalele `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` se pot utiliza, de asemenea, următoarele reguli pentru a limita numărul de elemente selectate, respectiv de fișiere încărcate: - -| `MinLength` | număr minim | `int` -| `MaxLength` | număr maxim | `int` -| `Length` | număr în interval sau număr exact | pereche `[int, int]` sau `int` - Mesaje de eroare .[#toc-error-messages] ---------------------------------------- +======================================= Toate regulile predefinite, cu excepția `Pattern` și `PatternInsensitive`, au un mesaj de eroare implicit, astfel încât acestea pot fi omise. Cu toate acestea, dacă treceți și formulați toate mesajele personalizate, veți face formularul mai ușor de utilizat. diff --git a/forms/ru/validation.texy b/forms/ru/validation.texy index 1f7b5c33f1..b88f35237e 100644 --- a/forms/ru/validation.texy +++ b/forms/ru/validation.texy @@ -23,9 +23,9 @@ $form->addPassword('password', 'Пароль:') ->addRule($form::MinLength, 'Пароль должен состоять не менее чем из %d символов', 8); ``` -Nette поставляется с рядом встроенных правил, имена которых являются константами класса `Nette\Forms\Form`: +**Правила валидации проверяются только в том случае, если пользователь заполнил элемент.** -Мы можем использовать следующие правила для всех элементов управления: +Nette поставляется с рядом предопределенных правил, имена которых являются константами класса `Nette\Forms\Form`. Мы можем применять эти правила ко всем элементам: | константа | описание | аргументы |------- @@ -38,6 +38,10 @@ Nette поставляется с рядом встроенных правил, | `IsNotIn` | значение не равно ни одному элементу массива | `array` | `Valid` | ввод проходит валидацию (для [#Условия]) | - + +Текстовые вводы +--------------- + Для элементов `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` также могут быть применены некоторые из следующих правил: | `MinLength` | минимальная длина строки | `int` @@ -57,6 +61,20 @@ Nette поставляется с рядом встроенных правил, Правила `Integer`, `Numeric` и `Float` автоматически преобразуют значение в целое (или плавающее соответственно). Более того, правило `URL` также принимает адрес без схемы (например, `nette.org`) и дополняет схему (`https://nette.org`). Выражения в `Pattern` и `PatternInsensitive` должны быть действительны для всего значения, т. е. как если бы оно было обернуто в символы `^` и `$`. + +Количество предметов .[#toc-number-of-items] +-------------------------------------------- + +Для элементов `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` также можно использовать следующие правила для ограничения количества выбранных элементов или загруженных файлов: + +| `MinLength` | минимальное количество | `int` +| `MaxLength` | максимальное количество | `int` +| `Length` | число в диапазоне или точное число | пары `[int, int]` или `int` + + +Загрузка файлов +--------------- + Для элементов управления `addUpload()`, `addMultiUpload()` также могут быть использованы следующие правила: | `MaxFileSize` | максимальный размер файла | `int` @@ -67,15 +85,9 @@ Nette поставляется с рядом встроенных правил, Для `MimeType` и `Image` требуется расширение PHP `fileinfo`. Принадлежность файла или изображения к нужному типу определяется по его сигнатуре. Целостность всего файла не проверяется. Вы можете узнать, не повреждено ли изображение, например, попытавшись [загрузить его|http:request#toImage]. -Для элементов управления `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` следующие правила также могут быть использованы для ограничения количества выбранных элементов, соответственно загруженных файлов: - -| `MinLength` | минимальное количество | `int` -| `MaxLength` | максимальное количество | `int` -| `Length` | количество в диапазоне или точное количество | пара `[int, int]` или `int` - Сообщения об ошибках .[#toc-error-messages] -------------------------------------------- +=========================================== Все предопределенные правила, кроме `Pattern` и `PatternInsensitive`, имеют сообщение об ошибке по умолчанию, поэтому их можно опустить. Однако, передав и сформулировав все индивидуальные сообщения, вы сделаете форму более удобной для пользователя. diff --git a/forms/sl/validation.texy b/forms/sl/validation.texy index 0d141c2fb9..c1d0a6ef09 100644 --- a/forms/sl/validation.texy +++ b/forms/sl/validation.texy @@ -23,9 +23,9 @@ $form->addPassword('password', 'Password:') ->addRule($form::MinLength, 'Password must be at least %d characters', 8); ``` -Nette ima na voljo številna vgrajena pravila, katerih imena so konstante razreda `Nette\Forms\Form`: +**Pravila potrjevanja se preverijo le, če je uporabnik izpolnil element.** -Naslednja pravila lahko uporabimo za vse kontrole: +Nette ima na voljo številna vnaprej določena pravila, katerih imena so konstante razreda `Nette\Forms\Form`. Ta pravila lahko uporabimo za vse elemente: | konstanta | opis | argumenti |------- @@ -38,6 +38,10 @@ Naslednja pravila lahko uporabimo za vse kontrole: | `IsNotIn` | vrednost ni enaka nobenemu elementu v polju | `array` | `Valid` | vhodni podatki so uspešno preverjeni (za [pogoje |#conditions]) | - + +Besedilni vnosi +--------------- + Za elemente `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` se lahko uporabijo tudi nekatera od naslednjih pravil: | `MinLength` | minimalna dolžina niza | `int` @@ -57,6 +61,20 @@ Za elemente `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInt Pravila `Integer`, `Numeric` in `Float` samodejno pretvorijo vrednost v celo število (oziroma plavajoče število). Poleg tega pravilo `URL` sprejme tudi naslov brez sheme (npr. `nette.org`) in dopolni shemo (`https://nette.org`). Izraza v `Pattern` in `PatternInsensitive` morata biti veljavna za celotno vrednost, tj. kot da bi bila zavita v znake `^` and `$`. + +Število elementov .[#toc-number-of-items] +----------------------------------------- + +Za elemente `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` lahko za omejitev števila izbranih elementov ali naloženih datotek uporabite tudi naslednja pravila: + +| `MinLength` | najmanjše število | `int` +| `MaxLength` | največje število | `int` +| `Length` | število v razponu ali natančno število | pari `[int, int]` ali `int` + + +Prenos datotek +-------------- + Za kontrole `addUpload()`, `addMultiUpload()` se lahko uporabljajo tudi naslednja pravila: | `MaxFileSize` | največja velikost datoteke | `int` @@ -67,15 +85,9 @@ Za kontrole `addUpload()`, `addMultiUpload()` se lahko uporabljajo tudi naslednj Za `MimeType` in `Image` je potrebna razširitev PHP `fileinfo`. Ali je datoteka ali slika zahtevane vrste, se ugotovi na podlagi njenega podpisa. Celovitost celotne datoteke se ne preverja. Ali slika ni poškodovana, lahko ugotovite na primer tako, da [jo |http:request#toImage] poskusite [naložiti |http:request#toImage]. -Za kontrolnike `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` lahko za omejitev števila izbranih elementov oziroma naloženih datotek uporabite tudi naslednja pravila: - -| `MinLength` | minimalno število | `int` -| `MaxLength` | maksimalno število | `int` -| `Length` | število v razponu ali natančno število | par `[int, int]` ali `int` - Sporočila o napakah .[#toc-error-messages] ------------------------------------------- +========================================== Vsa vnaprej določena pravila, razen `Pattern` in `PatternInsensitive`, imajo privzeto sporočilo o napaki, zato jih lahko izpustite. Vendar pa boste s posredovanjem in oblikovanjem vseh prilagojenih sporočil naredili obrazec prijaznejši do uporabnika. diff --git a/forms/tr/validation.texy b/forms/tr/validation.texy index ad95289175..8d4f636e56 100644 --- a/forms/tr/validation.texy +++ b/forms/tr/validation.texy @@ -23,9 +23,9 @@ $form->addPassword('password', 'Password:') ->addRule($form::MinLength, 'Password must be at least %d characters', 8); ``` -Nette, adları `Nette\Forms\Form` sınıfının sabitleri olan bir dizi yerleşik kuralla birlikte gelir: +**Doğrulama kuralları yalnızca kullanıcı öğeyi doldurduysa kontrol edilir.** -Tüm kontroller için aşağıdaki kuralları kullanabiliriz: +Nette, isimleri `Nette\Forms\Form` sınıfının sabitleri olan bir dizi önceden tanımlanmış kuralla birlikte gelir. Bu kuralları tüm öğelere uygulayabiliriz: | sabit | açıklama | argümanlar |------- @@ -38,6 +38,10 @@ Tüm kontroller için aşağıdaki kuralları kullanabiliriz: | `IsNotIn` | değer dizideki herhangi bir elemana eşit değil | `array` | `Valid` | girdi doğrulamayı geçer ( [koşullar |#conditions] için) | - + +Metin girişleri +--------------- + `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` öğeleri için aşağıdaki kurallardan bazıları da uygulanabilir: | `MinLength` | minimum dize uzunluğu | `int` @@ -57,6 +61,20 @@ Tüm kontroller için aşağıdaki kuralları kullanabiliriz: `Integer`, `Numeric` a `Float` kuralları değeri otomatik olarak tamsayıya (veya sırasıyla float) dönüştürür. Ayrıca, `URL` kuralı da şeması olmayan bir adresi kabul eder (örneğin `nette.org`) ve şemayı tamamlar (`https://nette.org`). `Pattern` ve `PatternInsensitive` içindeki ifadeler tüm değer için geçerli olmalıdır, yani `^` and `$` karakterlerine sarılmış gibi olmalıdır. + +Ürün Sayısı .[#toc-number-of-items] +----------------------------------- + + `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` öğeleri için, seçilen öğelerin veya yüklenen dosyaların sayısını sınırlamak üzere aşağıdaki kuralları da kullanabilirsiniz: + +| `MinLength` | minimum sayı | `int` +| `MaxLength` | maksimum sayı | `int` +| `Length` | aralıktaki sayı veya tam sayı | çiftleri `[int, int]` veya `int` + + +Dosya Yükleme +------------- + `addUpload()`, `addMultiUpload()` kontrolleri için aşağıdaki kurallar da kullanılabilir: | `MaxFileSize` | maksimum dosya boyutu | `int` @@ -67,15 +85,9 @@ Tüm kontroller için aşağıdaki kuralları kullanabiliriz: `MimeType` ve `Image` PHP uzantısı `fileinfo` gerektirir. Bir dosya veya resmin gerekli türde olup olmadığı imzasından anlaşılır. Tüm dosyanın bütünlüğü kontrol edilmez. Bir resmin bozuk olup olmadığını örneğin [yüklemeye |http:request#toImage] çalışarak öğrenebilirsiniz. -`addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` kontrolleri için, sırasıyla yüklenen dosyalar olmak üzere seçilen öğelerin sayısını sınırlamak için aşağıdaki kurallar da kullanılabilir: - -| `MinLength` | minimum sayı | `int` -| `MaxLength` | maksimum sayı | `int` -| `Length` | aralıktaki sayı veya tam sayı | çifti `[int, int]` veya `int` - Hata Mesajları .[#toc-error-messages] -------------------------------------- +===================================== `Pattern` ve `PatternInsensitive` dışındaki tüm önceden tanımlanmış kuralların varsayılan bir hata mesajı vardır, bu nedenle bunlar atlanabilir. Bununla birlikte, tüm özelleştirilmiş mesajları ileterek ve formüle ederek, formu daha kullanıcı dostu hale getireceksiniz. diff --git a/forms/uk/validation.texy b/forms/uk/validation.texy index ab69301e99..78b79d3084 100644 --- a/forms/uk/validation.texy +++ b/forms/uk/validation.texy @@ -23,9 +23,9 @@ $form->addPassword('password', 'Пароль:') ->addRule($form::MinLength, 'Пароль должен состоять не менее чем из %d символов', 8); ``` -Nette постачається з низкою вбудованих правил, імена яких є константами класу `Nette\Forms\Form`: +**Правила перевірки перевіряються тільки в тому випадку, якщо користувач заповнив елемент.** -Ми можемо використовувати такі правила для всіх елементів керування: +Nette постачається з низкою попередньо визначених правил, імена яких є константами класу `Nette\Forms\Form`. Ми можемо застосувати ці правила до всіх елементів: | константа | опис | аргументи |------- @@ -38,6 +38,10 @@ Nette постачається з низкою вбудованих правил | `IsNotIn` | значення не дорівнює жодному елементу масиву | `array` | `Valid` | введення проходить валідацію (для [Умови |#Условия])| - + +Текстові дані +------------- + Для елементів `addText()`, `addPassword()`, `addTextArea()`, `addEmail()`, `addInteger()`, `addFloat()` також можна застосувати деякі з наступних правил: | `MinLength` | мінімальна довжина рядка | `int` @@ -57,6 +61,20 @@ Nette постачається з низкою вбудованих правил Правила `Integer`, `Numeric` і `Float` автоматично перетворюють значення в ціле (або плаваюче відповідно). Більше того, правило `URL` також приймає адресу без схеми (наприклад, `nette.org`) і доповнює схему (`https://nette.org`). Вирази в `Pattern` і `PatternInsensitive` мають бути дійсними для всього значення, тобто так, ніби воно було обгорнуте в символи `^` и `$`. + +Кількість позицій .[#toc-number-of-items] +----------------------------------------- + +Для елементів `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` ви також можете використовувати наступні правила для обмеження кількості обраних елементів або завантажених файлів: + +| `MinLength` | мінімальна кількість `int` +| `MaxLength` | максимальна кількість `int` +| `Length` | кількість в діапазоні або точна кількість | пар `[int, int]` або `int` + + +Завантаження файлу +------------------ + Для елементів керування `addUpload()`, `addMultiUpload()` також можуть бути використані такі правила: | `MaxFileSize` | максимальний розмір файлу | `int` @@ -67,15 +85,9 @@ Nette постачається з низкою вбудованих правил Для `MimeType` і `Image` потрібне розширення PHP `fileinfo`. Належність файлу або зображення до потрібного типу визначається за його сигнатурою. Цілісність усього файлу не перевіряється. Ви можете дізнатися, чи не пошкоджено зображення, наприклад, спробувавши [завантажити його |http:request#toImage]. -Для елементів керування `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` такі правила також можуть бути використані для обмеження кількості обраних елементів, відповідно завантажених файлів: - -| `MinLength` | мінімальна кількість | `int` -| `MaxLength` | максимальна кількість | `int` -| `Length` | кількість у діапазоні або точна кількість | пара `[int, int]` або `int` - Повідомлення про помилки .[#toc-error-messages] ------------------------------------------------ +=============================================== Усі зумовлені правила, крім `Pattern` і `PatternInsensitive`, мають повідомлення про помилку за замовчуванням, тому їх можна опустити. Однак, передавши і сформулювавши всі індивідуальні повідомлення, ви зробите форму зручнішою для користувача. From 58166cbdd6bb44f5a606e2d50c92a27ac7cf11c1 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sun, 15 Oct 2023 23:23:10 +0200 Subject: [PATCH 024/137] forms: used unpkg.com for netteForms --- forms/bg/in-presenter.texy | 2 +- forms/bg/standalone.texy | 2 +- forms/bg/validation.texy | 2 +- forms/cs/in-presenter.texy | 2 +- forms/cs/standalone.texy | 2 +- forms/cs/validation.texy | 2 +- forms/de/in-presenter.texy | 2 +- forms/de/standalone.texy | 2 +- forms/de/validation.texy | 2 +- forms/el/in-presenter.texy | 2 +- forms/el/standalone.texy | 2 +- forms/el/validation.texy | 2 +- forms/en/in-presenter.texy | 2 +- forms/en/standalone.texy | 2 +- forms/en/validation.texy | 2 +- forms/es/in-presenter.texy | 2 +- forms/es/standalone.texy | 2 +- forms/es/validation.texy | 2 +- forms/fr/in-presenter.texy | 2 +- forms/fr/standalone.texy | 2 +- forms/fr/validation.texy | 2 +- forms/hu/in-presenter.texy | 2 +- forms/hu/standalone.texy | 2 +- forms/hu/validation.texy | 2 +- forms/it/in-presenter.texy | 2 +- forms/it/standalone.texy | 2 +- forms/it/validation.texy | 2 +- forms/pl/in-presenter.texy | 2 +- forms/pl/standalone.texy | 2 +- forms/pl/validation.texy | 2 +- forms/pt/in-presenter.texy | 2 +- forms/pt/standalone.texy | 2 +- forms/pt/validation.texy | 2 +- forms/ro/in-presenter.texy | 2 +- forms/ro/standalone.texy | 2 +- forms/ro/validation.texy | 2 +- forms/ru/in-presenter.texy | 2 +- forms/ru/standalone.texy | 2 +- forms/ru/validation.texy | 2 +- forms/sl/in-presenter.texy | 2 +- forms/sl/standalone.texy | 2 +- forms/sl/validation.texy | 2 +- forms/tr/in-presenter.texy | 2 +- forms/tr/standalone.texy | 2 +- forms/tr/validation.texy | 2 +- forms/uk/in-presenter.texy | 2 +- forms/uk/standalone.texy | 2 +- forms/uk/validation.texy | 2 +- 48 files changed, 48 insertions(+), 48 deletions(-) diff --git a/forms/bg/in-presenter.texy b/forms/bg/in-presenter.texy index ae2285540f..1c885cb270 100644 --- a/forms/bg/in-presenter.texy +++ b/forms/bg/in-presenter.texy @@ -132,7 +132,7 @@ $form->addText('name', 'Имя:') Вмъкнете го в шаблона за оформление: ```latte - + ``` Ако разгледате изходния код на страницата с формуляра, можете да забележите, че Nette вмъква задължителни полета в елементи с клас CSS `required`. Опитайте се да добавите следния стил към шаблона и тагът "Име" ще бъде червен. Елегантно маркираме задължителните полета за потребителите: diff --git a/forms/bg/standalone.texy b/forms/bg/standalone.texy index 5c2c5fc550..4ce57a672e 100644 --- a/forms/bg/standalone.texy +++ b/forms/bg/standalone.texy @@ -107,7 +107,7 @@ $form->addText('name', 'Имя:') Добавете го към страницата: ```latte - + ``` Ако разгледате изходния код на страницата с формуляра, можете да забележите, че Nette вмъква задължителни полета в елементи с клас CSS `required`. Опитайте се да добавите следния стил към шаблона и тагът "Име" ще бъде червен. Елегантно маркираме задължителните полета за потребителите: diff --git a/forms/bg/validation.texy b/forms/bg/validation.texy index 6b0881de4e..d3a09980ef 100644 --- a/forms/bg/validation.texy +++ b/forms/bg/validation.texy @@ -293,7 +293,7 @@ $form->addText('zip', 'postcode:') Можете да вградите скрипта директно в HTML страница от CDN: ```latte - + ``` Или копирайте локално в обща папка на проекта (например от `vendor/nette/forms/src/assets/netteForms.min.js`): diff --git a/forms/cs/in-presenter.texy b/forms/cs/in-presenter.texy index f3174f1c0a..4368a100dc 100644 --- a/forms/cs/in-presenter.texy +++ b/forms/cs/in-presenter.texy @@ -132,7 +132,7 @@ Formulář se vždy validuje na straně serveru, ale také se generuje JavaScrip Vložte jej do šablony layoutu: ```latte - + ``` Pokud se podíváte do zdrojového kódu stránky s formulářem, můžete si všimnout, že Nette povinné prvky vkládá do elementů s CSS třídou `required`. Zkuste přidat do šablony následující stylopis a popiska „Jméno“ bude červená. Elegantně tak uživatelům vyznačíme povinné prvky: diff --git a/forms/cs/standalone.texy b/forms/cs/standalone.texy index 965c271724..ce1a572842 100644 --- a/forms/cs/standalone.texy +++ b/forms/cs/standalone.texy @@ -107,7 +107,7 @@ Formulář se vždy validuje na straně serveru, ale také se generuje JavaScrip Vložte jej do stránky: ```latte - + ``` Pokud se podíváte do zdrojového kódu stránky s formulářem, můžete si všimnout, že Nette povinné prvky vkládá do elementů s CSS třídou `required`. Zkuste přidat do šablony následující stylopis a popiska „Jméno“ bude červená. Elegantně tak uživatelům vyznačíme povinné prvky: diff --git a/forms/cs/validation.texy b/forms/cs/validation.texy index 300f13d6e1..33d16f924e 100644 --- a/forms/cs/validation.texy +++ b/forms/cs/validation.texy @@ -293,7 +293,7 @@ Tím skriptem je `netteForms.js` a je dostupný z více možných zdrojů: Skript můžete vložit přímo do HTML stránky ze CDN: ```latte - + ``` Nebo zkopírovat lokálně do veřejné složky projektu (např. z `vendor/nette/forms/src/assets/netteForms.min.js`): diff --git a/forms/de/in-presenter.texy b/forms/de/in-presenter.texy index 41f8158caf..f7f4f18008 100644 --- a/forms/de/in-presenter.texy +++ b/forms/de/in-presenter.texy @@ -132,7 +132,7 @@ Das Formular wird immer serverseitig validiert, aber es wird auch eine JavaScrip Fügen Sie es in die Layout-Vorlage ein: ```latte - + ``` Wenn Sie in den Quellcode der Seite mit dem Formular schauen, werden Sie feststellen, dass Nette die erforderlichen Felder in Elemente mit einer CSS-Klasse `required` einfügt. Versuchen Sie, den folgenden Stil in die Vorlage einzufügen, und die Bezeichnung "Name" wird rot sein. Auf elegante Weise markieren wir die erforderlichen Felder für die Benutzer: diff --git a/forms/de/standalone.texy b/forms/de/standalone.texy index a0574fe054..039c051a97 100644 --- a/forms/de/standalone.texy +++ b/forms/de/standalone.texy @@ -107,7 +107,7 @@ Das Formular wird immer serverseitig validiert, aber es wird auch eine JavaScrip Fügen Sie es in die Seite ein: ```latte - + ``` Wenn Sie sich den Quellcode der Seite mit dem Formular ansehen, werden Sie feststellen, dass Nette die erforderlichen Felder in Elemente mit einer CSS-Klasse `required` einfügt. Versuchen Sie, der Vorlage den folgenden Stil hinzuzufügen, und die Bezeichnung "Name" wird rot sein. Auf elegante Weise markieren wir die erforderlichen Felder für die Benutzer: diff --git a/forms/de/validation.texy b/forms/de/validation.texy index 5bbcdb66e5..016aea76a3 100644 --- a/forms/de/validation.texy +++ b/forms/de/validation.texy @@ -293,7 +293,7 @@ Dieses Skript ist `netteForms.js`, das von mehreren möglichen Quellen erhältli Sie können das Skript direkt in die HTML-Seite aus dem CDN einbetten: ```latte - + ``` Oder kopieren Sie es lokal in den öffentlichen Ordner des Projekts (z. B. von `vendor/nette/forms/src/assets/netteForms.min.js`): diff --git a/forms/el/in-presenter.texy b/forms/el/in-presenter.texy index 9221cee979..d0ea92b9b2 100644 --- a/forms/el/in-presenter.texy +++ b/forms/el/in-presenter.texy @@ -132,7 +132,7 @@ $form->addText('name', 'Name:') Εισάγεται στο πρότυπο διάταξης: ```latte - + ``` Αν κοιτάξετε στον πηγαίο κώδικα της σελίδας με τη φόρμα, μπορεί να παρατηρήσετε ότι η Nette εισάγει τα απαιτούμενα πεδία σε στοιχεία με κλάση CSS `required`. Δοκιμάστε να προσθέσετε το ακόλουθο στυλ στο πρότυπο, και η ετικέτα "Όνομα" θα είναι κόκκινη. Κομψά, επισημαίνουμε τα υποχρεωτικά πεδία για τους χρήστες: diff --git a/forms/el/standalone.texy b/forms/el/standalone.texy index 67275ad240..220d7a4da5 100644 --- a/forms/el/standalone.texy +++ b/forms/el/standalone.texy @@ -107,7 +107,7 @@ $form->addText('name', 'Name:') Προσθέστε το στη σελίδα: ```latte - + ``` Αν κοιτάξετε στον πηγαίο κώδικα της σελίδας με τη φόρμα, μπορεί να παρατηρήσετε ότι η Nette εισάγει τα απαιτούμενα πεδία σε στοιχεία με κλάση CSS `required`. Δοκιμάστε να προσθέσετε το ακόλουθο στυλ στο πρότυπο, και η ετικέτα "Όνομα" θα είναι κόκκινη. Κομψά, επισημαίνουμε τα υποχρεωτικά πεδία για τους χρήστες: diff --git a/forms/el/validation.texy b/forms/el/validation.texy index 2ae2e83d6e..1123027e75 100644 --- a/forms/el/validation.texy +++ b/forms/el/validation.texy @@ -293,7 +293,7 @@ $form->addText('zip', 'Postcode:') Μπορείτε να ενσωματώσετε το σενάριο απευθείας στη σελίδα HTML από το CDN: ```latte - + ``` ή να το αντιγράψετε τοπικά στο δημόσιο φάκελο του έργου (π.χ. από το `vendor/nette/forms/src/assets/netteForms.min.js`): diff --git a/forms/en/in-presenter.texy b/forms/en/in-presenter.texy index e09ebee337..8a1c7cc2cc 100644 --- a/forms/en/in-presenter.texy +++ b/forms/en/in-presenter.texy @@ -132,7 +132,7 @@ The form is always validated on the server side, but JavaScript validation is al Insert it into the layout template: ```latte - + ``` If you look in the source code of the page with form, you may notice that Nette inserts the required fields into elements with a CSS class `required`. Try adding the following style to the template, and the "Name" label will be red. Elegantly, we mark the required fields for the users: diff --git a/forms/en/standalone.texy b/forms/en/standalone.texy index 13d1285515..1351e51aef 100644 --- a/forms/en/standalone.texy +++ b/forms/en/standalone.texy @@ -107,7 +107,7 @@ The form is always validated on the server side, but JavaScript validation is al Add it to the page: ```latte - + ``` If you look in the source code of the page with form, you may notice that Nette inserts the required fields into elements with a CSS class `required`. Try adding the following style to the template, and the "Name" label will be red. Elegantly, we mark the required fields for the users: diff --git a/forms/en/validation.texy b/forms/en/validation.texy index 684510f24b..308f5fb1a9 100644 --- a/forms/en/validation.texy +++ b/forms/en/validation.texy @@ -293,7 +293,7 @@ This script is `netteForms.js`, which is available from several possible sources You can embed the script directly into the HTML page from the CDN: ```latte - + ``` Or copy locally to the public folder of the project (e.g. from `vendor/nette/forms/src/assets/netteForms.min.js`): diff --git a/forms/es/in-presenter.texy b/forms/es/in-presenter.texy index 2dddcee064..e30d0b8c91 100644 --- a/forms/es/in-presenter.texy +++ b/forms/es/in-presenter.texy @@ -132,7 +132,7 @@ El formulario siempre se valida en el lado del servidor, pero también se genera Insértelo en la plantilla de diseño: ```latte - + ``` Si mira en el código fuente de la página con formulario, puede observar que Nette inserta los campos obligatorios en elementos con una clase CSS `required`. Pruebe a añadir el siguiente estilo a la plantilla, y la etiqueta "Nombre" será de color rojo. Elegantemente, marcamos los campos obligatorios para los usuarios: diff --git a/forms/es/standalone.texy b/forms/es/standalone.texy index 22066da21c..c34b775396 100644 --- a/forms/es/standalone.texy +++ b/forms/es/standalone.texy @@ -107,7 +107,7 @@ El formulario siempre se valida en el lado del servidor, pero también se genera Añádelo a la página: ```latte - + ``` Si miras en el código fuente de la página con formulario, puedes notar que Nette inserta los campos requeridos en elementos con una clase CSS `required`. Pruebe a añadir el siguiente estilo a la plantilla, y la etiqueta "Nombre" será de color rojo. Elegantemente, marcamos los campos obligatorios para los usuarios: diff --git a/forms/es/validation.texy b/forms/es/validation.texy index 51896dd549..9cca587c43 100644 --- a/forms/es/validation.texy +++ b/forms/es/validation.texy @@ -293,7 +293,7 @@ Este script es `netteForms.js`, que está disponible en varias fuentes posibles: Puedes incrustar el script directamente en la página HTML desde el CDN: ```latte - + ``` O copiarlo localmente en la carpeta pública del proyecto (por ejemplo, desde `vendor/nette/forms/src/assets/netteForms.min.js`): diff --git a/forms/fr/in-presenter.texy b/forms/fr/in-presenter.texy index 0fb310f2cb..48ef548323 100644 --- a/forms/fr/in-presenter.texy +++ b/forms/fr/in-presenter.texy @@ -132,7 +132,7 @@ Le formulaire est toujours validé du côté du serveur, mais la validation Java Insérez-le dans le modèle de mise en page : ```latte - + ``` Si vous regardez dans le code source de la page avec formulaire, vous pouvez remarquer que Nette insère les champs obligatoires dans des éléments avec une classe CSS `required`. Essayez d'ajouter le style suivant au modèle, et l'étiquette "Nom" sera rouge. De manière élégante, nous marquons les champs obligatoires pour les utilisateurs : diff --git a/forms/fr/standalone.texy b/forms/fr/standalone.texy index ea3843cd3e..1fe41903b0 100644 --- a/forms/fr/standalone.texy +++ b/forms/fr/standalone.texy @@ -107,7 +107,7 @@ Le formulaire est toujours validé du côté du serveur, mais la validation Java Ajoutez-le à la page : ```latte - + ``` Si vous regardez dans le code source de la page avec formulaire, vous pouvez remarquer que Nette insère les champs obligatoires dans des éléments avec une classe CSS `required`. Essayez d'ajouter le style suivant au modèle, et l'étiquette "Nom" sera rouge. De manière élégante, nous marquons les champs obligatoires pour les utilisateurs : diff --git a/forms/fr/validation.texy b/forms/fr/validation.texy index aa78326bed..9f0931173c 100644 --- a/forms/fr/validation.texy +++ b/forms/fr/validation.texy @@ -293,7 +293,7 @@ Ce script est `netteForms.js`, qui est disponible à partir de plusieurs sources Vous pouvez intégrer le script directement dans la page HTML à partir du CDN : ```latte - + ``` Ou le copier localement dans le dossier public du projet (par exemple à partir de `vendor/nette/forms/src/assets/netteForms.min.js`) : diff --git a/forms/hu/in-presenter.texy b/forms/hu/in-presenter.texy index d3bc0884a4..2a02728cca 100644 --- a/forms/hu/in-presenter.texy +++ b/forms/hu/in-presenter.texy @@ -132,7 +132,7 @@ Az űrlap mindig a szerveroldalon validálódik, de a JavaScript validáció is Ezt illessze be az elrendezési sablonba: ```latte - + ``` Ha megnézi az űrlapot tartalmazó oldal forráskódját, észreveheti, hogy a Nette a szükséges mezőket a `required` CSS osztályú elemekbe illeszti be. Próbálja meg a következő stílust hozzáadni a sablonhoz, és a "Név" felirat piros lesz. Elegánsan jelöljük a kötelező mezőket a felhasználók számára: diff --git a/forms/hu/standalone.texy b/forms/hu/standalone.texy index bcb4b6c8be..aa0825b549 100644 --- a/forms/hu/standalone.texy +++ b/forms/hu/standalone.texy @@ -107,7 +107,7 @@ Az űrlap mindig a szerveroldalon validálódik, de a JavaScript validáció is Adja hozzá az oldalhoz: ```latte - + ``` Ha megnézi az űrlapot tartalmazó oldal forráskódját, észreveheti, hogy a Nette a szükséges mezőket a `required` CSS osztályú elemekbe illeszti be. Próbálja meg hozzáadni a következő stílust a sablonhoz, és a "Név" felirat piros lesz. Elegánsan jelöljük a kötelező mezőket a felhasználók számára: diff --git a/forms/hu/validation.texy b/forms/hu/validation.texy index 1a042600bc..915425c223 100644 --- a/forms/hu/validation.texy +++ b/forms/hu/validation.texy @@ -293,7 +293,7 @@ Ez a szkript a `netteForms.js`, amely több lehetséges forrásból is elérhet A szkriptet közvetlenül a CDN-ből származó HTML-oldalba ágyazhatja be: ```latte - + ``` Vagy másolja be helyileg a projekt nyilvános mappájába (pl. a `vendor/nette/forms/src/assets/netteForms.min.js`): diff --git a/forms/it/in-presenter.texy b/forms/it/in-presenter.texy index a7b68bbb17..d4115962c3 100644 --- a/forms/it/in-presenter.texy +++ b/forms/it/in-presenter.texy @@ -132,7 +132,7 @@ Il modulo viene sempre convalidato sul lato server, ma viene generata anche una Inserirlo nel modello di layout: ```latte - + ``` Se si guarda nel codice sorgente della pagina con il modulo, si può notare che Nette inserisce i campi obbligatori in elementi con una classe CSS `required`. Provate ad aggiungere il seguente stile al modello e l'etichetta "Nome" diventerà rossa. In modo elegante, contrassegniamo i campi obbligatori per gli utenti: diff --git a/forms/it/standalone.texy b/forms/it/standalone.texy index 20ac7858c9..d4e81bbb43 100644 --- a/forms/it/standalone.texy +++ b/forms/it/standalone.texy @@ -107,7 +107,7 @@ Il modulo viene sempre convalidato sul lato server, ma viene generata anche una Aggiungerlo alla pagina: ```latte - + ``` Se si guarda nel codice sorgente della pagina con il modulo, si può notare che Nette inserisce i campi obbligatori in elementi con una classe CSS `required`. Provate ad aggiungere il seguente stile al template e l'etichetta "Nome" diventerà rossa. In modo elegante, contrassegniamo i campi obbligatori per gli utenti: diff --git a/forms/it/validation.texy b/forms/it/validation.texy index b2c3c91c2d..0fedfe4e62 100644 --- a/forms/it/validation.texy +++ b/forms/it/validation.texy @@ -293,7 +293,7 @@ Questo script è `netteForms.js`, disponibile da diverse fonti: È possibile incorporare lo script direttamente nella pagina HTML dal CDN: ```latte - + ``` Oppure copiare localmente nella cartella pubblica del progetto (ad esempio da `vendor/nette/forms/src/assets/netteForms.min.js`): diff --git a/forms/pl/in-presenter.texy b/forms/pl/in-presenter.texy index ff8db944ce..60bed90d6e 100644 --- a/forms/pl/in-presenter.texy +++ b/forms/pl/in-presenter.texy @@ -132,7 +132,7 @@ Formularz jest zawsze walidowany po stronie serwera, ale generuje również wali Wstaw go do szablonu układu: ```latte - + ``` Jeśli spojrzysz na kod źródłowy strony formularza, możesz zauważyć, że Nette wstawia wymagane elementy z klasą CSS `required`. Spróbuj dodać następujący arkusz stylów do szablonu, a etykieta "Nazwa" będzie czerwona. To elegancko podkreśli wymagane elementy dla użytkownika: diff --git a/forms/pl/standalone.texy b/forms/pl/standalone.texy index 82353d1de2..0757691ff0 100644 --- a/forms/pl/standalone.texy +++ b/forms/pl/standalone.texy @@ -107,7 +107,7 @@ Formularz jest zawsze walidowany po stronie serwera, ale generuje również wali Wstaw go na stronę: ```latte - + ``` Jeśli spojrzysz na kod źródłowy strony formularza, możesz zauważyć, że Nette wstawia wymagane elementy z klasą CSS `required`. Spróbuj dodać następujący arkusz stylów do szablonu, a etykieta "Nazwa" będzie czerwona. Dzięki temu w elegancki sposób zaznaczymy dla użytkowników elementy obowiązkowe: diff --git a/forms/pl/validation.texy b/forms/pl/validation.texy index 02b0a1d8ec..f6a652e651 100644 --- a/forms/pl/validation.texy +++ b/forms/pl/validation.texy @@ -293,7 +293,7 @@ Ten skrypt to `netteForms.js` i jest dostępny z wielu możliwych źródeł: Możesz osadzić skrypt bezpośrednio na stronie HTML z CDN: ```latte - + ``` Albo skopiuj go lokalnie do publicznego folderu projektu (np. z `vendor/nette/forms/src/assets/netteForms.min.js`): diff --git a/forms/pt/in-presenter.texy b/forms/pt/in-presenter.texy index 81cf7df2ae..0312dd2546 100644 --- a/forms/pt/in-presenter.texy +++ b/forms/pt/in-presenter.texy @@ -132,7 +132,7 @@ O formulário é sempre validado no lado do servidor, mas a validação JavaScri Insira-o no modelo de layout: ```latte - + ``` Se você olhar no código fonte da página com formulário, você pode notar que Nette insere os campos necessários em elementos com uma classe CSS `required`. Tente adicionar o seguinte estilo ao modelo, e a etiqueta "Name" (Nome) será vermelha. Elegantemente, marcamos os campos requeridos para os usuários: diff --git a/forms/pt/standalone.texy b/forms/pt/standalone.texy index 2bcad570b5..dafdebe9b8 100644 --- a/forms/pt/standalone.texy +++ b/forms/pt/standalone.texy @@ -107,7 +107,7 @@ O formulário é sempre validado no lado do servidor, mas a validação JavaScri Acrescente-o à página: ```latte - + ``` Se você olhar no código fonte da página com formulário, você pode notar que Nette insere os campos necessários em elementos com uma classe CSS `required`. Tente adicionar o seguinte estilo ao modelo, e a etiqueta "Name" (Nome) será vermelha. Elegantemente, marcamos os campos requeridos para os usuários: diff --git a/forms/pt/validation.texy b/forms/pt/validation.texy index 959ad82fff..b2331fc1ba 100644 --- a/forms/pt/validation.texy +++ b/forms/pt/validation.texy @@ -293,7 +293,7 @@ Este roteiro é `netteForms.js`, que está disponível em várias fontes possív Você pode incorporar o script diretamente na página HTML a partir do CDN: ```latte - + ``` Ou copiar localmente para a pasta pública do projeto (por exemplo, de `vendor/nette/forms/src/assets/netteForms.min.js`): diff --git a/forms/ro/in-presenter.texy b/forms/ro/in-presenter.texy index fb18bf4c66..be3f4d4a06 100644 --- a/forms/ro/in-presenter.texy +++ b/forms/ro/in-presenter.texy @@ -132,7 +132,7 @@ Formularul este întotdeauna validat pe partea serverului, dar este generată ș Introduceți-l în șablonul de prezentare: ```latte - + ``` Dacă vă uitați în codul sursă al paginii cu formular, puteți observa că Nette inserează câmpurile obligatorii în elemente cu o clasă CSS `required`. Încercați să adăugați următorul stil în șablon, iar eticheta "Name" va fi roșie. În mod elegant, marcăm câmpurile obligatorii pentru utilizatori: diff --git a/forms/ro/standalone.texy b/forms/ro/standalone.texy index 34ec299bb0..5427f926c7 100644 --- a/forms/ro/standalone.texy +++ b/forms/ro/standalone.texy @@ -107,7 +107,7 @@ Formularul este întotdeauna validat pe partea serverului, dar este generată ș Adăugați-l în pagină: ```latte - + ``` Dacă vă uitați în codul sursă al paginii cu formular, puteți observa că Nette inserează câmpurile obligatorii în elemente cu o clasă CSS `required`. Încercați să adăugați următorul stil în șablon, iar eticheta "Name" va fi roșie. În mod elegant, marcăm câmpurile obligatorii pentru utilizatori: diff --git a/forms/ro/validation.texy b/forms/ro/validation.texy index 4e100b2877..3c4b009059 100644 --- a/forms/ro/validation.texy +++ b/forms/ro/validation.texy @@ -293,7 +293,7 @@ Acest script este `netteForms.js`, care este disponibil din mai multe surse posi Puteți încorpora scriptul direct în pagina HTML din CDN: ```latte - + ``` Sau copiați local în folderul public al proiectului (de exemplu, de la `vendor/nette/forms/src/assets/netteForms.min.js`): diff --git a/forms/ru/in-presenter.texy b/forms/ru/in-presenter.texy index f8ba0bff66..76fdfb7969 100644 --- a/forms/ru/in-presenter.texy +++ b/forms/ru/in-presenter.texy @@ -132,7 +132,7 @@ $form->addText('name', 'Имя:') Вставьте его в шаблон макета: ```latte - + ``` Если вы посмотрите в исходный код страницы с формой, вы можете заметить, что Nette вставляет обязательные поля в элементы с CSS-классом `required`. Попробуйте добавить следующий стиль в шаблон, и метка "Имя" будет красного цвета. Мы элегантно помечаем обязательные поля для пользователей: diff --git a/forms/ru/standalone.texy b/forms/ru/standalone.texy index 65912b061e..1c2a1788e4 100644 --- a/forms/ru/standalone.texy +++ b/forms/ru/standalone.texy @@ -107,7 +107,7 @@ $form->addText('name', 'Имя:') Добавьте его на страницу: ```latte - + ``` Если вы посмотрите в исходный код страницы с формой, вы можете заметить, что Nette вставляет обязательные поля в элементы с CSS-классом `required`. Попробуйте добавить следующий стиль в шаблон, и метка "Имя" будет красного цвета. Мы элегантно помечаем обязательные поля для пользователей: diff --git a/forms/ru/validation.texy b/forms/ru/validation.texy index b88f35237e..895a1dc5ff 100644 --- a/forms/ru/validation.texy +++ b/forms/ru/validation.texy @@ -293,7 +293,7 @@ $form->addText('zip', 'Почтовый индекс:') Вы можете встроить сценарий непосредственно в HTML-страницу из CDN: ```latte - + ``` Или скопируйте локально в общую папку проекта (например, с сайта `vendor/nette/forms/src/assets/netteForms.min.js`): diff --git a/forms/sl/in-presenter.texy b/forms/sl/in-presenter.texy index bf919a5eb2..cbdc74a127 100644 --- a/forms/sl/in-presenter.texy +++ b/forms/sl/in-presenter.texy @@ -132,7 +132,7 @@ Obrazec se vedno potrdi na strani strežnika, vendar se ustvari tudi potrditev J Vstavite jo v predlogo postavitve: ```latte - + ``` Če pogledate izvorno kodo strani z obrazcem, lahko opazite, da Nette vstavi zahtevana polja v elemente z razredom CSS `required`. Poskusite v predlogo dodati naslednji slog in oznaka "Ime" bo rdeča. Na eleganten način označimo zahtevana polja za uporabnike: diff --git a/forms/sl/standalone.texy b/forms/sl/standalone.texy index a68ac0a15e..3a4a65f195 100644 --- a/forms/sl/standalone.texy +++ b/forms/sl/standalone.texy @@ -107,7 +107,7 @@ Obrazec se vedno potrdi na strani strežnika, vendar se ustvari tudi potrditev J Dodajte jo na stran: ```latte - + ``` Če pogledate izvorno kodo strani z obrazcem, lahko opazite, da Nette vstavi zahtevana polja v elemente z razredom CSS `required`. Poskusite v predlogo dodati naslednji slog in oznaka "Ime" bo rdeča. Na eleganten način označimo zahtevana polja za uporabnike: diff --git a/forms/sl/validation.texy b/forms/sl/validation.texy index c1d0a6ef09..ddcf592b27 100644 --- a/forms/sl/validation.texy +++ b/forms/sl/validation.texy @@ -293,7 +293,7 @@ Ta skripta je `netteForms.js`, ki je na voljo iz več možnih virov: Skripto lahko vstavite neposredno v stran HTML iz CDN: ```latte - + ``` Lahko pa jo kopirate lokalno v javno mapo projekta (npr. s spletne strani `vendor/nette/forms/src/assets/netteForms.min.js`): diff --git a/forms/tr/in-presenter.texy b/forms/tr/in-presenter.texy index cef4cc8ee8..abf4476a85 100644 --- a/forms/tr/in-presenter.texy +++ b/forms/tr/in-presenter.texy @@ -132,7 +132,7 @@ Form her zaman sunucu tarafında doğrulanır, ancak JavaScript doğrulaması da Bunu düzen şablonuna ekleyin: ```latte - + ``` Formun bulunduğu sayfanın kaynak koduna bakarsanız, Nette'in gerekli alanları `required` CSS sınıfına sahip öğelere eklediğini fark edebilirsiniz. Aşağıdaki stili şablona eklemeyi deneyin, "Ad" etiketi kırmızı olacaktır. Kullanıcılar için gerekli alanları zarif bir şekilde işaretliyoruz: diff --git a/forms/tr/standalone.texy b/forms/tr/standalone.texy index ffbe8fbea5..88f05b7924 100644 --- a/forms/tr/standalone.texy +++ b/forms/tr/standalone.texy @@ -107,7 +107,7 @@ Form her zaman sunucu tarafında doğrulanır, ancak JavaScript doğrulaması da Bunu sayfaya ekleyin: ```latte - + ``` Formun bulunduğu sayfanın kaynak koduna bakarsanız, Nette'in gerekli alanları `required` CSS sınıfına sahip öğelere eklediğini fark edebilirsiniz. Aşağıdaki stili şablona eklemeyi deneyin, "Ad" etiketi kırmızı olacaktır. Kullanıcılar için gerekli alanları zarif bir şekilde işaretliyoruz: diff --git a/forms/tr/validation.texy b/forms/tr/validation.texy index 8d4f636e56..484738d6be 100644 --- a/forms/tr/validation.texy +++ b/forms/tr/validation.texy @@ -293,7 +293,7 @@ Bu komut dosyası, birkaç olası kaynaktan temin edilebilen `netteForms.js` adr Komut dosyasını CDN'den doğrudan HTML sayfasına gömebilirsiniz: ```latte - + ``` Ya da yerel olarak projenin ortak klasörüne kopyalayın (örneğin `vendor/nette/forms/src/assets/netteForms.min.js` adresinden): diff --git a/forms/uk/in-presenter.texy b/forms/uk/in-presenter.texy index ed89773929..a3efcfabcc 100644 --- a/forms/uk/in-presenter.texy +++ b/forms/uk/in-presenter.texy @@ -132,7 +132,7 @@ $form->addText('name', 'Имя:') Вставте його в шаблон макета: ```latte - + ``` Якщо ви подивитеся у вихідний код сторінки з формою, ви можете помітити, що Nette вставляє обов'язкові поля в елементи з CSS-класом `required`. Спробуйте додати наступний стиль у шаблон, і мітка "Ім'я" буде червоного кольору. Ми елегантно позначаємо обов'язкові поля для користувачів: diff --git a/forms/uk/standalone.texy b/forms/uk/standalone.texy index ccd1872f46..ac5a0ff3ad 100644 --- a/forms/uk/standalone.texy +++ b/forms/uk/standalone.texy @@ -107,7 +107,7 @@ $form->addText('name', 'Имя:') Додайте його на сторінку: ```latte - + ``` Якщо ви подивитеся у вихідний код сторінки з формою, ви можете помітити, що Nette вставляє обов'язкові поля в елементи з CSS-класом `required`. Спробуйте додати наступний стиль у шаблон, і мітка "Ім'я" буде червоного кольору. Ми елегантно позначаємо обов'язкові поля для користувачів: diff --git a/forms/uk/validation.texy b/forms/uk/validation.texy index 78b79d3084..ff28466195 100644 --- a/forms/uk/validation.texy +++ b/forms/uk/validation.texy @@ -293,7 +293,7 @@ $form->addText('zip', 'Поштовий індекс:') Ви можете вбудувати сценарій безпосередньо в HTML-сторінку з CDN: ```latte - + ``` Або скопіюйте локально в загальну папку проєкту (наприклад, із сайту `vendor/nette/forms/src/assets/netteForms.min.js`): From fc920ebd5aabc2cfb68999b83a24fbfe82142015 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sun, 15 Oct 2023 23:31:51 +0200 Subject: [PATCH 025/137] ajax: improved --- application/bg/ajax.texy | 262 ++++++++++++++------------------ application/bg/components.texy | 2 +- application/cs/ajax.texy | 250 +++++++++++++----------------- application/cs/components.texy | 2 +- application/de/ajax.texy | 258 +++++++++++++------------------ application/de/components.texy | 2 +- application/el/ajax.texy | 260 ++++++++++++++------------------ application/el/components.texy | 2 +- application/en/ajax.texy | 254 +++++++++++++------------------ application/en/components.texy | 2 +- application/es/ajax.texy | 258 +++++++++++++------------------ application/es/components.texy | 2 +- application/fr/ajax.texy | 264 ++++++++++++++------------------ application/fr/components.texy | 2 +- application/hu/ajax.texy | 260 ++++++++++++++------------------ application/hu/components.texy | 2 +- application/it/ajax.texy | 258 +++++++++++++------------------ application/it/components.texy | 2 +- application/pl/ajax.texy | 266 ++++++++++++++------------------ application/pl/components.texy | 2 +- application/pt/ajax.texy | 266 ++++++++++++++------------------ application/pt/components.texy | 2 +- application/ro/ajax.texy | 260 ++++++++++++++------------------ application/ro/components.texy | 2 +- application/ru/ajax.texy | 262 ++++++++++++++------------------ application/ru/components.texy | 2 +- application/sl/ajax.texy | 260 ++++++++++++++------------------ application/sl/components.texy | 2 +- application/tr/ajax.texy | 258 +++++++++++++------------------ application/tr/components.texy | 2 +- application/uk/ajax.texy | 268 ++++++++++++++------------------- application/uk/components.texy | 2 +- latte/bg/tags.texy | 4 +- latte/cs/tags.texy | 4 +- latte/de/tags.texy | 4 +- latte/el/tags.texy | 4 +- latte/en/tags.texy | 4 +- latte/es/tags.texy | 4 +- latte/fr/tags.texy | 4 +- latte/hu/tags.texy | 4 +- latte/it/tags.texy | 4 +- latte/ja/tags.texy | 4 +- latte/pl/tags.texy | 4 +- latte/pt/tags.texy | 4 +- latte/ro/tags.texy | 4 +- latte/ru/tags.texy | 4 +- latte/sl/tags.texy | 4 +- latte/tr/tags.texy | 4 +- latte/uk/tags.texy | 4 +- 49 files changed, 1796 insertions(+), 2468 deletions(-) diff --git a/application/bg/ajax.texy b/application/bg/ajax.texy index dfb8f9f929..3b98231de7 100644 --- a/application/bg/ajax.texy +++ b/application/bg/ajax.texy @@ -3,10 +3,10 @@ AJAX и фрагменти
-Съвременните уеб приложения днес се изпълняват наполовина на сървъра и наполовина в браузъра. AJAX е важен обединяващ фактор. Каква поддръжка предлага рамката Nette? -- Подаване на фрагменти (наречени *фрагменти*) -- прехвърляне на променливи между PHP и JavaScript -- отстраняване на грешки в приложенията AJAX +В ерата на съвременните уеб приложения, където функционалността често се разпростира между сървъра и браузъра, AJAX е важен свързващ елемент. Какви възможности предлага Nette Framework в тази област? +- Изпращане на части от шаблона, т.нар. фрагменти +- предаване на променливи между PHP и JavaScript +- инструменти за отстраняване на грешки при AJAX заявките
@@ -14,29 +14,32 @@ AJAX и фрагменти Заявка AJAX .[#toc-ajax-request] ================================ -Заявката AJAX не се различава от класическата заявка - водещият се извиква с определен изглед и параметри. От водещия също зависи как да отговори на нея: той може да използва своя собствена процедура, която връща фрагмент от HTML код (HTML snippet), XML документ, JSON обект или JavaScript код. +Заявката AJAX не се различава съществено от класическата HTTP заявка. Извиква се презентатор с определени параметри. От водещия зависи как да отговори на заявката - той може да върне данни във формат JSON, да изпрати част от HTML код, XML документ и т.н. -От страна на сървъра AJAX заявката може да бъде открита с помощта на метода на услугата, [капсулиращ HTTP заявката |http:request] `$httpRequest->isAjax()` (открива се въз основа на HTTP заглавието `X-Requested-With`). Вътре в презентатора е наличен пряк път под формата на метода `$this->isAjax()`. +От страна на браузъра инициираме AJAX заявка, като използваме функцията `fetch()`: -Съществува предварително обработен обект `payload`, предназначен за изпращане на данни към браузъра във формат JSON. - -```php -public function actionDelete(int $id): void -{ - if ($this->isAjax()) { - $this->payload->message = 'Успешно'; - } - // ... -} +```js +fetch(url, { + headers: {'X-Requested-With': 'XMLHttpRequest'}, +}) +.then(response => response.json()) +.then(payload => { + // обработка на отговора +}); ``` -За да имате пълен контрол върху извеждането на JSON, използвайте метода `sendJson` в презентатора. Това веднага ще прекъсне презентатора и ще се справите без шаблона: +От страна на сървъра AJAX заявката се разпознава чрез метода `$httpRequest->isAjax()` на услугата, която [капсулира HTTP заявката |http:request]. Той използва HTTP заглавието `X-Requested-With`, така че е от съществено значение да го изпратите. В рамките на презентатора можете да използвате метода `$this->isAjax()`. + +Ако искате да изпратите данни във формат JSON, използвайте метода [`sendJson()` |presenters#Sending a response] метод. Методът също така прекратява дейността на презентатора. ```php -$this->sendJson(['key' => 'value', /* ... */]); +public function actionExport(): void +{ + $this->sendJson($this->model->getData); +} ``` -Ако искаме да изпращаме HTML, можем да създадем специален шаблон за AJAX заявки: +Ако планирате да отговорите със специален шаблон, предназначен за AJAX, можете да го направите по следния начин: ```php public function handleClick($param): void @@ -44,27 +47,37 @@ public function handleClick($param): void if ($this->isAjax()) { $this->template->setFile('path/to/ajax.latte'); } - // ... + //... } ``` +Извадки .[#toc-snippets] +======================== + +Най-мощният инструмент, предлаган от Nette за свързване на сървъра с клиента, са фрагментите. С тях можете да превърнете едно обикновено приложение в AJAX приложение с минимални усилия и няколко реда код. Примерът Fifteen демонстрира как работи всичко това, а кодът му може да бъде намерен в [GitHub |https://github.com/nette-examples/fifteen]. + +Извадките или изрезките ви позволяват да актуализирате само части от страницата, вместо да презареждате цялата страница. Това е по-бързо и по-ефективно, а също така осигурява по-удобно потребителско изживяване. Snippets може да ви напомнят за Hotwire за Ruby on Rails или Symfony UX Turbo. Интересното е, че Nette въвежда фрагментите 14 години по-рано. + +Как работят отрязъците? Когато страницата се зарежда за първи път (заявка, която не е свързана с AJAX), се зарежда цялата страница, включително всички фрагменти. Когато потребителят взаимодейства със страницата (напр. щракне върху бутон, изпрати формуляр и т.н.), вместо да се зареди цялата страница, се прави AJAX заявка. Кодът в презентатора извършва действието и решава кои фрагменти се нуждаят от актуализиране. Nette визуализира тези фрагменти и ги изпраща под формата на JSON масив. След това кодът за обработка в браузъра вмъква получените фрагменти обратно в страницата. Следователно се прехвърля само кодът на променените фрагменти, което спестява честотна лента и ускорява зареждането в сравнение с прехвърлянето на цялото съдържание на страницата. + + Naja .[#toc-naja] -================= +----------------- -[Библиотеката Naja |https://naja.js.org] се използва за обработка на AJAX заявки от страна на браузъра. [Инсталирайте |https://naja.js.org/#/guide/01-install-setup-naja] го като пакет за node.js (за използване с Webpack, Rollup, Vite, Parcel и други): +За обработка на фрагменти от страна на браузъра се използва [библиотеката Naja |https://naja.js.org]. [Инсталирайте я |https://naja.js.org/#/guide/01-install-setup-naja] като пакет за node.js (за използване с приложения като Webpack, Rollup, Vite, Parcel и други): ```shell npm install naja ``` -...или да вмъкнете директно в шаблон на страница: +... или я вмъкнете директно в шаблона на страницата: ```html ``` -За да създадете AJAX заявка от обикновена връзка (сигнал) или подаване на формуляр, просто маркирайте съответната връзка, формуляр или бутон с класа `ajax`: +За да превърнете обикновена връзка (сигнал) или подаване на форма в AJAX заявка, просто маркирайте съответната връзка, форма или бутон с класа `ajax`: ```html Go @@ -74,64 +87,39 @@ npm install naja or +
``` -Извадки .[#toc-snippety] -======================== - -Има обаче много по-мощен инструмент за вградена поддръжка на AJAX - фрагменти. Използването им ви позволява да превърнете обикновено приложение в AJAX приложение само с няколко реда код. Как работи всичко това, е показано в примера Fifteen, чийто код също е наличен в компилацията или в [GitHub |https://github.com/nette-examples/fifteen]. - -Принципът на фрагментите е, че цялата страница се прехвърля по време на първоначалната (т.е. не-AJAX) заявка и след това при всяка AJAX [подзаявка |components#Signal] (заявка на същия изглед от същия водещ) само кодът на променените части се прехвърля в хранилището `payload`, споменато по-рано. - -Извадките може да ви напомнят за Hotwire за Ruby on Rails или Symfony UX Turbo, но Nette ги изобретява четиринадесет години по-рано. +Прерисуване на фрагменти .[#toc-redrawing-snippets] +--------------------------------------------------- - -Инвалидизация .[#toc-invalidation-of-snippets] -============================================== - -Всеки наследник на класа [Control |components] (какъвто е Presenter) може да запомни дали по време на заявката е имало промени, които изискват повторно картографиране. Съществуват няколко начина за справяне с това: `redrawControl()` и `isControlInvalid()`. Пример: +Всеки обект от класа [Control |components] (включително самият Presenter) запазва запис дали са настъпили промени, които налагат прерисуването му. За тази цел се използва методът `redrawControl()`. ```php public function handleLogin(string $user): void { - // Обектът трябва да бъде показан отново, след като потребителят е влязъл в системата + // след като влезете в системата, е необходимо да прерисувате съответната част $this->redrawControl(); - // ... + //... } ``` -Nette обаче осигурява още по-фина разделителна способност от целите компоненти. Изброените методи приемат името на така наречения "фрагмент" като незадължителен параметър. "Фрагмент" по същество е елемент от вашия шаблон, маркиран с макрос Latte за тази цел, за който ще стане дума по-късно. По този начин можете да поискате от компонент да прерисува само *част* от шаблона. Ако целият компонент е невалиден, всички негови фрагменти се прерисуват. Компонент е "невалиден", ако някой от неговите подкомпоненти е невалиден. - -```php -$this->isControlInvalid(); // -> false -$this->redrawControl('header'); // обезсилване на фрагмента с име 'header' -$this->isControlInvalid('header'); // -> true -$this->isControlInvalid('footer'); // -> false -$this->isControlInvalid(); // -> true, поне един фрагмент е невалиден +Nette също така позволява по-фино управление на това, което трябва да се прерисува. Гореспоменатият метод може да приема името на фрагмента като аргумент. По този начин е възможно да се обезсили (което означава: да се наложи прерисуване) на ниво част от шаблона. Ако целият компонент бъде обезсилен, всеки фрагмент от него също ще бъде прерисуван: -$this->redrawControl(); // обезсилва целия компонент, всеки фрагмент -$this->isControlInvalid('footer'); // -> true +```php +// обезсилва фрагмента 'header' +$this->redrawControl('header'); ``` -Компонент, който е получил сигнал, автоматично се маркира за прерисуване. - -Чрез преначертаване на срезовете знаем точно кои части от кои елементи трябва да бъдат преначертани. - - -Етикет `{snippet} … {/snippet}` .{toc: Tag snippet} -=================================================== -Страницата се визуализира по същия начин, както при обикновена заявка: зареждат се същите шаблони и т.н. Най-важното обаче е да се предотвратят онези части, които не трябва да се извеждат; останалите части трябва да се свържат с идентификатор и да се изпратят на потребителя във формат, който обработващият JavaScript може да разбере. +Извадки в Latte .[#toc-snippets-in-latte] +----------------------------------------- - -Синтаксис .[#toc-sintaksis] ---------------------------- - -Ако в шаблона има контролен елемент или фрагмент, трябва да го обгърнем с помощта на сдвоения таг `{snippet} ... {/snippet}` - визуализираният фрагмент ще бъде "изрязан" и изпратен на браузъра. Освен това той ще го обгърне със спомагателен таг `
` (можете да използвате друга). Следващият пример дефинира фрагмент с име `header`. Той може да представлява и шаблон на компонент: +Използването на фрагменти в Latte е изключително лесно. За да определите част от шаблона като фрагмент, просто я обвийте в тагове `{snippet}` и `{/snippet}`: ```latte {snippet header} @@ -139,7 +127,9 @@ $this->isControlInvalid('footer'); // -> true {/snippet} ``` -Ако искате да създадете фрагмент със съдържащ елемент, различен от `
`, или да добавите потребителски атрибути към елемента, можете да използвате следното определение: +Извадката създава елемент `
` в HTML страницата със специално генериран `id`. При прерисуване на фрагмент съдържанието на този елемент се актуализира. Следователно при първоначалното визуализиране на страницата трябва да се визуализират и всички фрагменти, дори ако първоначално те могат да бъдат празни. + +Можете също така да създадете фрагмент с елемент, различен от `
` като използвате атрибут n:: ```latte
@@ -148,138 +138,106 @@ $this->isControlInvalid('footer'); // -> true ``` -Динамични фрагменти .[#toc-dinamiceskie-snippety] -================================================= +Области на извадките .[#toc-snippet-areas] +------------------------------------------ -В Nette можете също така да дефинирате фрагменти с динамично име въз основа на параметър по време на изпълнение. Това е най-подходящо за различни списъци, в които трябва да променим само един ред, но не искаме да преместим целия списък заедно с него. Пример за това е: +Имената на фрагментите могат да бъдат и изрази: ```latte - +{foreach $items as $id => $item} +
  • {$item}
  • +{/foreach} ``` -Съществува един статичен фрагмент `itemsContainer`, който съдържа няколко динамични фрагмента: `пункт-0`, `пункт-1` и т.н. +По този начин ще получим няколко фрагмента като `item-0`, `item-1` и т.н. Ако директно обезсилим динамичен фрагмент (например `item-1`), нищо няма да бъде прерисувано. Причината е, че фрагментите функционират като истински откъси и само те самите се визуализират директно. В шаблона обаче технически няма фрагмент с име `item-1`. Той се появява само при изпълнение на заобикалящия го код на фрагмента, в този случай цикъла foreach. Следователно ще маркираме частта от шаблона, която трябва да се изпълни, с тага `{snippetArea}`: -Не можете да прерисувате динамичния фрагмент директно (прерисуването на `item-1` няма ефект), а трябва да прерисувате родителския фрагмент ( `itemsContainer` в този пример). При това се изпълнява кодът на родителския фрагмент, но на браузъра се предават само неговите вложени фрагменти. Ако искате да предадете само един от вложените фрагменти, трябва да промените входа за родителския фрагмент, за да избегнете генерирането на други вложени фрагменти. +```latte +
      + {foreach $items as $id => $item} +
    • {$item}
    • + {/foreach} +
    +``` -В горния пример трябва да се уверите, че само един елемент ще бъде добавен към масива `$list`, когато бъде направена заявката AJAX, така че цикълът `foreach` ще изведе само един динамичен фрагмент. +И ще прерисуваме както отделния фрагмент, така и цялата обща област: ```php -class HomePresenter extends Nette\Application\UI\Presenter -{ - /** - * Этот метод возвращает данные для списка. - * Обычно это просто запрос данных из модели. - * Для целей этого примера данные жёстко закодированы. - */ - private function getTheWholeList(): array - { - return [ - 'First', - 'Second', - 'Third', - ]; - } - - public function renderDefault(): void - { - if (!isset($this->template->list)) { - $this->template->list = $this->getTheWholeList(); - } - } - - public function handleUpdate(int $id): void - { - $this->template->list = $this->isAjax() - ? [] - : $this->getTheWholeList(); - $this->template->list[$id] = 'Updated item'; - $this->redrawControl('itemsContainer'); - } -} +$this->redrawControl('itemsContainer'); +$this->redrawControl('item-1'); ``` +Също така е важно да се гарантира, че масивът `$items` съдържа само елементите, които трябва да бъдат прерисувани. -Извадки в активирания шаблон .[#toc-snippety-vo-vklyucennom-sablone] -==================================================================== - -Възможно е даден фрагмент да се намира в шаблон, който е включен от друг шаблон. В този случай е необходимо да се обгърне кодът за разрешаване във втория шаблон с макроса `snippetArea`, след което да се прерисуват както областта snippetArea, така и самият фрагмент. - -Макросът `snippetArea` гарантира, че кодът в него ще бъде изпълнен, но само действителният фрагмент от включения шаблон ще бъде изпратен на браузъра. +При вмъкване на друг шаблон в основния с помощта на тага `{include}`, който има фрагменти, е необходимо отново да се обвие включеният шаблон в `snippetArea` и да се обезсилят заедно и фрагментът, и областта: ```latte -{* parent.latte *} -{snippetArea wrapper} - {include 'child.latte'} +{snippetArea include} + {include 'included.latte'} {/snippetArea} ``` + ```latte -{* child.latte *} +{* included.latte *} {snippet item} -... + ... {/snippet} ``` + ```php -$this->redrawControl('wrapper'); +$this->redrawControl('include'); $this->redrawControl('item'); ``` -Можете също така да го комбинирате с динамични фрагменти. - -Добавяне и премахване .[#toc-dobavlenie-i-udalenie] -=================================================== +Извадки в компонентите .[#toc-snippets-in-components] +----------------------------------------------------- -Ако добавите нов елемент в списъка и отмените `itemsContainer`, заявката AJAX ще върне фрагменти, включващи новия елемент, но обработващият javascript няма да може да го визуализира. Това е така, защото няма HTML елемент с новосъздадения ID. - -В този случай най-лесният начин е да обвиете целия списък в друг фрагмент и да го обезсилите: +Можете да създавате фрагменти в [компонентите |components] и Nette автоматично ще ги прерисува. Има обаче специфично ограничение: за да прерисува отрязъци, той извиква метода `render()` без никакви параметри. По този начин подаването на параметри в шаблона няма да работи: ```latte -{snippet wholeList} - -{/snippet} -Добавить +OK +{control productGrid} + +will not work: +{control productGrid $arg, $arg} +{control productGrid:paginator} ``` + +Изпращане на потребителски данни .[#toc-sending-user-data] +---------------------------------------------------------- + +Заедно с фрагментите можете да изпращате всякакви допълнителни данни на клиента. Просто ги запишете в обекта `payload`: + ```php -public function handleAdd(): void +public function actionDelete(int $id): void { - $this->template->list = $this->getTheWholeList(); - $this->template->list[] = 'New one'; - $this->redrawControl('wholeList'); + //... + if ($this->isAjax()) { + $this->payload->message = 'Success'; + } } ``` -Същото важи и за изтриване на елемент. Може да се подаде празен фрагмент, но обикновено списъците могат да бъдат странирани и би било трудно да се приложи премахването на един елемент и зареждането на друг (който преди това е бил на друга страница на странирания списък). +Изпращане на параметри .[#toc-sending-parameters] +================================================= -Изпращане на параметри към компонент .[#toc-otpravka-parametrov-komponentu] -=========================================================================== - -Когато изпращаме параметри към компонент чрез заявка AJAX, независимо дали става въпрос за сигнални или постоянни параметри, трябва да предоставим тяхното глобално име, което съдържа и името на компонента. Пълното име на параметъра се връща от метода `getParameterId()`. +Когато изпращаме параметри към компонента чрез AJAX заявка, независимо дали става въпрос за сигнални или постоянни параметри, трябва да предоставим тяхното глобално име, което съдържа и името на компонента. Пълното име на параметъра се връща от метода `getParameterId()`. ```js -$.getJSON( - {link changeCountBasket!}, - { - {$control->getParameterId('id')}: id, - {$control->getParameterId('count')}: count - } -}); +let url = new URL({link //foo!}); +url.searchParams.set({$control->getParameterId('bar')}, bar); + +fetch(url, { + headers: {'X-Requested-With': 'XMLHttpRequest'}, +}) ``` -И обработете метода със съответните параметри в компонента. +Метод за обработка със съответните параметри в компонента: ```php -public function handleChangeCountBasket(int $id, int $count): void +public function handleFoo(int $bar): void { - } ``` diff --git a/application/bg/components.texy b/application/bg/components.texy index 3bd9a2ebf9..0a8293d052 100644 --- a/application/bg/components.texy +++ b/application/bg/components.texy @@ -380,7 +380,7 @@ interface PollControlFactory Компонентите в Nette Application са части за многократна употреба на уеб приложение, които вграждаме в страници, което е предмет на тази глава. Какви са възможностите на такъв компонент? 1) може да се показва в шаблон -2) той знае каква част от себе си да покаже по време на [заявката AJAX |ajax#invalidation] (фрагменти) +2) знае [коя част от себе си |ajax#snippets] да визуализира по време на заявка AJAX (фрагменти). 3) има възможност да съхранява състоянието си в URL (постоянни параметри). 4) има възможност да реагира на действията (сигналите) на потребителя. 5) създава йерархична структура (където коренът е главният). diff --git a/application/cs/ajax.texy b/application/cs/ajax.texy index 18e53a91a5..407622ab95 100644 --- a/application/cs/ajax.texy +++ b/application/cs/ajax.texy @@ -3,10 +3,10 @@ AJAX & snippety
    -Moderní webové aplikace dnes běží napůl na serveru, napůl v prohlížeči. AJAX je tím klíčovým spojovacím prvkem. Jakou podporu nabízí Nette Framework? -- posílání výřezů šablony (tzv. snippety) +V éře moderních webových aplikací, kde se často rozkládá funkcionalita mezi serverem a prohlížečem, je AJAX nezbytným spojovacím prvkem. Jaké možnosti nám v této oblasti nabízí Nette Framework? +- odesílání částí šablony, tzv. snippetů - předávání proměnných mezi PHP a JavaScriptem -- debugování AJAXových aplikací +- nástroje pro debugování AJAXových požadavků
    @@ -14,29 +14,32 @@ Moderní webové aplikace dnes běží napůl na serveru, napůl v prohlížeči AJAXový požadavek ================= -AJAXový požadavek se nijak neliší od klasického požadavku - je zavolán presenter s určitým view a parametry. Je také věcí presenteru, jak bude na něj reagovat: může použít vlastní rutinu, která vrátí nějaký fragment HTML kódu (HTML snippet), XML dokument, JSON objekt nebo kód v JavaScriptu. +AJAXový požadavek se v zásadě neliší od klasického HTTP požadavku. Zavolá se presenter s určitými parametry. A je na presenteru, jakým způsobem bude na požadavek reagovat - může vrátit data ve formátu JSON, odeslat část HTML kódu, XML dokument, atd. -Na straně serveru lze AJAXový požadavek detekovat metodou služby [zapouzdřující HTTP požadavek |http:request] `$httpRequest->isAjax()` (detekuje podle HTTP hlavičky `X-Requested-With`). Uvnitř presenteru je k dispozici "zkratka" v podobě metody `$this->isAjax()`. +Na straně prohlížeče inicializujeme AJAXový požadavek pomocí funkce `fetch()`: -Pro odesílání dat prohlížeči ve formátu JSON lze využít předpřipravený objekt `payload`: - -```php -public function actionDelete(int $id): void -{ - if ($this->isAjax()) { - $this->payload->message = 'Success'; - } - // ... -} +```js +fetch(url, { + headers: {'X-Requested-With': 'XMLHttpRequest'}, +}) +.then(response => response.json()) +.then(payload => { + // zpracování odpovědi +}); ``` -Pokud potřebujete plnou kontrolu nad odeslaným JSONem, použijte metodu `sendJson` v presenteru. Tím ihned ukončíte činnost presenteru a obejdete se i bez šablony: +Na straně serveru rozpoznáme AJAXový požadavek metodou `$httpRequest->isAjax()` služby [zapouzdřující HTTP požadavek |http:request]. K detekci používá HTTP hlavičku `X-Requested-With`, proto je důležité ji odesílat. V rámci presenteru lze použít metodu `$this->isAjax()`. + +Chcete-li odeslat data ve formátu JSON, použijte metodu [`sendJson()` |presenters#Odeslání odpovědi]. Metoda rovněž ukončí činnost presenteru. ```php -$this->sendJson(['key' => 'value', /* ... */]); +public function actionExport(): void +{ + $this->sendJson($this->model->getData); +} ``` -Když chceme odeslat HTML, můžeme jednak zvolit speciální šablonu pro AJAX: +Máte-li v plánu odpovědět pomocí speciální šablony určené pro AJAX, můžete to udělat následovně: ```php public function handleClick($param): void @@ -49,10 +52,20 @@ public function handleClick($param): void ``` +Snippety +======== + +Nejsilnější prostředek, který nabízí Nette pro propojení serveru s klientem, představují snippety. Díky nim můžete z obyčejné aplikace udělat AJAXovou jen s minimálním úsilím a několika řádky kódu. Jak to celé funguje demonstruje příklad Fifteen, jehož kód najdete na [GitHubu |https://github.com/nette-examples/fifteen]. + +Snippety, nebo-li výstřižky, umožnují aktualizovat jen části stránky, místo toho, aby se celá stránka znovunačítala. Jednak je to rychlejší a efektivnější, ale poskytuje to také komfortnější uživatelský zážitek. Snippety vám mohou připomínat Hotwire pro Ruby on Rails nebo Symfony UX Turbo. Zajímavé je, že Nette představilo snippety již o 14 let dříve. + +Jak snippety fungují? Při prvním načtení stránky (ne-AJAXovém požadavku) se načte celá stránka včetně všech snippetů. Když uživatel interaguje se stránkou (např. klikne na tlačítko, odešle formulář, atd.), místo načtení celé stránky se vyvolá AJAXový požadavek. Kód v presenteru provede akci a rozhodne, které snippety je třeba aktualizovat. Nette tyto snippety vykreslí a odešle ve formě pole ve formátu JSON. Obslužný kód v prohlížeči získané snippety vloží zpět do stránky. Přenáší se tedy jen kód změněných snippetů, což šetří šířku pásma a zrychluje načítání oproti přenášení obsahu celé stránky. + + Naja -==== +---- -K obsluze AJAXových požadavků na straně prohlížeče slouží [knihovna Naja |https://naja.js.org]. Tu [nainstalujte |https://naja.js.org/#/guide/01-install-setup-naja] jako node.js balíček (pro použití s aplikacemi Webpack, Rollup, Vite, Parcel a dalšími): +K obsluze snippetů na straně prohlížeče slouží [knihovna Naja |https://naja.js.org]. Tu [nainstalujte |https://naja.js.org/#/guide/01-install-setup-naja] jako node.js balíček (pro použití s aplikacemi Webpack, Rollup, Vite, Parcel a dalšími): ```shell npm install naja @@ -74,64 +87,39 @@ Aby se z obyčejného odkazu (signálu) nebo odeslání formuláře vytvořil AJ nebo +
    ``` -Snippety -======== - -Daleko silnější nástroj představuje vestavěná podpora AJAXových snippetů. Díky ní lze udělat z obyčejné aplikace AJAXovou prakticky několika řádky kódu. Jak to celé funguje, demonstruje příklad Fifteen, jehož kód najdete na [GitHubu |https://github.com/nette-examples/fifteen]. - -Snippety fungují tak, že při prvotním (tedy neAJAXovém) požadavku se přenese celá stránka a poté se při každém již AJAXovém [subrequestu |components#Signál] (= požadavku na stejný presenter a view) přenáší pouze kód změněných částí ve zmíněném úložišti `payload`. K tomu slouží dva mechanismy: invalidace a renderování snippetů. - -Snippety vám mohou připomínat Hotwire pro Ruby on Rails nebo Symfony UX Turbo, nicméně Nette s nimi přišlo už o čtrnáct let dříve. +Překreslení snippetů +-------------------- - -Invalidace snippetů -=================== - -Každý objekt třídy [Control |components] (což je i samotný Presenter) si umí zapamatovat, jestli při signálu došlo ke změnám, které si vyžadují jej překreslit. K tomu slouží dvojice metod `redrawControl()` a `isControlInvalid()`. Příklad: +Každý objekt třídy [Control |components] (včetně samotného Presenteru) eviduje, zda došlo ke změnám vyžadujícím jeho překreslení. K tomu slouží metoda `redrawControl()`: ```php public function handleLogin(string $user): void { - // po přihlášení uživatele se musí objekt překreslit + // po přihlášení je potřeba překreslit relevantní část $this->redrawControl(); // ... } ``` -Nette však nabízí ještě jemnější rozlišení, než na úrovni komponent. Uvedené metody mohou totiž jako argument přijímat název tzv. "snippetu", nebo-li výstřižku. Lze tedy invalidovat (rozuměj: vynutit překreslení) na úrovni těchto snippetů (každý objekt může mít libovolné množství snippetů). Pokud se invaliduje celá komponenta, tak se i každý snippet překreslí. Komponenta je "invalidní" i tehdy, pokud je invalidní některá její subkomponenta. - -```php -$this->isControlInvalid(); // -> false -$this->redrawControl('header'); // invaliduje snippet 'header' -$this->isControlInvalid('header'); // -> true -$this->isControlInvalid('footer'); // -> false -$this->isControlInvalid(); // -> true, alespoň jeden snippet je invalid +Nette umožňuje ještě jemnější kontrolu toho, co se má překreslit. Uvedená metoda totiž může jako argument přijímat název snippetu. Lze tedy invalidovat (rozuměj: vynutit překreslení) na úrovni částí šablony. Pokud se invaliduje celá komponenta, tak se překreslí i každý její snippet: -$this->redrawControl(); // invaliduje celou komponentu, každý snippet -$this->isControlInvalid('footer'); // -> true +```php +// invaliduje snippet 'header' +$this->redrawControl('header'); ``` -Komponenta, která přijímá signál, je automaticky označena za invalidní. - -Díky invalidaci snippetů přesně víme, které části kterých prvků bude potřeba překreslit. - - -Tagy `{snippet} … {/snippet}` .{toc: Tag snippet} -================================================= - -Vykreslování stránky probíhá velmi podobně jako při běžném požadavku: načtou se stejné šablony atd. Podstatné však je vynechání částí, které se nemají dostat na výstup; ostatní části se přiřadí k identifikátoru a pošlou se uživateli ve formátu srozumitelném pro obslužný program JavaScriptu. - -Syntaxe -------- +Snippety v Latte +---------------- -Pokud se uvnitř šablony nachází control nebo snippet, musíme jej obalit párovou značkou `{snippet} ... {/snippet}` - ty totiž zajistí, že se vykreslený snippet vystřihne a pošle do prohlížeče. Také jej obalí pomocnou značkou `
    ` s vygenerovaným `id`. V uvedeném příkladě je snippet pojmenován jako `header` a může představovat i například šablonu controlu: +Používání snippetů v Latte je nesmírně snadné. Chcete-li definovat část šablony jako snippet, obalte ji jednoduše značkami `{snippet}` a `{/snippet}`: ```latte {snippet header} @@ -139,7 +127,9 @@ Pokud se uvnitř šablony nachází control nebo snippet, musíme jej obalit pá {/snippet} ``` -Snippetu jiného typu než `
    ` nebo snippetu s dalšími HTML atributy docílíme použitím atributové varianty: +Snippet vytvoří v HTML stránce element `
    ` se speciálním vygenerovaným `id`. Při překreslení snippetu se pak aktulizuje obsah tohoto elementu. Proto je nutné, aby při prvotním vykreslení stránky se vykreslily také všechny snippety, byť mohou být třeba na začátku prázdné. + +Můžete vytvořit i snippet s jiným elementem než `
    ` pomocí n:attributu: ```latte
    @@ -148,138 +138,106 @@ Snippetu jiného typu než `
    ` nebo snippetu s dalšími HTML atributy docí ``` -Dynamické snippety -================== +Oblasti snippetů +---------------- -Nette také umožňuje používání snippetů, jejichž název se vytvoří až za běhu - tj. dynamicky. Hodí se to pro různé seznamy, kde při změně jednoho řádku nechceme přenášet AJAXem celý seznam, ale stačí onen samotný řádek. Příklad: +Názvy snippetů mohou být také výrazy: ```latte -
      - {foreach $list as $id => $item} -
    • {$item} update
    • - {/foreach} -
    +{foreach $items as $id => $item} +
  • {$item}
  • +{/foreach} ``` -Zde máme statický snippet `itemsContainer`, obsahující několik dynamických snippetů `item-0`, `item-1` atd. +Takto nám vznikne několik snippetů `item-0`, `item-1` atd. Pokud bychom přímo invalidovali dynamický snippet (například `item-1`), nepřekreslilo by se nic. Důvod je ten, že snippety opravdu fungují jako výstřižky a vykreslují se jen přímo ony samotné. Jenže v šabloně fakticky žádný snippet pojmenovaný `item-1` není. Ten vznikne až vykonáváním kódu v okolí snippetu, tedy cyklu foreach. Označíme proto část šablony, která se má vykonat pomocí značky `{snippetArea}`: -Dynamické snippety nelze invalidovat přímo (invalidace `item-1` neudělá vůbec nic), musíte invalidovat jim nadřazený statický snippet (zde snippet `itemsContainer`). Potom dojde k tomu, že se provede celý kód toho kontejneru, ale prohlížeči se pošlou jenom jeho sub-snippety. Pokud chcete, aby prohlížeč dostal pouze jediný z nich, musíte upravit vstup toho kontejneru tak, aby ostatní negeneroval. +```latte +
      + {foreach $items as $id => $item} +
    • {$item}
    • + {/foreach} +
    +``` -V příkladu výše zkrátka musíte zajistit, aby při ajaxovém požadavku byla v proměnné `$list` pouze jedna položka a tedy aby ten cyklus `foreach` naplnil pouze jeden dynamický snippet: +A necháme překreslit jak samotný snippet, tak i celou nadřazenou oblast: ```php -class HomePresenter extends Nette\Application\UI\Presenter -{ - /** - * Tato metoda vrací data pro seznam. - * Obvykle se jedná pouze o vyžádání dat z modelu. - * Pro účely tohoto příkladu jsou data zadána natvrdo. - */ - private function getTheWholeList(): array - { - return [ - 'První', - 'Druhý', - 'Třetí', - ]; - } - - public function renderDefault(): void - { - if (!isset($this->template->list)) { - $this->template->list = $this->getTheWholeList(); - } - } - - public function handleUpdate(int $id): void - { - $this->template->list = $this->isAjax() - ? [] - : $this->getTheWholeList(); - $this->template->list[$id] = 'Updated item'; - $this->redrawControl('itemsContainer'); - } -} +$this->redrawControl('itemsContainer'); +$this->redrawControl('item-1'); ``` +Zároveň je vhodné zajistit, aby pole `$items` obsahovalo jen ty položky, které se mají překreslit. -Snippety v includované šabloně -============================== - -Může se stát, že máme snippet v šabloně, kterou teprve includujeme do jiné šablony. V takovém případě je nutné vkládání této šablony obalit značkami `snippetArea`, které pak invalidujeme spolu se samotnym snippetem. - -Tagy `snippetArea` zaručí, že se daný kód, který vkládá šablonu, provede, do prohlížeče se však odešle pouze snippet v includované šabloně. +Pokud do šablony vkládáme pomocí značky `{include}` jinou šablonu, která obsahuje snippety, je nutné vložení šablony opět zahrnout do `snippetArea` a tu invalidovat společně se snippetem: ```latte -{* parent.latte *} -{snippetArea wrapper} -{include 'child.latte'} +{snippetArea include} + {include 'included.latte'} {/snippetArea} ``` + ```latte -{* child.latte *} +{* included.latte *} {snippet item} -... + ... {/snippet} ``` + ```php -$this->redrawControl('wrapper'); +$this->redrawControl('include'); $this->redrawControl('item'); ``` -Tento přístup se nechá použít i v kombinaci s dynamickými snippety. - -Přidávání a mazání -================== +Snippety v komponentách +----------------------- -Pokud přidáte novou položku a invalidujete `itemsContainer`, pak vám AJAXový požadavek sice vrátí i nový snippet, ale obslužný javascript ho neumí nikam přiřadit. Na stránce totiž zatím není žádný HTML prvek s takovým ID. - -V takovém případě je nejjednodušší celý ten seznam obalit ještě jedním snippetem a invalidovat to celé: +Snippety můžete vytvářet i v [komponentách|components] a Nette je bude automaticky překreslovat. Ale platí tu určité omezení: pro překreslení snippetů volá metodu `render()` bez parametrů. Tedy nebude fungovat předávání parametrů v šabloně: ```latte -{snippet wholeList} -
      - {foreach $list as $id => $item} -
    • {$item} update
    • - {/foreach} -
    -{/snippet} -Add +OK +{control productGrid} + +nebude fungovat: +{control productGrid $arg, $arg} +{control productGrid:paginator} ``` + +Posílání uživatelských dat +-------------------------- + +Společně se snippety můžete klientovi poslat libovolná další data. Stačí je zapsat do objektu `payload`: + ```php -public function handleAdd(): void +public function actionDelete(int $id): void { - $this->template->list = $this->getTheWholeList(); - $this->template->list[] = 'New one'; - $this->redrawControl('wholeList'); + // ... + if ($this->isAjax()) { + $this->payload->message = 'Success'; + } } ``` -Totéž platí i pro mazání. Sice by se dal nějak poslat prázdný snippet, jenže v praxi jsou většinou seznamy stránkované a řešit úsporněji smazání jednoho plus případné načtení jiného (který se předtím nevešel) by bylo příliš složité. - -Posílání parametrů do komponenty -================================ +Předávání parametrů +=================== Pokud komponentě pomocí AJAXového požadavku odesíláme parametry, ať už parametry signálu nebo persistentní parametry, musíme u požadavku uvést jejich globální název, který obsahuje i jméno komponenty. Celý název parametru vrací metoda `getParameterId()`. ```js -$.getJSON( - {link changeCountBasket!}, - { - {$control->getParameterId('id')}: id, - {$control->getParameterId('count')}: count - } -}); +let url = new URL({link //foo!}); +url.searchParams.set({$control->getParameterId('bar')}, bar); + +fetch(url, { + headers: {'X-Requested-With': 'XMLHttpRequest'}, +}) ``` -A handle metoda s odpovídajícími parametry v komponentě. +A handle metoda s odpovídajícími parametry v komponentě: ```php -public function handleChangeCountBasket(int $id, int $count): void +public function handleFoo(int $bar): void { - } ``` diff --git a/application/cs/components.texy b/application/cs/components.texy index c7ca3c65ef..649c1a6b0d 100644 --- a/application/cs/components.texy +++ b/application/cs/components.texy @@ -380,7 +380,7 @@ Komponenty do hloubky Komponenty v Nette Application představují znovupoužitelné součásti webové aplikace, které vkládáme do stránek a kterým se ostatně věnuje celá tato kapitola. Jaké přesně schopnosti taková komponenta má? 1) je vykreslitelná v šabloně -2) ví, kterou svou část má vykreslit při [AJAXovém požadavku |ajax#invalidace] (snippety) +2) ví, [kterou svou část|ajax#snippety] má vykreslit při AJAXovém požadavku (snippety) 3) má schopnost ukládat svůj stav do URL (persistentní parametry) 4) má schopnost reagovat na uživatelské akce (signály) 5) vytváří hierarchickou strukturu (kde kořenem je presenter) diff --git a/application/de/ajax.texy b/application/de/ajax.texy index 12a3014a57..9b97c2db0e 100644 --- a/application/de/ajax.texy +++ b/application/de/ajax.texy @@ -3,10 +3,10 @@ AJAX & Schnipsel
    -Moderne Webanwendungen laufen heute zur Hälfte auf einem Server und zur Hälfte in einem Browser. AJAX ist ein wichtiger verbindender Faktor. Welche Unterstützung bietet das Nette Framework? -- Senden von Template-Fragmenten (sogenannte *snippets*) +Im Zeitalter moderner Webanwendungen, bei denen sich die Funktionalität oft zwischen Server und Browser erstreckt, ist AJAX ein wesentliches Verbindungselement. Welche Möglichkeiten bietet das Nette Framework in diesem Bereich? +- Senden von Teilen des Templates, sogenannte Snippets - Übergabe von Variablen zwischen PHP und JavaScript -- Debugging von AJAX-Anwendungen +- Werkzeuge zur Fehlersuche bei AJAX-Anfragen
    @@ -14,29 +14,32 @@ Moderne Webanwendungen laufen heute zur Hälfte auf einem Server und zur Hälfte AJAX-Anfrage .[#toc-ajax-request] ================================= -Eine AJAX-Anfrage unterscheidet sich nicht von einer klassischen Anfrage - der Presenter wird mit einer bestimmten Ansicht und Parametern aufgerufen. Es liegt auch am Präsentator, wie er darauf reagiert: Er kann seine eigene Routine verwenden, die ein HTML-Codefragment (HTML-Snippet), ein XML-Dokument, ein JSON-Objekt oder JavaScript-Code zurückgibt. +Eine AJAX-Anfrage unterscheidet sich im Grunde nicht von einer klassischen HTTP-Anfrage. Ein Presenter wird mit bestimmten Parametern aufgerufen. Es liegt am Präsentator, wie er auf die Anfrage antwortet - er kann Daten im JSON-Format zurückgeben, einen Teil des HTML-Codes, ein XML-Dokument usw. senden. -Auf der Serverseite kann eine AJAX-Anfrage mit Hilfe der Servicemethode erkannt werden [, die die HTTP-Anfrage kapselt |http:request] `$httpRequest->isAjax()` (erkennt auf der Grundlage des HTTP-Headers `X-Requested-With`). Innerhalb des Presenters ist eine Abkürzung in Form der Methode `$this->isAjax()` verfügbar. +Auf der Browserseite initiieren wir eine AJAX-Anfrage mit der Funktion `fetch()`: -Es gibt ein vorverarbeitetes Objekt namens `payload`, das für das Senden von Daten in JSON an den Browser bestimmt ist. - -```php -public function actionDelete(int $id): void -{ - if ($this->isAjax()) { - $this->payload->message = 'Erfolg'; - } - // ... -} +```js +fetch(url, { + headers: {'X-Requested-With': 'XMLHttpRequest'}, +}) +.then(response => response.json()) +.then(payload => { + // Bearbeitung der Antwort +}); ``` -Um die volle Kontrolle über Ihre JSON-Ausgabe zu haben, verwenden Sie die Methode `sendJson` in Ihrem Presenter. Sie beendet den Presenter sofort und Sie können auf eine Vorlage verzichten: +Auf der Serverseite wird eine AJAX-Anfrage durch die Methode `$httpRequest->isAjax()` des Dienstes erkannt [, der die HTTP-Anfrage kapselt |http:request]. Sie verwendet den HTTP-Header `X-Requested-With` und muss daher unbedingt gesendet werden. Innerhalb des Presenters können Sie die Methode `$this->isAjax()` verwenden. + +Wenn Sie Daten im JSON-Format senden möchten, verwenden Sie die [`sendJson()` |presenters#Sending a response] Methode. Die Methode beendet auch die Aktivität des Presenters. ```php -$this->sendJson(['key' => 'value', /* ... */]); +public function actionExport(): void +{ + $this->sendJson($this->model->getData); +} ``` -Wenn wir HTML senden wollen, können wir entweder eine spezielle Vorlage für AJAX-Anfragen festlegen: +Wenn Sie vorhaben, mit einer speziellen Vorlage für AJAX zu antworten, können Sie dies wie folgt tun: ```php public function handleClick($param): void @@ -44,27 +47,37 @@ public function handleClick($param): void if ($this->isAjax()) { $this->template->setFile('path/to/ajax.latte'); } - // ... + //... } ``` +Schnipsel .[#toc-snippets] +========================== + +Das mächtigste Werkzeug, das Nette für die Verbindung zwischen Server und Client bietet, sind Snippets. Mit ihnen lässt sich eine gewöhnliche Anwendung mit minimalem Aufwand und ein paar Zeilen Code in eine AJAX-Anwendung verwandeln. Das Fifteen-Beispiel zeigt, wie das Ganze funktioniert, und der Code ist auf [GitHub |https://github.com/nette-examples/fifteen] zu finden. + +Mit Snippets oder Clippings können Sie nur Teile der Seite aktualisieren, anstatt die gesamte Seite neu zu laden. Das ist schneller und effizienter und bietet zudem eine komfortablere Benutzererfahrung. Snippets erinnern Sie vielleicht an Hotwire für Ruby on Rails oder Symfony UX Turbo. Interessanterweise hat Nette Snippets schon 14 Jahre früher eingeführt. + +Wie funktionieren Snippets? Wenn die Seite zum ersten Mal geladen wird (eine Nicht-AJAX-Anfrage), wird die gesamte Seite, einschließlich aller Snippets, geladen. Wenn der Benutzer mit der Seite interagiert (z. B. auf eine Schaltfläche klickt, ein Formular ausfüllt usw.), wird nicht die gesamte Seite geladen, sondern eine AJAX-Anfrage gestellt. Der Code im Presenter führt die Aktion aus und entscheidet, welche Snippets aktualisiert werden müssen. Nette rendert diese Schnipsel und sendet sie in Form eines JSON-Arrays. Der Verarbeitungscode im Browser fügt dann die empfangenen Snippets wieder in die Seite ein. Es wird also nur der Code der geänderten Snippets übertragen, was im Vergleich zur Übertragung des gesamten Seiteninhalts Bandbreite spart und das Laden beschleunigt. + + Naja .[#toc-naja] -================= +----------------- -Die [Naja-Bibliothek |https://naja.js.org] wird verwendet, um AJAX-Anfragen auf der Browserseite zu verarbeiten. [Installieren |https://naja.js.org/#/guide/01-install-setup-naja] Sie sie als node.js-Paket (zur Verwendung mit Webpack, Rollup, Vite, Parcel und mehr): +Um Snippets auf der Browserseite zu verarbeiten, wird die [Naja-Bibliothek |https://naja.js.org] verwendet. [Installieren Sie sie |https://naja.js.org/#/guide/01-install-setup-naja] als node.js-Paket (zur Verwendung mit Anwendungen wie Webpack, Rollup, Vite, Parcel und anderen): ```shell npm install naja ``` -...oder fügen Sie sie direkt in die Seitenvorlage ein: +... oder fügen Sie sie direkt in die Seitenvorlage ein: ```html ``` -Um eine AJAX-Anfrage aus einem regulären Link (Signal) oder einer Formularübermittlung zu erzeugen, markieren Sie einfach den entsprechenden Link, das Formular oder die Schaltfläche mit der Klasse `ajax`: +Um einen gewöhnlichen Link (Signal) oder eine Formularübermittlung zu einer AJAX-Anfrage zu machen, markieren Sie einfach den entsprechenden Link, das Formular oder die Schaltfläche mit der Klasse `ajax`: ```html Go @@ -74,64 +87,39 @@ Um eine AJAX-Anfrage aus einem regulären Link (Signal) oder einer Formularüber or +
    ``` -Schnipsel .[#toc-snippets] -========================== - -Es gibt ein weitaus mächtigeres Werkzeug der eingebauten AJAX-Unterstützung - Snippets. Mit ihnen ist es möglich, eine normale Anwendung mit nur wenigen Zeilen Code in eine AJAX-Anwendung zu verwandeln. Wie das Ganze funktioniert, wird im Fifteen-Beispiel gezeigt, dessen Code auch im Build oder auf [GitHub |https://github.com/nette-examples/fifteen] verfügbar ist. - -Die Funktionsweise der Snippets besteht darin, dass bei der ersten (d.h. Nicht-AJAX-) Anfrage die gesamte Seite übertragen wird und dann bei jeder [AJAX-Unteranfrage |components#signal] (Anfrage derselben Ansicht desselben Präsentators) nur der Code der geänderten Teile in das bereits erwähnte Repository `payload` übertragen wird. - -Snippets erinnern vielleicht an Hotwire für Ruby on Rails oder Symfony UX Turbo, aber Nette hat sie schon vierzehn Jahre früher erfunden. - - -Invalidierung von Snippets .[#toc-invalidation-of-snippets] -=========================================================== +Schnipsel neu zeichnen .[#toc-redrawing-snippets] +------------------------------------------------- -Jeder Nachkomme der Klasse [Control |components] (also auch ein Presenter) ist in der Lage, sich zu merken, ob es während einer Anfrage Änderungen gab, die ein erneutes Rendern erforderlich machen. Dafür gibt es zwei Methoden: `redrawControl()` und `isControlInvalid()`. Ein Beispiel: +Jedes Objekt der Klasse [Control |components] (einschließlich des Presenters selbst) hält fest, ob Änderungen eingetreten sind, die ein erneutes Zeichnen erforderlich machen. Zu diesem Zweck wird die Methode `redrawControl()` verwendet. ```php public function handleLogin(string $user): void { - // Das Objekt muss neu gerendert werden, nachdem sich der Benutzer angemeldet hat + // nach dem Einloggen muss der entsprechende Teil neu gezeichnet werden $this->redrawControl(); - // ... + //... } ``` -Nette bietet jedoch eine noch feinere Auflösung als ganze Komponenten. Die aufgeführten Methoden akzeptieren den Namen eines sogenannten "Snippets" als optionalen Parameter. Ein "Snippet" ist im Grunde ein Element in Ihrer Vorlage, das zu diesem Zweck durch ein Latte-Makro markiert wurde, mehr dazu später. So ist es möglich, eine Komponente aufzufordern, nur *Teile* ihrer Vorlage neu zu zeichnen. Wenn die gesamte Komponente ungültig ist, werden alle ihre Schnipsel neu gerendert. Eine Komponente ist auch dann "ungültig", wenn eine ihrer Unterkomponenten ungültig ist. -```php -$this->isControlInvalid(); // -> false - -$this->redrawControl('header'); // macht das Snippet namens 'header' ungültig -$this->isControlInvalid('header'); // -> true -$this->isControlInvalid('footer'); // -> false -$this->isControlInvalid(); // -> true, mindestens ein Snippet ist ungültig +Nette ermöglicht auch eine genauere Kontrolle darüber, was neu gezeichnet werden muss. Die oben erwähnte Methode kann den Snippet-Namen als Argument verwenden. So ist es möglich, auf der Ebene des Schablonenteils zu invalidieren (d.h. ein Neuzeichnen zu erzwingen). Wird die gesamte Komponente für ungültig erklärt, wird auch jedes Snippet davon neu gezeichnet: -$this->redrawControl(); // macht die gesamte Komponente ungültig, jedes Snippet -$this->isControlInvalid('footer'); // -> true +```php +// macht den "Header"-Schnipsel ungültig +$this->redrawControl('header'); ``` -Eine Komponente, die ein Signal erhält, wird automatisch zum Neuzeichnen markiert. - -Dank des Snippet-Redrawing wissen wir genau, welche Teile welcher Elemente neu gezeichnet werden sollten. - - -Tag `{snippet} … {/snippet}` .{toc: Tag snippet} -================================================ - -Das Rendering der Seite verläuft ganz ähnlich wie bei einer normalen Anfrage: Es werden die gleichen Vorlagen geladen usw. Entscheidend ist jedoch, dass die Teile, die nicht in die Ausgabe gelangen sollen, weggelassen werden; die anderen Teile sollen mit einem Bezeichner verknüpft und in einem für einen JavaScript-Handler verständlichen Format an den Benutzer gesendet werden. - -Syntax .[#toc-syntax] ---------------------- +Schnipsel in Latte .[#toc-snippets-in-latte] +-------------------------------------------- -Wenn ein Steuerelement oder ein Snippet in der Vorlage vorhanden ist, müssen wir es mit dem `{snippet} ... {/snippet}` pair-Tag einpacken - er sorgt dafür, dass das gerenderte Snippet "ausgeschnitten" und an den Browser gesendet wird. Außerdem wird es in ein Hilfs-Tag eingebettet `
    ` Tag (es ist möglich, einen anderen zu verwenden). Im folgenden Beispiel wird ein Snippet mit dem Namen `header` definiert. Es kann ebenso gut die Vorlage einer Komponente darstellen: +Die Verwendung von Snippets in Latte ist extrem einfach. Um einen Teil der Vorlage als Snippet zu definieren, umhüllen Sie ihn einfach mit den Tags `{snippet}` und `{/snippet}`: ```latte {snippet header} @@ -139,7 +127,9 @@ Wenn ein Steuerelement oder ein Snippet in der Vorlage vorhanden ist, müssen wi {/snippet} ``` -Wenn Sie ein Snippet mit einem anderen Element erstellen möchten als `
    ` erstellen oder dem Element benutzerdefinierte Attribute hinzufügen möchten, können Sie die folgende Definition verwenden: +Das Snippet erzeugt ein Element `
    ` in der HTML-Seite mit einem speziell generierten `id`. Wenn ein Snippet neu gezeichnet wird, wird der Inhalt dieses Elements aktualisiert. Daher müssen beim ersten Rendering der Seite alle Snippets ebenfalls gerendert werden, auch wenn sie zunächst leer sind. + +Sie können auch ein Snippet mit einem anderen Element als `
    ` mit einem n:-Attribut erstellen: ```latte
    @@ -148,138 +138,106 @@ Wenn Sie ein Snippet mit einem anderen Element erstellen möchten als `
    ` er ``` -Dynamische Schnipsel .[#toc-dynamic-snippets] -============================================= +Schnipsel Bereiche .[#toc-snippet-areas] +---------------------------------------- -In Nette können Sie auch Snippets mit einem dynamischen Namen definieren, der auf einem Laufzeitparameter basiert. Dies eignet sich besonders für verschiedene Listen, bei denen nur eine Zeile geändert werden muss, aber nicht die ganze Liste mit übertragen werden soll. Ein Beispiel hierfür wäre: +Snippet-Namen können auch Ausdrücke sein: ```latte -
      - {foreach $list as $id => $item} -
    • {$item} update
    • - {/foreach} -
    +{foreach $items as $id => $item} +
  • {$item}
  • +{/foreach} ``` -Es gibt ein statisches Snippet namens `itemsContainer`, das mehrere dynamische Snippets enthält: `item-0`, `item-1` und so weiter. +Auf diese Weise erhalten wir mehrere Snippets wie `item-0`, `item-1`, usw. Wenn wir einen dynamischen Ausschnitt (z. B. `item-1`) direkt ungültig machen würden, würde nichts neu gezeichnet werden. Der Grund dafür ist, dass Snippets als echte Auszüge funktionieren und nur sie selbst direkt gerendert werden. In der Vorlage gibt es jedoch technisch gesehen kein Snippet namens `item-1`. Es taucht nur auf, wenn der umgebende Code des Snippets ausgeführt wird, in diesem Fall die foreach-Schleife. Daher markieren wir den Teil der Vorlage, der ausgeführt werden muss, mit dem Tag `{snippetArea}`: -Ein dynamisches Snippet kann nicht direkt neu gezeichnet werden (das erneute Zeichnen von `item-1` hat keine Auswirkung), Sie müssen das übergeordnete Snippet (in diesem Beispiel `itemsContainer`) neu zeichnen. Dies bewirkt, dass der Code des übergeordneten Snippets ausgeführt wird, aber nur seine Unter-Snippets an den Browser gesendet werden. Wenn Sie nur einen der Teil-Snippets senden wollen, müssen Sie die Eingabe für das übergeordnete Snippet so ändern, dass die anderen Teil-Snippets nicht erzeugt werden. +```latte +
      + {foreach $items as $id => $item} +
    • {$item}
    • + {/foreach} +
    +``` -Im obigen Beispiel müssen Sie sicherstellen, dass bei einer AJAX-Anfrage nur ein Element zum Array `$list` hinzugefügt wird, so dass die Schleife `foreach` nur ein dynamisches Snippet ausgibt. +Und wir werden sowohl das einzelne Snippet als auch den gesamten übergreifenden Bereich neu zeichnen: ```php -class HomePresenter extends Nette\Application\UI\Presenter -{ - /** - * This method returns data for the list. - * Usually this would just request the data from a model. - * For the purpose of this example, the data is hard-coded. - */ - private function getTheWholeList(): array - { - return [ - 'First', - 'Second', - 'Third', - ]; - } - - public function renderDefault(): void - { - if (!isset($this->template->list)) { - $this->template->list = $this->getTheWholeList(); - } - } - - public function handleUpdate(int $id): void - { - $this->template->list = $this->isAjax() - ? [] - : $this->getTheWholeList(); - $this->template->list[$id] = 'Updated item'; - $this->redrawControl('itemsContainer'); - } -} +$this->redrawControl('itemsContainer'); +$this->redrawControl('item-1'); ``` +Es ist auch wichtig, dass das Array `$items` nur die Elemente enthält, die neu gezeichnet werden sollen. -Snippets in einer eingebundenen Vorlage .[#toc-snippets-in-an-included-template] -================================================================================ - -Es kann vorkommen, dass sich das Snippet in einer Vorlage befindet, die von einer anderen Vorlage eingebunden wird. In diesem Fall müssen wir den Einbindungscode in der zweiten Vorlage mit dem `snippetArea` -Makro einschließen, dann zeichnen wir sowohl den Snippet-Bereich als auch das eigentliche Snippet neu. - -Das Makro `snippetArea` sorgt dafür, dass der darin enthaltene Code ausgeführt wird, aber nur das eigentliche Snippet in der eingebundenen Vorlage an den Browser gesendet wird. +Beim Einfügen einer anderen Vorlage in die Hauptvorlage unter Verwendung des `{include}` -Tags, das Snippets enthält, muss die eingefügte Vorlage erneut in ein `snippetArea` -Tag eingeschlossen und sowohl das Snippet als auch der Bereich gemeinsam ungültig gemacht werden: ```latte -{* parent.latte *} -{snippetArea wrapper} - {include 'child.latte'} +{snippetArea include} + {include 'included.latte'} {/snippetArea} ``` + ```latte -{* child.latte *} +{* enthalten.latte *} {snippet item} -... + ... {/snippet} ``` + ```php -$this->redrawControl('wrapper'); +$this->redrawControl('include'); $this->redrawControl('item'); ``` -Sie können es auch mit dynamischen Snippets kombinieren. +Schnipsel in Komponenten .[#toc-snippets-in-components] +------------------------------------------------------- -Hinzufügen und Löschen .[#toc-adding-and-deleting] -================================================== - -Wenn Sie ein neues Element in die Liste einfügen und `itemsContainer` ungültig machen, liefert die AJAX-Anfrage Snippets, die das neue Element enthalten, aber der Javascript-Handler kann es nicht darstellen. Das liegt daran, dass es kein HTML-Element mit der neu erstellten ID gibt. - -In diesem Fall besteht die einfachste Möglichkeit darin, die gesamte Liste in ein weiteres Snippet zu verpacken und alles ungültig zu machen: +Sie können Snippets in [Komponenten |components] erstellen, und Nette wird sie automatisch neu zeichnen. Es gibt jedoch eine bestimmte Einschränkung: Um Snippets neu zu zeichnen, wird die Methode `render()` ohne Parameter aufgerufen. Die Übergabe von Parametern in der Vorlage funktioniert also nicht: ```latte -{snippet wholeList} -
      - {foreach $list as $id => $item} -
    • {$item} update
    • - {/foreach} -
    -{/snippet} -Add +OK +{control productGrid} + +will not work: +{control productGrid $arg, $arg} +{control productGrid:paginator} ``` + +Senden von Benutzerdaten .[#toc-sending-user-data] +-------------------------------------------------- + +Neben den Snippets können Sie beliebige weitere Daten an den Client senden. Schreiben Sie sie einfach in das `payload` Objekt: + ```php -public function handleAdd(): void +public function actionDelete(int $id): void { - $this->template->list = $this->getTheWholeList(); - $this->template->list[] = 'New one'; - $this->redrawControl('wholeList'); + //... + if ($this->isAjax()) { + $this->payload->message = 'Success'; + } } ``` -Das Gleiche gilt für das Löschen eines Eintrags. Es wäre möglich, ein leeres Snippet zu senden, aber in der Regel können Listen paginiert werden, und es wäre kompliziert, das Löschen eines Elements und das Laden eines anderen (das sich auf einer anderen Seite der paginierten Liste befand) zu implementieren. - -Parameter an die Komponente senden .[#toc-sending-parameters-to-component] -========================================================================== +Senden von Parametern .[#toc-sending-parameters] +================================================ Wenn wir Parameter über eine AJAX-Anfrage an die Komponente senden, egal ob es sich um Signalparameter oder dauerhafte Parameter handelt, müssen wir ihren globalen Namen angeben, der auch den Namen der Komponente enthält. Den vollständigen Namen des Parameters gibt die Methode `getParameterId()` zurück. ```js -$.getJSON( - {link changeCountBasket!}, - { - {$control->getParameterId('id')}: id, - {$control->getParameterId('count')}: count - } -}); +let url = new URL({link //foo!}); +url.searchParams.set({$control->getParameterId('bar')}, bar); + +fetch(url, { + headers: {'X-Requested-With': 'XMLHttpRequest'}, +}) ``` -Und behandeln Sie die Methode mit den entsprechenden Parametern in der Komponente. +Eine Handle-Methode mit den entsprechenden Parametern in der Komponente: ```php -public function handleChangeCountBasket(int $id, int $count): void +public function handleFoo(int $bar): void { - } ``` diff --git a/application/de/components.texy b/application/de/components.texy index b4540b4808..e5371761ea 100644 --- a/application/de/components.texy +++ b/application/de/components.texy @@ -380,7 +380,7 @@ Komponenten im Detail .[#toc-components-in-depth] Komponenten in einer Nette-Anwendung sind die wiederverwendbaren Teile einer Web-Anwendung, die wir in Seiten einbetten, was das Thema dieses Kapitels ist. Was genau sind die Fähigkeiten einer solchen Komponente? 1) sie ist in einer Vorlage renderbar -2) sie weiß, welcher Teil von ihr bei einer [AJAX-Anfrage |ajax#invalidation] gerendert werden soll (Snippets) +2) es weiß, [welcher Teil von sich selbst |ajax#snippets] während einer AJAX-Anfrage zu rendern ist (Snippets) 3) er kann seinen Zustand in einer URL speichern (persistente Parameter) 4) es hat die Fähigkeit, auf Benutzeraktionen zu reagieren (Signale) 5) er erstellt eine hierarchische Struktur (wobei die Wurzel der Präsentator ist) diff --git a/application/el/ajax.texy b/application/el/ajax.texy index 08df9e3fc2..de4975d290 100644 --- a/application/el/ajax.texy +++ b/application/el/ajax.texy @@ -3,10 +3,10 @@ AJAX & Snippets
    -Οι σύγχρονες διαδικτυακές εφαρμογές τρέχουν σήμερα κατά το ήμισυ σε έναν διακομιστή και κατά το ήμισυ σε ένα πρόγραμμα περιήγησης. Το AJAX είναι ένας ζωτικής σημασίας ενωτικός παράγοντας. Τι υποστήριξη προσφέρει το Nette Framework; -- αποστολή τμημάτων προτύπου (τα λεγόμενα *snippets*) -- μεταβίβαση μεταβλητών μεταξύ PHP και JavaScript -- αποσφαλμάτωση εφαρμογών AJAX +Στην εποχή των σύγχρονων διαδικτυακών εφαρμογών, όπου η λειτουργικότητα συχνά εκτείνεται μεταξύ του διακομιστή και του προγράμματος περιήγησης, το AJAX είναι ένα απαραίτητο συνδετικό στοιχείο. Ποιες επιλογές προσφέρει το Nette Framework σε αυτόν τον τομέα; +- αποστολή τμημάτων του προτύπου, των λεγόμενων αποσπασμάτων +- διαβίβαση μεταβλητών μεταξύ PHP και JavaScript +- εργαλεία για την αποσφαλμάτωση αιτημάτων AJAX
    @@ -14,29 +14,32 @@ AJAX & Snippets Αίτηση AJAX .[#toc-ajax-request] ================================ -Ένα αίτημα AJAX δεν διαφέρει από ένα κλασικό αίτημα - ο παρουσιαστής καλείται με μια συγκεκριμένη προβολή και παραμέτρους. Εξαρτάται επίσης από τον παρουσιαστή πώς θα απαντήσει σε αυτό: μπορεί να χρησιμοποιήσει τη δική του ρουτίνα, η οποία επιστρέφει ένα τμήμα κώδικα HTML (απόσπασμα HTML), ένα έγγραφο XML, ένα αντικείμενο JSON ή κώδικα JavaScript. +Ένα αίτημα AJAX δεν διαφέρει ουσιαστικά από ένα κλασικό αίτημα HTTP. Ένας παρουσιαστής καλείται με συγκεκριμένες παραμέτρους. Από τον παρουσιαστή εξαρτάται πώς θα απαντήσει στο αίτημα - μπορεί να επιστρέψει δεδομένα σε μορφή JSON, να στείλει ένα τμήμα κώδικα HTML, ένα έγγραφο XML κ.λπ. -Από την πλευρά του διακομιστή, ένα αίτημα AJAX μπορεί να ανιχνευθεί χρησιμοποιώντας τη μέθοδο service που [ενθυλακώνει το αίτημα HTTP |http:request] `$httpRequest->isAjax()` (ανιχνεύει με βάση την επικεφαλίδα HTTP `X-Requested-With`). Στο εσωτερικό του παρουσιαστή, είναι διαθέσιμη μια συντόμευση με τη μορφή της μεθόδου `$this->isAjax()`. +Από την πλευρά του προγράμματος περιήγησης, ξεκινάμε ένα αίτημα AJAX χρησιμοποιώντας τη συνάρτηση `fetch()`: -Υπάρχει ένα προεπεξεργασμένο αντικείμενο που ονομάζεται `payload` και είναι αφιερωμένο στην αποστολή δεδομένων στο πρόγραμμα περιήγησης σε JSON. - -```php -public function actionDelete(int $id): void -{ - if ($this->isAjax()) { - $this->payload->message = 'Success'; - } - // ... -} +```js +fetch(url, { + headers: {'X-Requested-With': 'XMLHttpRequest'}, +}) +.then(response => response.json()) +.then(payload => { + // επεξεργασία της απάντησης +}); ``` -Για πλήρη έλεγχο της εξόδου JSON χρησιμοποιήστε τη μέθοδο `sendJson` στον παρουσιαστή σας. Τερματίζει αμέσως τον presenter και θα κάνετε χωρίς πρότυπο: +Στην πλευρά του διακομιστή, ένα αίτημα AJAX αναγνωρίζεται από τη μέθοδο `$httpRequest->isAjax()` της υπηρεσίας που [ενθυλακώνει το αίτημα HTTP |http:request]. Χρησιμοποιεί την επικεφαλίδα HTTP `X-Requested-With`, οπότε είναι απαραίτητη η αποστολή της. Μέσα στον παρουσιαστή, μπορείτε να χρησιμοποιήσετε τη μέθοδο `$this->isAjax()`. + +Εάν θέλετε να στείλετε δεδομένα σε μορφή JSON, χρησιμοποιήστε τη μέθοδο [`sendJson()` |presenters#Sending a response] μέθοδο. Η μέθοδος τερματίζει επίσης τη δραστηριότητα του παρουσιαστή. ```php -$this->sendJson(['key' => 'value', /* ... */]); +public function actionExport(): void +{ + $this->sendJson($this->model->getData); +} ``` -Εάν θέλουμε να στείλουμε HTML, μπορούμε είτε να ορίσουμε ένα ειδικό πρότυπο για αιτήσεις AJAX: +Αν σκοπεύετε να απαντήσετε με ένα ειδικό πρότυπο σχεδιασμένο για AJAX, μπορείτε να το κάνετε ως εξής: ```php public function handleClick($param): void @@ -44,27 +47,37 @@ public function handleClick($param): void if ($this->isAjax()) { $this->template->setFile('path/to/ajax.latte'); } - // ... + //... } ``` +Αποσπάσματα .[#toc-snippets] +============================ + +Το πιο ισχυρό εργαλείο που προσφέρει η Nette για τη σύνδεση του διακομιστή με τον πελάτη είναι τα snippets. Με αυτά μπορείτε να μετατρέψετε μια συνηθισμένη εφαρμογή σε AJAX με ελάχιστη προσπάθεια και λίγες γραμμές κώδικα. Το παράδειγμα Fifteen δείχνει πώς λειτουργούν όλα αυτά, και ο κώδικάς του μπορεί να βρεθεί στο [GitHub |https://github.com/nette-examples/fifteen]. + +Τα αποσπάσματα, ή αποκόμματα, σας επιτρέπουν να ενημερώνετε μόνο τμήματα της σελίδας, αντί να επαναφορτώνετε ολόκληρη τη σελίδα. Αυτό είναι πιο γρήγορο και αποτελεσματικό, και παρέχει επίσης μια πιο άνετη εμπειρία χρήσης. Τα αποσπάσματα μπορεί να σας θυμίζουν το Hotwire για το Ruby on Rails ή το Symfony UX Turbo. Είναι ενδιαφέρον ότι η Nette εισήγαγε τα snippets 14 χρόνια νωρίτερα. + +Πώς λειτουργούν τα snippets; Όταν φορτώνεται για πρώτη φορά η σελίδα (μια αίτηση χωρίς-AJAX), φορτώνεται ολόκληρη η σελίδα, συμπεριλαμβανομένων όλων των snippets. Όταν ο χρήστης αλληλεπιδρά με τη σελίδα (π.χ. κάνει κλικ σε ένα κουμπί, υποβάλλει μια φόρμα κ.λπ.), αντί να φορτωθεί ολόκληρη η σελίδα, γίνεται ένα αίτημα AJAX. Ο κώδικας στον παρουσιαστή εκτελεί την ενέργεια και αποφασίζει ποια αποσπάσματα χρειάζονται ενημέρωση. Η Nette αποδίδει αυτά τα αποσπάσματα και τα αποστέλλει με τη μορφή ενός πίνακα JSON. Ο κώδικας χειρισμού στο πρόγραμμα περιήγησης εισάγει στη συνέχεια τα ληφθέντα αποσπάσματα πίσω στη σελίδα. Επομένως, μεταφέρεται μόνο ο κώδικας των αλλαγμένων αποσπασμάτων, εξοικονομώντας εύρος ζώνης και επιταχύνοντας τη φόρτωση σε σύγκριση με τη μεταφορά ολόκληρου του περιεχομένου της σελίδας. + + Naja .[#toc-naja] -================= +----------------- -Η [βιβλιοθήκη Naja |https://naja.js.org] χρησιμοποιείται για το χειρισμό αιτημάτων AJAX στην πλευρά του προγράμματος περιήγησης. [Εγκαταστήστε |https://naja.js.org/#/guide/01-install-setup-naja] την ως πακέτο node.js (για χρήση με Webpack, Rollup, Vite, Parcel και άλλα): +Για το χειρισμό των αποσπασμάτων στην πλευρά του προγράμματος περιήγησης, χρησιμοποιείται η [βιβλιοθήκη Naja |https://naja.js.org]. [Εγκαταστήστε την |https://naja.js.org/#/guide/01-install-setup-naja] ως πακέτο node.js (για χρήση με εφαρμογές όπως Webpack, Rollup, Vite, Parcel και άλλες): ```shell npm install naja ``` -...ή να την εισαγάγετε απευθείας στο πρότυπο της σελίδας: +... ή να την εισαγάγετε απευθείας στο πρότυπο της σελίδας: ```html ``` -Για να δημιουργήσετε μια αίτηση AJAX από έναν κανονικό σύνδεσμο (σήμα) ή μια υποβολή φόρμας, απλά επισημάνετε τον σχετικό σύνδεσμο, τη φόρμα ή το κουμπί με την κλάση `ajax`: +Για να μετατρέψετε έναν συνηθισμένο σύνδεσμο (σήμα) ή την υποβολή φόρμας σε αίτηση AJAX, απλά σημειώστε τον αντίστοιχο σύνδεσμο, φόρμα ή κουμπί με την κλάση `ajax`: ```html Go @@ -74,64 +87,39 @@ npm install naja or +
    ``` -Snippets .[#toc-snippets] -========================= - -Υπάρχει ένα πολύ πιο ισχυρό εργαλείο ενσωματωμένης υποστήριξης AJAX - τα αποσπάσματα. Η χρήση τους καθιστά δυνατή τη μετατροπή μιας κανονικής εφαρμογής σε εφαρμογή AJAX χρησιμοποιώντας μόνο μερικές γραμμές κώδικα. Το πώς λειτουργούν όλα αυτά παρουσιάζεται στο παράδειγμα Fifteen του οποίου ο κώδικας είναι επίσης προσβάσιμος στο build ή στο [GitHub |https://github.com/nette-examples/fifteen]. - -Ο τρόπος που λειτουργούν τα snippets είναι ότι ολόκληρη η σελίδα μεταφέρεται κατά το αρχικό (δηλαδή μη-AJAX) αίτημα και στη συνέχεια με κάθε AJAX [υποερώτημα |components#signal] (αίτημα της ίδιας προβολής του ίδιου παρουσιαστή) μεταφέρεται μόνο ο κώδικας των αλλαγμένων τμημάτων στο αποθετήριο `payload` που αναφέρθηκε προηγουμένως. - -Τα Snippets μπορεί να σας θυμίζουν το Hotwire για το Ruby on Rails ή το Symfony UX Turbo, αλλά η Nette τα επινόησε δεκατέσσερα χρόνια νωρίτερα. +Επανασχεδίαση αποσπασμάτων .[#toc-redrawing-snippets] +----------------------------------------------------- - -Ακύρωση των Snippets .[#toc-invalidation-of-snippets] -===================================================== - -Κάθε απόγονος της κλάσης [Control |components] (που είναι και ένας Παρουσιαστής) είναι σε θέση να θυμάται αν υπήρξαν αλλαγές κατά τη διάρκεια μιας αίτησης που απαιτούν την εκ νέου εμφάνιση. Υπάρχει ένα ζευγάρι μεθόδων για το χειρισμό αυτό: `redrawControl()` και `isControlInvalid()`. Ένα παράδειγμα: +Κάθε αντικείμενο της κλάσης [Control |components] (συμπεριλαμβανομένου και του ίδιου του Presenter) διατηρεί αρχείο για το αν έχουν συμβεί αλλαγές που καθιστούν αναγκαία την επανασχεδίασή του. Για το σκοπό αυτό χρησιμοποιείται η μέθοδος `redrawControl()`. ```php public function handleLogin(string $user): void { - // Το αντικείμενο πρέπει να αναδημιουργηθεί εκ νέου μετά τη σύνδεση του χρήστη. + // μετά τη σύνδεση, είναι απαραίτητο να σχεδιάσετε εκ νέου το σχετικό τμήμα $this->redrawControl(); - // ... + //... } ``` -Η Nette ωστόσο προσφέρει μια ακόμη πιο λεπτή ανάλυση από ολόκληρα στοιχεία. Οι αναφερόμενες μέθοδοι δέχονται το όνομα ενός λεγόμενου "αποσπάσματος" ως προαιρετική παράμετρο. Ένα "απόσπασμα" είναι ουσιαστικά ένα στοιχείο στο πρότυπό σας που επισημαίνεται για το σκοπό αυτό με μια ετικέτα Latte, περισσότερα γι' αυτό αργότερα. Έτσι είναι δυνατόν να ζητήσετε από ένα στοιχείο να ξανασχεδιάσει μόνο *μέρη* του προτύπου του. Εάν ακυρωθεί ολόκληρο το συστατικό, τότε όλα τα αποσπάσματά του αναδημιουργούνται εκ νέου. Ένα συστατικό είναι "άκυρο" επίσης εάν οποιοδήποτε από τα υποσυστήματά του είναι άκυρο. - -```php -$this->isControlInvalid(); // -> false -$this->redrawControl('header'); // ακυρώνει το απόσπασμα με το όνομα 'header' -$this->isControlInvalid('header'); // -> true -$this->isControlInvalid('footer'); // -> false -$this->isControlInvalid(); // -> true, τουλάχιστον ένα απόσπασμα είναι άκυρο +Η Nette επιτρέπει επίσης έναν πιο λεπτομερή έλεγχο του τι χρειάζεται επανασχεδίαση. Η προαναφερθείσα μέθοδος μπορεί να λάβει το όνομα του αποσπάσματος ως όρισμα. Έτσι, είναι δυνατή η ακύρωση (που σημαίνει: εξαναγκασμός σε επανασχεδίαση) σε επίπεδο τμήματος προτύπου. Εάν ακυρωθεί ολόκληρο το συστατικό, κάθε απόσπασμα αυτού επανασχεδιάζεται επίσης: -$this->redrawControl(); // ακυρώνει ολόκληρο το συστατικό, κάθε απόσπασμα -$this->isControlInvalid('footer'); // -> true +```php +// ακυρώνει το απόσπασμα 'header' +$this->redrawControl('header'); ``` -Ένα συστατικό που λαμβάνει σήμα επισημαίνεται αυτόματα για επανασχεδίαση. - -Χάρη στην επανασχεδίαση αποσπασμάτων γνωρίζουμε επακριβώς ποια τμήματα ποιων στοιχείων πρέπει να επανασχεδιαστούν. - - -Ετικέτα `{snippet} … {/snippet}` .{toc: Tag snippet} -==================================================== -Η απόδοση της σελίδας εξελίσσεται πολύ παρόμοια με μια κανονική αίτηση: φορτώνονται τα ίδια πρότυπα κ.λπ. Το ζωτικής σημασίας μέρος είναι, ωστόσο, να παραλείπονται τα μέρη που δεν πρέπει να φτάσουν στην έξοδο- τα υπόλοιπα μέρη πρέπει να συσχετίζονται με ένα αναγνωριστικό και να αποστέλλονται στο χρήστη σε κατανοητή μορφή για έναν χειριστή JavaScript. +Αποσπάσματα σε Latte .[#toc-snippets-in-latte] +---------------------------------------------- - -Σύνταξη .[#toc-syntax] ----------------------- - -Εάν υπάρχει ένα στοιχείο ελέγχου ή ένα απόσπασμα στο πρότυπο, πρέπει να το τυλίξουμε χρησιμοποιώντας την ετικέτα `{snippet} ... {/snippet}` pair - θα διασφαλίσει ότι το αποδιδόμενο απόσπασμα θα "αποκοπεί" και θα σταλεί στο πρόγραμμα περιήγησης. Θα το περικλείσει επίσης σε ένα βοηθητικό `
    ` tag (είναι δυνατόν να χρησιμοποιηθεί ένα διαφορετικό). Στο ακόλουθο παράδειγμα ορίζεται ένα απόσπασμα με το όνομα `header`. Μπορεί κάλλιστα να αντιπροσωπεύει το πρότυπο ενός στοιχείου: +Η χρήση αποσπασμάτων στο Latte είναι εξαιρετικά εύκολη. Για να ορίσετε ένα μέρος του προτύπου ως snippet, απλά τυλίξτε το σε ετικέτες `{snippet}` και `{/snippet}`: ```latte {snippet header} @@ -139,7 +127,9 @@ $this->isControlInvalid('footer'); // -> true {/snippet} ``` -Ένα απόσπασμα άλλου τύπου από το `
    ` ή ένα απόσπασμα με πρόσθετα χαρακτηριστικά HTML επιτυγχάνεται με τη χρήση της παραλλαγής χαρακτηριστικών: +Το απόσπασμα δημιουργεί ένα στοιχείο `
    ` στη σελίδα HTML με ένα ειδικά δημιουργημένο `id`. Κατά την επανασχεδίαση ενός αποσπάσματος, το περιεχόμενο αυτού του στοιχείου ενημερώνεται. Επομένως, κατά την αρχική απόδοση της σελίδας, όλα τα snippets πρέπει επίσης να αποδοθούν, ακόμη και αν μπορεί αρχικά να είναι κενά. + +Μπορείτε επίσης να δημιουργήσετε ένα απόσπασμα με ένα στοιχείο διαφορετικό από το `
    ` χρησιμοποιώντας ένα χαρακτηριστικό n:attribute: ```latte
    @@ -148,138 +138,106 @@ $this->isControlInvalid('footer'); // -> true ``` -Δυναμικά αποσπάσματα .[#toc-dynamic-snippets] -============================================= +Περιοχές αποσπασμάτων .[#toc-snippet-areas] +------------------------------------------- -Στο Nette μπορείτε επίσης να ορίσετε αποσπάσματα με δυναμικό όνομα βάσει μιας παραμέτρου εκτέλεσης. Αυτό είναι πιο κατάλληλο για διάφορες λίστες όπου πρέπει να αλλάξουμε μόνο μια γραμμή αλλά δεν θέλουμε να μεταφέρουμε ολόκληρη τη λίστα μαζί με αυτήν. Ένα τέτοιο παράδειγμα θα ήταν το εξής: +Τα ονόματα αποσπασμάτων μπορούν επίσης να είναι εκφράσεις: ```latte -
      - {foreach $list as $id => $item} -
    • {$item} update
    • - {/foreach} -
    +{foreach $items as $id => $item} +
  • {$item}
  • +{/foreach} ``` -Υπάρχει ένα στατικό απόσπασμα που ονομάζεται `itemsContainer`, το οποίο περιέχει διάφορα δυναμικά αποσπάσματα: `item-0`, `item-1` κ.ο.κ. + `item-0`, `item-1`, κ.λπ. Αν ακυρώναμε άμεσα ένα δυναμικό απόσπασμα (π.χ. `item-1`), τίποτα δεν θα ξανασχεδιαζόταν. Ο λόγος είναι ότι τα αποσπάσματα λειτουργούν ως αληθινά αποσπάσματα και μόνο τα ίδια αποδίδονται άμεσα. Ωστόσο, στο πρότυπο, δεν υπάρχει τεχνικά ένα απόσπασμα με το όνομα `item-1`. Εμφανίζεται μόνο όταν εκτελείται ο περιβάλλων κώδικας του αποσπάσματος, στην προκειμένη περίπτωση, ο βρόχος foreach. Ως εκ τούτου, θα επισημάνουμε το τμήμα του προτύπου που πρέπει να εκτελεστεί με την ετικέτα `{snippetArea}`: -Δεν μπορείτε να ξανασχεδιάσετε άμεσα ένα δυναμικό απόσπασμα (η επανασχεδίαση του `item-1` δεν έχει κανένα αποτέλεσμα), πρέπει να ξανασχεδιάσετε το γονικό του απόσπασμα (σε αυτό το παράδειγμα `itemsContainer`). Αυτό προκαλεί την εκτέλεση του κώδικα του γονικού αποσπάσματος, αλλά στη συνέχεια αποστέλλονται στο πρόγραμμα περιήγησης μόνο τα επιμέρους αποσπάσματά του. Αν θέλετε να στείλετε μόνο ένα από τα υπο-στοιχεία, πρέπει να τροποποιήσετε την είσοδο για το γονικό απόσπασμα ώστε να μην παράγει τα άλλα υπο-στοιχεία. +```latte +
      + {foreach $items as $id => $item} +
    • {$item}
    • + {/foreach} +
    +``` -Στο παραπάνω παράδειγμα πρέπει να βεβαιωθείτε ότι για μια αίτηση AJAX θα προστεθεί μόνο ένα στοιχείο στον πίνακα `$list`, επομένως ο βρόχος `foreach` θα εκτυπώσει μόνο ένα δυναμικό απόσπασμα. +Και θα ξανασχεδιάσουμε τόσο το μεμονωμένο απόσπασμα όσο και ολόκληρη την υπερκείμενη περιοχή: ```php -class HomePresenter extends Nette\Application\UI\Presenter -{ - /** - * This method returns data for the list. - * Usually this would just request the data from a model. - * For the purpose of this example, the data is hard-coded. - */ - private function getTheWholeList(): array - { - return [ - 'First', - 'Second', - 'Third', - ]; - } - - public function renderDefault(): void - { - if (!isset($this->template->list)) { - $this->template->list = $this->getTheWholeList(); - } - } - - public function handleUpdate(int $id): void - { - $this->template->list = $this->isAjax() - ? [] - : $this->getTheWholeList(); - $this->template->list[$id] = 'Updated item'; - $this->redrawControl('itemsContainer'); - } -} +$this->redrawControl('itemsContainer'); +$this->redrawControl('item-1'); ``` +Είναι επίσης σημαντικό να διασφαλίσουμε ότι ο πίνακας `$items` περιέχει μόνο τα στοιχεία που πρέπει να επανασχεδιαστούν. -Αποσπάσματα σε συμπεριλαμβανόμενο πρότυπο .[#toc-snippets-in-an-included-template] -================================================================================== - -Μπορεί να συμβεί το απόσπασμα να βρίσκεται σε ένα πρότυπο το οποίο συμπεριλαμβάνεται από ένα διαφορετικό πρότυπο. Σε αυτή την περίπτωση πρέπει να τυλίξουμε τον κώδικα συμπερίληψης στο δεύτερο πρότυπο με την ετικέτα `snippetArea`, και στη συνέχεια να ξανασχεδιάσουμε τόσο το snippetArea όσο και το πραγματικό απόσπασμα. - -Η ετικέτα `snippetArea` διασφαλίζει ότι ο κώδικας στο εσωτερικό της εκτελείται, αλλά μόνο το πραγματικό απόσπασμα στο συμπεριλαμβανόμενο πρότυπο αποστέλλεται στο πρόγραμμα περιήγησης. +Κατά την εισαγωγή ενός άλλου προτύπου στο κύριο με τη χρήση της ετικέτας `{include}`, το οποίο έχει αποσπάσματα, είναι απαραίτητο να τυλίξετε και πάλι το συμπεριλαμβανόμενο πρότυπο σε ένα `snippetArea` και να ακυρώσετε τόσο το απόσπασμα όσο και την περιοχή μαζί: ```latte -{* parent.latte *} -{snippetArea wrapper} - {include 'child.latte'} +{snippetArea include} + {include 'included.latte'} {/snippetArea} ``` + ```latte -{* child.latte *} +{* included.latte *} {snippet item} -... + ... {/snippet} ``` + ```php -$this->redrawControl('wrapper'); +$this->redrawControl('include'); $this->redrawControl('item'); ``` -Μπορείτε επίσης να το συνδυάσετε με δυναμικά αποσπάσματα. - -Προσθήκη και διαγραφή .[#toc-adding-and-deleting] -================================================= +Αποσπάσματα σε στοιχεία .[#toc-snippets-in-components] +------------------------------------------------------ -Εάν προσθέσετε ένα νέο στοιχείο στη λίστα και ακυρώσετε το `itemsContainer`, η αίτηση AJAX επιστρέφει αποσπάσματα που περιλαμβάνουν το νέο στοιχείο, αλλά ο χειριστής javascript δεν θα είναι σε θέση να το αποδώσει. Αυτό συμβαίνει επειδή δεν υπάρχει κανένα στοιχείο HTML με το νεοδημιουργηθέν ID. - -Σε αυτή την περίπτωση, ο απλούστερος τρόπος είναι να τυλίξετε ολόκληρη τη λίστα σε ένα ακόμη απόσπασμα και να τα ακυρώσετε όλα: +Μπορείτε να δημιουργήσετε αποσπάσματα μέσα σε [στοιχεία |components] και η Nette θα τα ανασχεδιάσει αυτόματα. Ωστόσο, υπάρχει ένας συγκεκριμένος περιορισμός: για να ξανασχεδιάσει αποσπάσματα, καλεί τη μέθοδο `render()` χωρίς καμία παράμετρο. Έτσι, η μετάδοση παραμέτρων στο πρότυπο δεν θα λειτουργήσει: ```latte -{snippet wholeList} -
      - {foreach $list as $id => $item} -
    • {$item} update
    • - {/foreach} -
    -{/snippet} -Add +OK +{control productGrid} + +will not work: +{control productGrid $arg, $arg} +{control productGrid:paginator} ``` + +Αποστολή δεδομένων χρήστη .[#toc-sending-user-data] +--------------------------------------------------- + +Μαζί με τα αποσπάσματα, μπορείτε να στείλετε οποιαδήποτε πρόσθετα δεδομένα στον πελάτη. Απλά γράψτε τα στο αντικείμενο `payload`: + ```php -public function handleAdd(): void +public function actionDelete(int $id): void { - $this->template->list = $this->getTheWholeList(); - $this->template->list[] = 'New one'; - $this->redrawControl('wholeList'); + //... + if ($this->isAjax()) { + $this->payload->message = 'Success'; + } } ``` -Το ίδιο ισχύει και για τη διαγραφή ενός στοιχείου. Θα ήταν δυνατό να στείλετε κενό snippet, αλλά συνήθως οι λίστες μπορούν να είναι σελιδοποιημένες και θα ήταν περίπλοκο να υλοποιήσετε τη διαγραφή ενός στοιχείου και τη φόρτωση ενός άλλου (το οποίο βρισκόταν σε διαφορετική σελίδα της σελιδοποιημένης λίστας). - -Αποστολή παραμέτρων στο συστατικό .[#toc-sending-parameters-to-component] -========================================================================= +Παράμετροι αποστολής .[#toc-sending-parameters] +=============================================== Όταν στέλνουμε παραμέτρους στο στοιχείο μέσω αίτησης AJAX, είτε πρόκειται για παραμέτρους σήματος είτε για μόνιμες παραμέτρους, πρέπει να παρέχουμε το συνολικό τους όνομα, το οποίο περιέχει επίσης το όνομα του στοιχείου. Το πλήρες όνομα της παραμέτρου επιστρέφει η μέθοδος `getParameterId()`. ```js -$.getJSON( - {link changeCountBasket!}, - { - {$control->getParameterId('id')}: id, - {$control->getParameterId('count')}: count - } -}); +let url = new URL({link //foo!}); +url.searchParams.set({$control->getParameterId('bar')}, bar); + +fetch(url, { + headers: {'X-Requested-With': 'XMLHttpRequest'}, +}) ``` -Και χειρίζεται τη μέθοδο με s αντίστοιχες παραμέτρους στο συστατικό. +Μια μέθοδος χειρισμού με τις αντίστοιχες παραμέτρους στο συστατικό: ```php -public function handleChangeCountBasket(int $id, int $count): void +public function handleFoo(int $bar): void { - } ``` diff --git a/application/el/components.texy b/application/el/components.texy index ae5fc64c2f..8df1c185b6 100644 --- a/application/el/components.texy +++ b/application/el/components.texy @@ -380,7 +380,7 @@ interface PollControlFactory Τα συστατικά σε μια εφαρμογή Nette είναι τα επαναχρησιμοποιήσιμα μέρη μιας διαδικτυακής εφαρμογής που ενσωματώνουμε σε σελίδες, τα οποία αποτελούν το αντικείμενο αυτού του κεφαλαίου. Ποιες ακριβώς είναι οι δυνατότητες ενός τέτοιου συστατικού; 1) είναι δυνατό να αποδοθεί σε ένα πρότυπο -2) γνωρίζει ποιο μέρος του εαυτού του να αποδώσει κατά τη διάρκεια μιας [αίτησης AJAX |ajax#invalidation] (αποσπάσματα) +2) γνωρίζει [ποιο μέρος του εαυτού του |ajax#snippets] να αποδώσει κατά τη διάρκεια μιας αίτησης AJAX (αποσπάσματα) 3) έχει τη δυνατότητα να αποθηκεύει την κατάστασή του σε μια διεύθυνση URL (μόνιμες παράμετροι) 4) έχει τη δυνατότητα να ανταποκρίνεται σε ενέργειες του χρήστη (σήματα) 5) δημιουργεί μια ιεραρχική δομή (όπου η ρίζα είναι ο παρουσιαστής) diff --git a/application/en/ajax.texy b/application/en/ajax.texy index 6077456b78..a62ed95cfc 100644 --- a/application/en/ajax.texy +++ b/application/en/ajax.texy @@ -3,10 +3,10 @@ AJAX & Snippets
    -Modern web applications nowadays run half on a server and half in a browser. AJAX is a vital uniting factor. What support does the Nette Framework offer? -- sending template fragments (so-called *snippets*) +In the era of modern web applications, where functionality often spans between the server and the browser, AJAX is an essential connecting element. What options does the Nette Framework offer in this area? +- sending parts of the template, so-called snippets - passing variables between PHP and JavaScript -- AJAX applications debugging +- tools for debugging AJAX requests
    @@ -14,29 +14,32 @@ Modern web applications nowadays run half on a server and half in a browser. AJA AJAX Request ============ -An AJAX request does not differ from a classic request - the presenter is called with a specific view and parameters. It is also up to the presenter how to respond to it: it can use its own routine, which returns an HTML code fragment (HTML snippet), an XML document, a JSON object, or JavaScript code. +An AJAX request fundamentally does not differ from a classic HTTP request. A presenter is called with specific parameters. It's up to the presenter how to respond to the request - it can return data in JSON format, send a part of HTML code, an XML document, etc. -On the server side, an AJAX request can be detected using the service method [encapsulating the HTTP request |http:request] `$httpRequest->isAjax()` (detects based on the HTTP header `X-Requested-With`). Inside the presenter, a shortcut is available in the form of the method `$this->isAjax()`. +On the browser side, we initiate an AJAX request using the `fetch()` function: -There is a pre-processed object called `payload` dedicated to sending data to the browser in JSON. - -```php -public function actionDelete(int $id): void -{ - if ($this->isAjax()) { - $this->payload->message = 'Success'; - } - // ... -} +```js +fetch(url, { + headers: {'X-Requested-With': 'XMLHttpRequest'}, +}) +.then(response => response.json()) +.then(payload => { + // processing the response +}); ``` -For a full control over your JSON output use the `sendJson` method in your presenter. It terminates presenter immediately and you'll do without a template: +On the server side, an AJAX request is recognized by the `$httpRequest->isAjax()` method of the service [encapsulating the HTTP request |http:request]. It uses the HTTP header `X-Requested-With`, so it's essential to send it. Within the presenter, you can use the `$this->isAjax()` method. + +If you want to send data in JSON format, use the [`sendJson()` |presenters#Sending a response] method. The method also terminates the presenter's activity. ```php -$this->sendJson(['key' => 'value', /* ... */]); +public function actionExport(): void +{ + $this->sendJson($this->model->getData); +} ``` -If we want to send HTML, we can either set a special template for AJAX requests: +If you plan to respond with a special template designed for AJAX, you can do it as follows: ```php public function handleClick($param): void @@ -49,22 +52,32 @@ public function handleClick($param): void ``` +Snippets +======== + +The most powerful tool offered by Nette for connecting the server with the client are snippets. With them, you can turn an ordinary application into an AJAX one with minimal effort and a few lines of code. The Fifteen example demonstrates how it all works, and its code can be found on [GitHub |https://github.com/nette-examples/fifteen]. + +Snippets, or clippings, allow you to update only parts of the page, instead of reloading the entire page. This is faster and more efficient, and also provides a more comfortable user experience. Snippets might remind you of Hotwire for Ruby on Rails or Symfony UX Turbo. Interestingly, Nette introduced snippets 14 years earlier. + +How do snippets work? When the page is first loaded (a non-AJAX request), the entire page, including all snippets, is loaded. When the user interacts with the page (e.g., clicks a button, submits a form, etc.), instead of loading the entire page, an AJAX request is made. The code in the presenter performs the action and decides which snippets need updating. Nette renders these snippets and sends them in the form of a JSON array. The handling code in the browser then inserts the received snippets back into the page. Therefore, only the code of the changed snippets is transferred, saving bandwidth and speeding up loading compared to transferring the entire page content. + + Naja -==== +---- -The [Naja library|https://naja.js.org] is used to handle AJAX requests on the browser side. [Install |https://naja.js.org/#/guide/01-install-setup-naja] it as a node.js package (to use with Webpack, Rollup, Vite, Parcel and more): +To handle snippets on the browser side, the [Naja library |https://naja.js.org] is used. [Install it |https://naja.js.org/#/guide/01-install-setup-naja] as a node.js package (for use with applications such as Webpack, Rollup, Vite, Parcel, and others): ```shell npm install naja ``` -…or insert it directly into the page template: +... or insert it directly into the page template: ```html ``` -To create an AJAX request from a regular link (signal) or form submittion, simply mark the relevant link, form, or button with the class `ajax`: +To make an ordinary link (signal) or form submission an AJAX request, simply mark the respective link, form, or button with the `ajax` class: ```html Go @@ -74,64 +87,39 @@ To create an AJAX request from a regular link (signal) or form submittion, simpl or +
    ``` -Snippets -======== - -There is a far more powerful tool of built-in AJAX support – snippets. Using them makes it possible to turn a regular application into an AJAX one using only a few lines of code. How it all works is demonstrated in the Fifteen example whose code is also accessible in the build or on [GitHub |https://github.com/nette-examples/fifteen]. - -The way snippets work is that the whole page is transferred during the initial (i.e. non-AJAX) request and then with every AJAX [subrequest |components#signal] (request of the same view of the same presenter) only the code of the changed parts is transferred in the `payload` repository mentioned earlier. - -Snippets may remind you of Hotwire for Ruby on Rails or Symfony UX Turbo, but Nette came up with them fourteen years earlier. - +Redrawing Snippets +------------------ -Invalidation of Snippets -======================== - -Each descendant of class [Control |components] (which a Presenter is too) is able to remember whether there were any changes during a request that require it to re-render. There are a pair of methods to handle this: `redrawControl()` and `isControlInvalid()`. An example: +Every object of the [Control |components] class (including the Presenter itself) keeps a record of whether changes have occurred that necessitate its redrawing. The `redrawControl()` method is employed for this purpose. ```php public function handleLogin(string $user): void { - // The object has to re-render after the user has logged in + // after logging in, it is necessary to redraw the relevant part $this->redrawControl(); // ... } ``` -Nette however offers an even finer resolution than whole components. The listed methods accept the name of a so-called "snippet" as an optional parameter. A "snippet" is basically an element in your template marked for that purpose by a Latte tag, more on that later. Thus it is possible to ask a component to redraw only *parts* of its template. If the entire component is invalidated then all of its snippets are re-rendered. A component is “invalid” also if any of its subcomponents is invalid. - -```php -$this->isControlInvalid(); // -> false -$this->redrawControl('header'); // invalidates the snippet named 'header' -$this->isControlInvalid('header'); // -> true -$this->isControlInvalid('footer'); // -> false -$this->isControlInvalid(); // -> true, at least one snippet is invalid +Nette also allows for finer control of what needs redrawing. The aforementioned method can take the snippet name as an argument. Thus, it's possible to invalidate (meaning: force a redraw) at the template part level. If the entire component is invalidated, every snippet of it is also redrawn: -$this->redrawControl(); // invalidates the whole component, every snippet -$this->isControlInvalid('footer'); // -> true +```php +// invalidates the 'header' snippet +$this->redrawControl('header'); ``` -A component which receives a signal is automatically marked for redrawing. - -Thanks to snippet redrawing we know exactly which parts of which elements should be re-rendered. - - -Tag `{snippet} … {/snippet}` .{toc: Tag snippet} -================================================ - -Rendering of the page proceeds very similarly to a regular request: the same templates are loaded, etc. The vital part is, however, to leave out the parts that are not supposed to reach the output; the other parts shall be associated with an identifier and sent to the user in a comprehensible format for a JavaScript handler. - -Syntax ------- +Snippets in Latte +----------------- -If there is a control or a snippet in the template, we have to wrap it using the `{snippet} ... {/snippet}` pair tag - it will make sure that the rendered snippet will be "cut out" and sent to the browser. It will also enclose it in a helper `
    ` tag (it is possible to use a different one). In the following example a snippet named `header` is defined. It may as well represent the template of a component: +Using snippets in Latte is extremely easy. To define a part of the template as a snippet, simply wrap it in `{snippet}` and `{/snippet}` tags: ```latte {snippet header} @@ -139,7 +127,9 @@ If there is a control or a snippet in the template, we have to wrap it using the {/snippet} ``` -A snippet of a type other than `
    ` or a snippet with additional HTML attributes is achieved by using the attribute variant: +The snippet creates an element `
    ` in the HTML page with a specially generated `id`. When redrawing a snippet, the content of this element is updated. Therefore, when the page is initially rendered, all snippets must also be rendered, even if they may initially be empty. + +You can also create a snippet with an element other than `
    ` using an n:attribute: ```latte
    @@ -148,138 +138,106 @@ A snippet of a type other than `
    ` or a snippet with additional HTML attribu ``` -Dynamic Snippets -================ +Snippet Areas +------------- -In Nette you can also define snippets with a dynamic name based on a runtime parameter. This is most suitable for various lists where we need to change just one row but we don't want transfer the whole list along with it. An example of this would be: +Snippet names can also be expressions: ```latte -
      - {foreach $list as $id => $item} -
    • {$item} update
    • - {/foreach} -
    +{foreach $items as $id => $item} +
  • {$item}
  • +{/foreach} ``` -There is one static snippet called `itemsContainer`, containing several dynamic snippets: `item-0`, `item-1` and so on. +This way, we'll get several snippets like `item-0`, `item-1`, etc. If we were to directly invalidate a dynamic snippet (e.g., `item-1`), nothing would be redrawn. The reason being, snippets function as true excerpts and only they themselves are rendered directly. However, in the template, there isn't technically a snippet named `item-1`. It only emerges when executing the surrounding code of the snippet, in this case, the foreach loop. Hence, we'll mark the part of the template that needs to be executed with the `{snippetArea}` tag: -You can't redraw a dynamic snippet directly (redrawing of `item-1` has no effect), you have to redraw its parent snippet (in this example `itemsContainer`). This causes the code of the parent snippet to be executed, but then just its sub-snippets are sent to the browser. If you want to send over just one of the sub-snippets, you have to modify input for the parent snippet to not generate the other sub-snippets. +```latte +
      + {foreach $items as $id => $item} +
    • {$item}
    • + {/foreach} +
    +``` -In the example above you have to make sure that for an AJAX request only one item will be added to the `$list` array, therefore the `foreach` loop will print just one dynamic snippet. +And we'll redraw both the individual snippet and the entire overarching area: ```php -class HomePresenter extends Nette\Application\UI\Presenter -{ - /** - * This method returns data for the list. - * Usually this would just request the data from a model. - * For the purpose of this example, the data is hard-coded. - */ - private function getTheWholeList(): array - { - return [ - 'First', - 'Second', - 'Third', - ]; - } - - public function renderDefault(): void - { - if (!isset($this->template->list)) { - $this->template->list = $this->getTheWholeList(); - } - } - - public function handleUpdate(int $id): void - { - $this->template->list = $this->isAjax() - ? [] - : $this->getTheWholeList(); - $this->template->list[$id] = 'Updated item'; - $this->redrawControl('itemsContainer'); - } -} +$this->redrawControl('itemsContainer'); +$this->redrawControl('item-1'); ``` +It's also essential to ensure that the `$items` array contains only the items that should be redrawn. -Snippets in an Included Template -================================ - -It can happen that the snippet is in a template which is being included from a different template. In that case we need to wrap the inclusion code in the second template with the `snippetArea` tag, then we redraw both the snippetArea and the actual snippet. - -Tag `snippetArea` ensures that the code inside is executed but only the actual snippet in the included template is sent to the browser. +When inserting another template into the main one using the `{include}` tag, which has snippets, it's necessary to again wrap the included template in a `snippetArea` and invalidate both the snippet and the area together: ```latte -{* parent.latte *} -{snippetArea wrapper} - {include 'child.latte'} +{snippetArea include} + {include 'included.latte'} {/snippetArea} ``` + ```latte -{* child.latte *} +{* included.latte *} {snippet item} -... + ... {/snippet} ``` + ```php -$this->redrawControl('wrapper'); +$this->redrawControl('include'); $this->redrawControl('item'); ``` -You can also combine it with dynamic snippets. - -Adding and Deleting -=================== +Snippets in Components +---------------------- -If you add a new item into the list and invalidate `itemsContainer`, the AJAX request returns snippets including the new one, but the javascript handler won’t be able to render it. This is because there is no HTML element with the newly created ID. - -In this case, the simplest way is to wrap the whole list in one more snippet and invalidate it all: +You can create snippets within [components], and Nette will automatically redraw them. However, there's a specific limitation: to redraw snippets, it calls the `render()` method without any parameters. Thus, passing parameters in the template won't work: ```latte -{snippet wholeList} -
      - {foreach $list as $id => $item} -
    • {$item} update
    • - {/foreach} -
    -{/snippet} -Add +OK +{control productGrid} + +will not work: +{control productGrid $arg, $arg} +{control productGrid:paginator} ``` + +Sending User Data +----------------- + +Along with snippets, you can send any additional data to the client. Simply write them into the `payload` object: + ```php -public function handleAdd(): void +public function actionDelete(int $id): void { - $this->template->list = $this->getTheWholeList(); - $this->template->list[] = 'New one'; - $this->redrawControl('wholeList'); + // ... + if ($this->isAjax()) { + $this->payload->message = 'Success'; + } } ``` -The same goes for deleting an item. It would be possible to send empty snippet, but usually lists can be paginated and it would be complicated to implement deleting one item and loading another (which used to be on a different page of the paginated list). - -Sending Parameters to Component -=============================== +Sending Parameters +================== When we send parameters to the component via AJAX request, whether signal parameters or persistent parameters, we must provide their global name, which also contains the name of the component. The full name of parameter returns the `getParameterId()` method. ```js -$.getJSON( - {link changeCountBasket!}, - { - {$control->getParameterId('id')}: id, - {$control->getParameterId('count')}: count - } -}); +let url = new URL({link //foo!}); +url.searchParams.set({$control->getParameterId('bar')}, bar); + +fetch(url, { + headers: {'X-Requested-With': 'XMLHttpRequest'}, +}) ``` -And handle method with s corresponding parameters in component. +A handle method with the corresponding parameters in the component: ```php -public function handleChangeCountBasket(int $id, int $count): void +public function handleFoo(int $bar): void { - } ``` diff --git a/application/en/components.texy b/application/en/components.texy index b610a84739..eb131f7990 100644 --- a/application/en/components.texy +++ b/application/en/components.texy @@ -380,7 +380,7 @@ Components in Depth Components in a Nette Application are the reusable parts of a web application that we embed in pages, which is the subject of this chapter. What exactly are the capabilities of such a component? 1) it is renderable in a template -2) it knows which part of itself to render during an [AJAX request |ajax#invalidation] (snippets) +2) it knows [which part of itself |ajax#snippets] to render during an AJAX request (snippets) 3) it has the ability to store its state in a URL (persistent parameters) 4) has the ability to respond to user actions (signals) 5) creates a hierarchical structure (where the root is the presenter) diff --git a/application/es/ajax.texy b/application/es/ajax.texy index db292160c4..a90acb698b 100644 --- a/application/es/ajax.texy +++ b/application/es/ajax.texy @@ -3,10 +3,10 @@ AJAX y fragmentos
    -Hoy en día, las aplicaciones web modernas se ejecutan mitad en un servidor y mitad en un navegador. AJAX es un factor de unión vital. ¿Qué soporte ofrece Nette Framework? -- envío de fragmentos de plantillas (los llamados *snippets*) +En la era de las aplicaciones web modernas, donde la funcionalidad a menudo se extiende entre el servidor y el navegador, AJAX es un elemento de conexión esencial. ¿Qué opciones ofrece Nette Framework en este ámbito? +- envío de partes de la plantilla, los llamados snippets - paso de variables entre PHP y JavaScript -- depuración de aplicaciones AJAX +- herramientas para depurar peticiones AJAX
    @@ -14,29 +14,32 @@ Hoy en día, las aplicaciones web modernas se ejecutan mitad en un servidor y mi Solicitud AJAX .[#toc-ajax-request] =================================== -Una petición AJAX no difiere de una petición clásica: se llama al presentador con una vista y unos parámetros específicos. También depende del presentador cómo responder a ella: puede utilizar su propia rutina, que devuelve un fragmento de código HTML (HTML snippet), un documento XML, un objeto JSON o código JavaScript. +Una petición AJAX fundamentalmente no difiere de una petición HTTP clásica. Se llama a un presentador con parámetros específicos. Depende del presentador cómo responder a la petición - puede devolver datos en formato JSON, enviar una parte de código HTML, un documento XML, etc. -En el lado del servidor, una petición AJAX puede detectarse utilizando el método de servicio [que encapsula la petición HTTP |http:request] `$httpRequest->isAjax()` (detecta basándose en la cabecera HTTP `X-Requested-With`). Dentro del presentador, se dispone de un acceso directo en forma del método `$this->isAjax()`. +En el navegador, iniciamos una petición AJAX utilizando la función `fetch()`: -Existe un objeto preprocesado llamado `payload` dedicado a enviar datos al navegador en JSON. - -```php -public function actionDelete(int $id): void -{ - if ($this->isAjax()) { - $this->payload->message = 'Success'; - } - // ... -} +```js +fetch(url, { + headers: {'X-Requested-With': 'XMLHttpRequest'}, +}) +.then(response => response.json()) +.then(payload => { + // tratamiento de la respuesta +}); ``` -Para un control total sobre su salida JSON utilice el método `sendJson` en su presentador. Terminará el presentador inmediatamente y prescindirá de una plantilla: +En el lado del servidor, una petición AJAX es reconocida por el método `$httpRequest->isAjax()` del servicio [que encapsula la petición HTTP |http:request]. Utiliza la cabecera HTTP `X-Requested-With`, por lo que es imprescindible enviarla. Dentro del presentador, puede utilizar el método `$this->isAjax()`. + +Si desea enviar datos en formato JSON, utilice el método [`sendJson()` |presenters#Sending a response] método. El método también finaliza la actividad del presentador. ```php -$this->sendJson(['key' => 'value', /* ... */]); +public function actionExport(): void +{ + $this->sendJson($this->model->getData); +} ``` -Si queremos enviar HTML, podemos establecer una plantilla especial para peticiones AJAX: +Si planea responder con una plantilla especial diseñada para AJAX, puede hacerlo de la siguiente manera: ```php public function handleClick($param): void @@ -44,27 +47,37 @@ public function handleClick($param): void if ($this->isAjax()) { $this->template->setFile('path/to/ajax.latte'); } - // ... + //... } ``` +Recortes .[#toc-snippets] +========================= + +La herramienta más potente que ofrece Nette para conectar el servidor con el cliente son los snippets. Con ellos, puedes convertir una aplicación ordinaria en una AJAX con el mínimo esfuerzo y unas pocas líneas de código. El ejemplo Fifteen demuestra cómo funciona todo, y su código puede encontrarse en [GitHub |https://github.com/nette-examples/fifteen]. + +Los snippets, o recortes, permiten actualizar sólo partes de la página, en lugar de recargarla entera. Esto es más rápido y eficiente, y también proporciona una experiencia de usuario más cómoda. Puede que los snippets te recuerden a Hotwire para Ruby on Rails o a Symfony UX Turbo. Curiosamente, Nette introdujo los snippets 14 años antes. + +¿Cómo funcionan los fragmentos? Cuando se carga la página por primera vez (una petición no-AJAX), se carga toda la página, incluidos todos los fragmentos. Cuando el usuario interactúa con la página (por ejemplo, hace clic en un botón, envía un formulario, etc.), en lugar de cargarse toda la página, se realiza una solicitud AJAX. El código del presentador ejecuta la acción y decide qué fragmentos deben actualizarse. Nette renderiza estos fragmentos y los envía en forma de matriz JSON. A continuación, el código de gestión del navegador vuelve a insertar en la página los fragmentos recibidos. Por lo tanto, sólo se transfiere el código de los fragmentos modificados, lo que ahorra ancho de banda y acelera la carga en comparación con la transferencia de todo el contenido de la página. + + Naja .[#toc-naja] -================= +----------------- -K obsluze AJAXových požadavků na straně prohlížeče slouží [knihovna Naja |https://naja.js.org], [instálalo |https://naja.js.org/#/guide/01-install-setup-naja] como un paquete node.js (para usarlo con Webpack, Rollup, Vite, Parcel y más): +Para manejar snippets en el lado del navegador, se utiliza la [librería Naja |https://naja.js.org]. [Instálala |https://naja.js.org/#/guide/01-install-setup-naja] como un paquete node.js (para usar con aplicaciones como Webpack, Rollup, Vite, Parcel, y otras): ```shell npm install naja ``` -...o insertarlo directamente en la plantilla de la página: +... o insértala directamente en la plantilla de la página: ```html ``` -Para crear una solicitud AJAX a partir de un enlace normal (señal) o el envío de un formulario, basta con marcar el enlace, formulario o botón correspondiente con la clase `ajax`: +Para convertir un enlace ordinario (señal) o el envío de un formulario en una petición AJAX, basta con marcar el enlace, formulario o botón correspondiente con la clase `ajax`: ```html Go @@ -74,64 +87,39 @@ Para crear una solicitud AJAX a partir de un enlace normal (señal) o el envío or +
    ``` -Fragmentos .[#toc-snippets] -=========================== - -Existe una herramienta mucho más potente de soporte AJAX integrado: los snippets. Su uso permite convertir una aplicación normal en una aplicación AJAX utilizando sólo unas pocas líneas de código. Cómo funciona todo se demuestra en el ejemplo Fifteen cuyo código también está accesible en la compilación o en [GitHub |https://github.com/nette-examples/fifteen]. - -La forma en que funcionan los snippets es que toda la página se transfiere durante la petición inicial (es decir, no AJAX) y luego con cada [subpetición |components#signal] AJAX (petición de la misma vista del mismo presentador) sólo se transfiere el código de las partes modificadas en el repositorio `payload` mencionado anteriormente. - -Puede que los snippets te recuerden a Hotwire para Ruby on Rails o a Symfony UX Turbo, pero Nette los inventó catorce años antes. +Redibujar fragmentos .[#toc-redrawing-snippets] +----------------------------------------------- - -Invalidación de Snippets .[#toc-invalidation-of-snippets] -========================================================= - -Cada descendiente de la clase [Control |components] (que también es un Presentador) es capaz de recordar si hubo algún cambio durante una petición que requiera que se vuelva a renderizar. Hay un par de métodos para manejar esto: `redrawControl()` y `isControlInvalid()`. Un ejemplo: +Cada objeto de la clase [Control |components] (incluido el propio Presentador) mantiene un registro de si se han producido cambios que requieran su redibujado. Para ello se emplea el método `redrawControl()`. ```php public function handleLogin(string $user): void { - // The object has to re-render after the user has logged in + // después de iniciar la sesión, es necesario volver a dibujar la parte pertinente $this->redrawControl(); - // ... + //... } ``` -Nette, sin embargo, ofrece una resolución aún más fina que la de los componentes completos. Los métodos mencionados aceptan el nombre de un "fragmento" como parámetro opcional. Un "fragmento" es básicamente un elemento de su plantilla marcado para ese propósito por una tag Latte, más sobre esto más adelante. Así, es posible pedir a un componente que redibuje sólo *partes* de su plantilla. Si se invalida todo el componente, entonces se vuelven a renderizar todos sus fragmentos. Un componente es "inválido" también si cualquiera de sus subcomponentes es inválido. - -```php -$this->isControlInvalid(); // -> false -$this->redrawControl('header'); // invalidates the snippet named 'header' -$this->isControlInvalid('header'); // -> true -$this->isControlInvalid('footer'); // -> false -$this->isControlInvalid(); // -> true, at least one snippet is invalid +Nette también permite un control más preciso de lo que hay que redibujar. El método mencionado puede tomar el nombre del fragmento como argumento. Así, es posible invalidar (es decir: forzar un redibujado) a nivel de la parte de la plantilla. Si se invalida todo el componente, también se redibujan todos sus fragmentos: -$this->redrawControl(); // invalidates the whole component, every snippet -$this->isControlInvalid('footer'); // -> true +```php +// invalida el fragmento de cabecera +$this->redrawControl('header'); ``` -Un componente que recibe una señal se marca automáticamente para ser redibujado. - -Gracias al redibujado de fragmentos, sabemos exactamente qué partes de qué elementos deben redibujarse. - - -Etiqueta `{snippet} … {/snippet}` .{toc: Tag snippet} -===================================================== -El renderizado de la página procede de forma muy similar a una petición normal: se cargan las mismas plantillas, etc. Sin embargo, lo esencial es dejar fuera las partes que no deben llegar a la salida; las demás partes se asociarán a un identificador y se enviarán al usuario en un formato comprensible para un manipulador JavaScript. +Fragmentos en Latte .[#toc-snippets-in-latte] +--------------------------------------------- - -Sintaxis .[#toc-syntax] ------------------------ - -Si hay un control o un fragmento en la plantilla, tenemos que envolverlo usando la etiqueta `{snippet} ... {/snippet}` pair - se asegurará de que el fragmento renderizado será "recortado" y enviado al navegador. También lo encerrará en una etiqueta helper `
    ` (es posible utilizar otra). En el siguiente ejemplo se define un fragmento llamado `header`. También puede representar la plantilla de un componente: +Utilizar snippets en Latte es extremadamente fácil. Para definir una parte de la plantilla como fragmento, basta con envolverla en las etiquetas `{snippet}` y `{/snippet}`: ```latte {snippet header} @@ -139,7 +127,9 @@ Si hay un control o un fragmento en la plantilla, tenemos que envolverlo usando {/snippet} ``` -Si desea crear un fragmento con un elemento contenedor distinto de `
    ` o añadir atributos personalizados al elemento, puede utilizar la siguiente definición: +El fragmento crea un elemento `
    ` en la página HTML con un `id` especialmente generado. Al redibujar un fragmento, se actualiza el contenido de este elemento. Por lo tanto, cuando la página se renderiza inicialmente, también deben renderizarse todos los fragmentos, aunque inicialmente puedan estar vacíos. + +También puede crear un fragmento con un elemento distinto de `
    ` mediante un atributo n:attribute: ```latte
    @@ -148,138 +138,106 @@ Si desea crear un fragmento con un elemento contenedor distinto de `
    ` o añ ``` -Fragmentos dinámicos .[#toc-dynamic-snippets] -============================================= +Áreas de recortes .[#toc-snippet-areas] +--------------------------------------- -En Nette también puede definir fragmentos con un nombre dinámico basado en un parámetro de tiempo de ejecución. Esto es más adecuado para varias listas en las que necesitamos cambiar sólo una fila pero no queremos transferir toda la lista junto con ella. Un ejemplo de esto sería: +Los nombres de los recortes también pueden ser expresiones: ```latte -
      - {foreach $list as $id => $item} -
    • {$item} update
    • - {/foreach} -
    +{foreach $items as $id => $item} +
  • {$item}
  • +{/foreach} ``` -Hay un fragmento estático llamado `itemsContainer`, que contiene varios fragmentos dinámicos: `item-0` `item-1` y así sucesivamente. +De este modo, obtendremos varios fragmentos como `item-0`, `item-1`, etc. Si invalidáramos directamente un fragmento dinámico (por ejemplo, `item-1`), no se volvería a dibujar nada. La razón es que los fragmentos funcionan como verdaderos extractos y sólo ellos mismos se renderizan directamente. Sin embargo, en la plantilla no existe técnicamente un fragmento llamado `item-1`. Sólo aparece cuando se ejecuta el código que rodea al fragmento, en este caso, el bucle foreach. Por lo tanto, marcaremos la parte de la plantilla que necesita ser ejecutada con la etiqueta `{snippetArea}`: -No puedes redibujar un fragmento dinámico directamente (redibujar `item-1` no tiene ningún efecto), tienes que redibujar su fragmento padre (en este ejemplo `itemsContainer`). Esto hace que se ejecute el código del fragmento padre, pero entonces sólo se envían al navegador sus sub fragmentos. Si desea enviar sólo uno de los sub fragmentos, debe modificar la entrada del fragmento padre para que no genere los otros sub fragmentos. +```latte +
      + {foreach $items as $id => $item} +
    • {$item}
    • + {/foreach} +
    +``` -En el ejemplo anterior tiene que asegurarse de que para una petición AJAX sólo se añadirá un elemento a la matriz `$list`, por lo que el bucle `foreach` sólo imprimirá un fragmento dinámico. +Y redibujaremos tanto el fragmento individual como toda el área general: ```php -class HomePresenter extends Nette\Application\UI\Presenter -{ - /** - * This method returns data for the list. - * Usually this would just request the data from a model. - * For the purpose of this example, the data is hard-coded. - */ - private function getTheWholeList(): array - { - return [ - 'First', - 'Second', - 'Third', - ]; - } - - public function renderDefault(): void - { - if (!isset($this->template->list)) { - $this->template->list = $this->getTheWholeList(); - } - } - - public function handleUpdate(int $id): void - { - $this->template->list = $this->isAjax() - ? [] - : $this->getTheWholeList(); - $this->template->list[$id] = 'Updated item'; - $this->redrawControl('itemsContainer'); - } -} +$this->redrawControl('itemsContainer'); +$this->redrawControl('item-1'); ``` +También es esencial asegurarse de que la matriz `$items` contiene sólo los elementos que deben ser redibujados. -Fragmentos en una plantilla incluida .[#toc-snippets-in-an-included-template] -============================================================================= - -Puede ocurrir que el snippet esté en una plantilla que está siendo incluida desde una plantilla diferente. En ese caso necesitamos envolver el código de inclusión en la segunda plantilla con la tag `snippetArea`, entonces redibujamos tanto el snippetArea como el snippet real. - -La tag `snippetArea` garantiza que se ejecute el código que contiene, pero que sólo se envíe al navegador el fragmento real de la plantilla incluida. +Cuando se inserta otra plantilla en la principal utilizando la etiqueta `{include}`, que tiene fragmentos, es necesario envolver de nuevo la plantilla incluida en un `snippetArea` e invalidar conjuntamente el fragmento y el área: ```latte -{* parent.latte *} -{snippetArea wrapper} - {include 'child.latte'} +{snippetArea include} + {include 'included.latte'} {/snippetArea} ``` + ```latte -{* child.latte *} +{* included.latte *} {snippet item} -... + ... {/snippet} ``` + ```php -$this->redrawControl('wrapper'); +$this->redrawControl('include'); $this->redrawControl('item'); ``` -También se puede combinar con fragmentos dinámicos. - -Añadir y eliminar .[#toc-adding-and-deleting] -============================================= +Fragmentos en componentes .[#toc-snippets-in-components] +-------------------------------------------------------- -Si añades un nuevo elemento a la lista e invalidas `itemsContainer`, la petición AJAX devuelve fragmentos que incluyen el nuevo, pero el manejador javascript no podrá renderizarlo. Esto se debe a que no hay ningún elemento HTML con el ID recién creado. - -En este caso, la forma más sencilla es envolver toda la lista en un fragmento más e invalidarlo todo: +Puede crear fragmentos dentro de los [componentes |components] y Nette los redibujará automáticamente. Sin embargo, hay una limitación específica: para redibujar fragmentos, llama al método `render()` sin ningún parámetro. Por lo tanto, pasar parámetros en la plantilla no funcionará: ```latte -{snippet wholeList} -
      - {foreach $list as $id => $item} -
    • {$item} update
    • - {/foreach} -
    -{/snippet} -Add +OK +{control productGrid} + +will not work: +{control productGrid $arg, $arg} +{control productGrid:paginator} ``` + +Envío de datos de usuario .[#toc-sending-user-data] +--------------------------------------------------- + +Junto con los fragmentos, puede enviar cualquier dato adicional al cliente. Simplemente escríbalos en el objeto `payload`: + ```php -public function handleAdd(): void +public function actionDelete(int $id): void { - $this->template->list = $this->getTheWholeList(); - $this->template->list[] = 'New one'; - $this->redrawControl('wholeList'); + //... + if ($this->isAjax()) { + $this->payload->message = 'Success'; + } } ``` -Lo mismo ocurre con la eliminación de un elemento. Sería posible enviar un fragmento vacío, pero normalmente las listas pueden paginarse y sería complicado implementar la eliminación de un elemento y la carga de otro (que solía estar en una página diferente de la lista paginada). - -Envío de parámetros al componente .[#toc-sending-parameters-to-component] -========================================================================= +Envío de parámetros .[#toc-sending-parameters] +============================================== Cuando enviamos parámetros al componente a través de una petición AJAX, ya sean parámetros de señal o parámetros persistentes, debemos proporcionar su nombre global, que también contiene el nombre del componente. El nombre completo del parámetro devuelve el método `getParameterId()`. ```js -$.getJSON( - {link changeCountBasket!}, - { - {$control->getParameterId('id')}: id, - {$control->getParameterId('count')}: count - } -}); +let url = new URL({link //foo!}); +url.searchParams.set({$control->getParameterId('bar')}, bar); + +fetch(url, { + headers: {'X-Requested-With': 'XMLHttpRequest'}, +}) ``` -Y manejar el método con s parámetros correspondientes en el componente. +Un método handle con los parámetros correspondientes en el componente: ```php -public function handleChangeCountBasket(int $id, int $count): void +public function handleFoo(int $bar): void { - } ``` diff --git a/application/es/components.texy b/application/es/components.texy index 7f736ea960..837084cc94 100644 --- a/application/es/components.texy +++ b/application/es/components.texy @@ -380,7 +380,7 @@ Componentes en profundidad .[#toc-components-in-depth] Los componentes en una aplicación Nette son las partes reutilizables de una aplicación web que incrustamos en las páginas, que es el tema de este capítulo. ¿Cuáles son exactamente las capacidades de un componente? 1) es renderizable en una plantilla -2) sabe qué parte de sí mismo renderizar durante una [petición AJAX |ajax#invalidation] (fragmentos) +2) sabe [qué parte de sí mismo |ajax#snippets] debe representar durante una petición AJAX (fragmentos) 3) tiene la capacidad de almacenar su estado en una URL (parámetros persistentes) 4) tiene la capacidad de responder a las acciones del usuario (señales) 5) crea una estructura jerárquica (donde la raíz es el presentador) diff --git a/application/fr/ajax.texy b/application/fr/ajax.texy index 7e05c20cdc..6ef5b2bf32 100644 --- a/application/fr/ajax.texy +++ b/application/fr/ajax.texy @@ -1,12 +1,12 @@ -AJAX et Snippets -**************** +AJAX & Snippets +***************
    -Les applications web modernes fonctionnent aujourd'hui pour moitié sur un serveur et pour moitié dans un navigateur. AJAX est un facteur d'unité essentiel. Quel est le support offert par le Nette Framework ? -- l'envoi de fragments de modèles (appelés *snippets*) +À l'ère des applications web modernes, où les fonctionnalités s'étendent souvent entre le serveur et le navigateur, AJAX est un élément de connexion essentiel. Quelles sont les possibilités offertes par le Nette Framework dans ce domaine ? +- l'envoi de parties du modèle, appelées "snippets - le passage de variables entre PHP et JavaScript -- débogage des applications AJAX +- outils de débogage des requêtes AJAX
    @@ -14,29 +14,32 @@ Les applications web modernes fonctionnent aujourd'hui pour moitié sur un serve Demande AJAX .[#toc-ajax-request] ================================= -Une requête AJAX ne diffère pas d'une requête classique : le diffuseur est appelé avec une vue et des paramètres spécifiques. C'est également au présentateur de décider comment y répondre : il peut utiliser sa propre routine, qui renvoie un fragment de code HTML (extrait HTML), un document XML, un objet JSON ou du code JavaScript. +Une requête AJAX ne diffère pas fondamentalement d'une requête HTTP classique. Un présentateur est appelé avec des paramètres spécifiques. C'est au présentateur de décider comment répondre à la requête - il peut renvoyer des données au format JSON, envoyer une partie du code HTML, un document XML, etc. -Côté serveur, une requête AJAX peut être détectée à l'aide de la méthode de service [encapsulant la requête HTTP |http:request] `$httpRequest->isAjax()` (détection basée sur l'en-tête HTTP `X-Requested-With`). Dans le présentateur, un raccourci est disponible sous la forme de la méthode `$this->isAjax()`. +Du côté du navigateur, nous lançons une requête AJAX à l'aide de la fonction `fetch()`: -Il existe un objet prétraité appelé `payload` dédié à l'envoi de données au navigateur en JSON. - -```php -public function actionDelete(int $id): void -{ - if ($this->isAjax()) { - $this->payload->message = 'Success'; - } - // ... -} +```js +fetch(url, { + headers: {'X-Requested-With': 'XMLHttpRequest'}, +}) +.then(response => response.json()) +.then(payload => { + // traitement de la réponse +}); ``` -Pour un contrôle total de votre sortie JSON, utilisez la méthode `sendJson` dans votre présentateur. Elle met immédiatement fin au présentateur et vous vous passerez de modèle : +Du côté du serveur, une requête AJAX est reconnue par la méthode `$httpRequest->isAjax()` du service [encapsulant la requête HTTP |http:request]. Elle utilise l'en-tête HTTP `X-Requested-With`, qu'il est donc essentiel d'envoyer. Dans le présentateur, vous pouvez utiliser la méthode `$this->isAjax()`. + +Si vous souhaitez envoyer des données au format JSON, utilisez la méthode [`sendJson()` |presenters#Sending a response] méthode. La méthode met également fin à l'activité du présentateur. ```php -$this->sendJson(['key' => 'value', /* ... */]); +public function actionExport(): void +{ + $this->sendJson($this->model->getData); +} ``` -Si nous voulons envoyer du HTML, nous pouvons soit définir un modèle spécial pour les demandes AJAX : +Si vous envisagez de répondre avec un modèle spécial conçu pour AJAX, vous pouvez procéder comme suit : ```php public function handleClick($param): void @@ -44,27 +47,37 @@ public function handleClick($param): void if ($this->isAjax()) { $this->template->setFile('path/to/ajax.latte'); } - // ... + //... } ``` +Bribes .[#toc-snippets] +======================= + +Les snippets sont l'outil le plus puissant offert par Nette pour connecter le serveur au client. Grâce à eux, vous pouvez transformer une application ordinaire en une application AJAX avec un minimum d'effort et quelques lignes de code. L'exemple Fifteen montre comment tout cela fonctionne, et son code peut être trouvé sur [GitHub |https://github.com/nette-examples/fifteen]. + +Les snippets, ou clippings, vous permettent de ne mettre à jour que certaines parties de la page, au lieu de recharger toute la page. C'est plus rapide et plus efficace, et l'expérience utilisateur est plus confortable. Les snippets peuvent vous rappeler Hotwire pour Ruby on Rails ou Symfony UX Turbo. Il est intéressant de noter que Nette a introduit les snippets 14 ans plus tôt. + +Comment fonctionnent les snippets ? Lorsque la page est chargée pour la première fois (requête non-AJAX), la page entière, y compris tous les snippets, est chargée. Lorsque l'utilisateur interagit avec la page (par exemple, lorsqu'il clique sur un bouton, soumet un formulaire, etc.), au lieu de charger la page entière, une requête AJAX est effectuée. Le code du présentateur exécute l'action et décide quels extraits doivent être mis à jour. Nette rend ces extraits et les envoie sous la forme d'un tableau JSON. Le code de traitement du navigateur réintègre alors les extraits reçus dans la page. Par conséquent, seul le code des extraits modifiés est transféré, ce qui permet d'économiser de la bande passante et d'accélérer le chargement par rapport au transfert de l'ensemble du contenu de la page. + + Naja .[#toc-naja] -================= +----------------- -La [bibliothèque Naja |https://naja.js.org] est utilisée pour gérer les requêtes AJAX du côté du navigateur. [Installez-la |https://naja.js.org/#/guide/01-install-setup-naja] en tant que paquet node.js (à utiliser avec Webpack, Rollup, Vite, Parcel et plus) : +La [bibliothèque Naja |https://naja.js.org] est utilisée pour gérer les snippets du côté du navigateur. [Installez-la |https://naja.js.org/#/guide/01-install-setup-naja] en tant que paquetage node.js (pour une utilisation avec des applications telles que Webpack, Rollup, Vite, Parcel, et d'autres) : ```shell npm install naja ``` -...ou insérez-la directement dans le modèle de page : +... ou insérez-la directement dans le modèle de page : ```html ``` -Pour créer une requête AJAX à partir d'un lien normal (signal) ou d'une soumission de formulaire, il suffit de marquer le lien, le formulaire ou le bouton concerné avec la classe `ajax`: +Pour faire d'un lien ordinaire (signal) ou d'une soumission de formulaire une requête AJAX, il suffit de marquer le lien, le formulaire ou le bouton correspondant avec la classe `ajax`: ```html Go @@ -74,64 +87,39 @@ Pour créer une requête AJAX à partir d'un lien normal (signal) ou d'une soumi or +
    ``` -Extraits de texte .[#toc-snippets] -================================== - -Il existe un outil bien plus puissant que le support AJAX intégré : les snippets. Leur utilisation permet de transformer une application ordinaire en une application AJAX en utilisant seulement quelques lignes de code. La façon dont tout cela fonctionne est démontrée dans l'exemple Fifteen dont le code est également accessible dans le build ou sur [GitHub |https://github.com/nette-examples/fifteen]. - -Le fonctionnement des snippets est le suivant : la page entière est transférée lors de la requête initiale (c'est-à-dire non-AJAX), puis à chaque [sous-requête |components#signal] AJAX (requête de la même vue du même présentateur), seul le code des parties modifiées est transféré dans le dépôt `payload` mentionné précédemment. - -Les snippets vous rappellent peut-être Hotwire pour Ruby on Rails ou Symfony UX Turbo, mais Nette les a inventés quatorze ans plus tôt. +Redessiner des extraits .[#toc-redrawing-snippets] +-------------------------------------------------- - -Invalidation des Snippets .[#toc-invalidation-of-snippets] -========================================================== - -Chaque descendant de la classe [Control |components] (ce qu'est aussi un Presenter) est capable de se souvenir si des changements sont intervenus au cours d'une requête qui nécessitent un nouveau rendu. Il existe une paire de méthodes pour gérer cela : `redrawControl()` et `isControlInvalid()`. Un exemple : +Chaque objet de la classe [Control |components] (y compris le Presenter lui-même) garde une trace des changements survenus qui nécessitent son redécoupage. La méthode `redrawControl()` est utilisée à cette fin. ```php public function handleLogin(string $user): void { - // L'objet doit être rendu à nouveau après que l'utilisateur se soit connecté. + // après la connexion, il est nécessaire de redessiner la partie concernée $this->redrawControl(); - // ... + //... } ``` -Nette offre cependant une résolution encore plus fine que les composants entiers. Les méthodes listées acceptent le nom d'un "snippet" comme paramètre optionnel. Un "snippet" est en fait un élément de votre modèle marqué à cet effet par une tag Latte, nous y reviendrons plus tard. Il est donc possible de demander à un composant de ne redessiner que des *parties* de son modèle. Si le composant entier est invalidé, tous ses snippets sont redessinés. Un composant est également "invalide" si l'un de ses sous-composants est invalide. - -```php -$this->isControlInvalid(); // -> false -$this->redrawControl('header'); // invalide le snippet nommé 'header'. -$this->isControlInvalid('header'); // -> true -$this->isControlInvalid('footer'); // -> false -$this->isControlInvalid(); // -> true, au moins un extrait est invalide. +Nette permet également un contrôle plus fin de ce qui doit être redessiné. La méthode susmentionnée peut prendre le nom de l'extrait comme argument. Ainsi, il est possible d'invalider (c'est-à-dire de forcer un nouveau dessin) au niveau de la partie du modèle. Si l'ensemble du composant est invalidé, chaque extrait est également redessiné : -$this->redrawControl(); // invalide l'ensemble du composant, chaque extrait. -$this->isControlInvalid('footer'); // -> true +```php +// invalide l'extrait "header" (en-tête) +$this->redrawControl('header'); ``` -Un composant qui reçoit un signal est automatiquement marqué pour être redessiné. - -Grâce au redessin de snippet, nous savons exactement quelles parties de quels éléments doivent être redessinées. - - -Balise `{snippet} … {/snippet}` .{toc: Tag snippet} -=================================================== -Le rendu de la page se déroule de manière très similaire à une requête ordinaire : les mêmes modèles sont chargés, etc. L'essentiel est toutefois de laisser de côté les parties qui ne sont pas censées atteindre la sortie ; les autres parties doivent être associées à un identifiant et envoyées à l'utilisateur dans un format compréhensible pour un gestionnaire JavaScript. +Bribes dans Latte .[#toc-snippets-in-latte] +------------------------------------------- - -Syntaxe .[#toc-syntax] ----------------------- - -Si le modèle contient un contrôle ou un extrait, nous devons l'envelopper à l'aide de la balise de paire `{snippet} ... {/snippet}`. Elle veillera à ce que l'extrait rendu soit "découpé" et envoyé au navigateur. Elle l'enfermera également dans une balise auxiliaire `
    ` (il est possible d'en utiliser une autre). Dans l'exemple suivant, un extrait nommé `header` est défini. Il peut tout aussi bien représenter le modèle d'un composant : +L'utilisation des snippets dans Latte est extrêmement simple. Pour définir une partie du modèle comme un extrait, il suffit de l'entourer des balises `{snippet}` et `{/snippet}`: ```latte {snippet header} @@ -139,7 +127,9 @@ Si le modèle contient un contrôle ou un extrait, nous devons l'envelopper à l {/snippet} ``` -Si vous souhaitez créer un snippet avec un élément contenant différent de `
    ` ou ajouter des attributs personnalisés à l'élément, vous pouvez utiliser la définition suivante : +Le snippet crée un élément `
    ` dans la page HTML avec un `id` spécialement généré. Lorsqu'un extrait est redessiné, le contenu de cet élément est mis à jour. Par conséquent, lors du rendu initial de la page, tous les snippets doivent également être rendus, même s'ils sont initialement vides. + +Vous pouvez également créer un extrait avec un élément autre que `
    ` à l'aide d'un attribut n: : ```latte
    @@ -148,138 +138,106 @@ Si vous souhaitez créer un snippet avec un élément contenant différent de `< ``` -Dynamic Snippets .[#toc-dynamic-snippets] -========================================= +Zones d'échantillonnage .[#toc-snippet-areas] +--------------------------------------------- -Dans Nette, vous pouvez également définir des snippets avec un nom dynamique basé sur un paramètre d'exécution. C'est la solution la plus appropriée pour les listes diverses où nous devons modifier une seule ligne mais où nous ne voulons pas transférer toute la liste avec elle. Un exemple de ceci serait : +Les noms des snippets peuvent également être des expressions : ```latte -
      - {foreach $list as $id => $item} -
    • {$item} update
    • - {/foreach} -
    +{foreach $items as $id => $item} +
  • {$item}
  • +{/foreach} ``` -Il y a un snippet statique appelé `itemsContainer`, contenant plusieurs snippets dynamiques : `item-0`, `item-1` et ainsi de suite. +De cette manière, nous obtiendrons plusieurs snippets comme `item-0`, `item-1`, etc. Si nous devions invalider directement un extrait dynamique (par exemple, `item-1`), rien ne serait redessiné. La raison en est que les snippets fonctionnent comme de véritables extraits et qu'ils sont les seuls à être rendus directement. Cependant, dans le modèle, il n'y a pas techniquement d'extrait nommé `item-1`. Il n'apparaît que lors de l'exécution du code environnant de l'extrait, dans ce cas, la boucle foreach. Par conséquent, nous marquerons la partie du modèle qui doit être exécutée avec la balise `{snippetArea}`: -Vous ne pouvez pas redessiner un extrait dynamique directement (redessiner `item-1` n'a aucun effet), vous devez redessiner son extrait parent (dans cet exemple `itemsContainer`). Le code du snippet parent est alors exécuté, mais seuls ses sous-snippets sont envoyés au navigateur. Si vous souhaitez n'envoyer qu'un seul des sous-ensembles, vous devez modifier l'entrée du snippet parent pour ne pas générer les autres sous-ensembles. +```latte +
      + {foreach $items as $id => $item} +
    • {$item}
    • + {/foreach} +
    +``` -Dans l'exemple ci-dessus, vous devez vous assurer que, pour une requête AJAX, un seul élément sera ajouté au tableau `$list`. Par conséquent, la boucle `foreach` n'imprimera qu'un seul extrait dynamique. +Et nous redessinerons à la fois l'extrait individuel et l'ensemble de la zone globale : ```php -class HomePresenter extends Nette\Application\UI\Presenter -{ - /** - * This method returns data for the list. - * Usually this would just request the data from a model. - * For the purpose of this example, the data is hard-coded. - */ - private function getTheWholeList(): array - { - return [ - 'First', - 'Second', - 'Third', - ]; - } - - public function renderDefault(): void - { - if (!isset($this->template->list)) { - $this->template->list = $this->getTheWholeList(); - } - } - - public function handleUpdate(int $id): void - { - $this->template->list = $this->isAjax() - ? [] - : $this->getTheWholeList(); - $this->template->list[$id] = 'Updated item'; - $this->redrawControl('itemsContainer'); - } -} +$this->redrawControl('itemsContainer'); +$this->redrawControl('item-1'); ``` +Il est également essentiel de s'assurer que le tableau `$items` ne contient que les éléments qui doivent être redessinés. -Extraits dans un modèle inclus .[#toc-snippets-in-an-included-template] -======================================================================= - -Il peut arriver que le snippet se trouve dans un modèle qui est inclus à partir d'un autre modèle. Dans ce cas, nous devons envelopper le code d'inclusion dans le second modèle avec la tag `snippetArea`, puis nous redessinons à la fois la snippetArea et le snippet lui-même. - -La tag `snippetArea` garantit que le code qu'elle contient est exécuté mais que seul l'extrait réel du modèle inclus est envoyé au navigateur. +Lors de l'insertion d'un autre modèle dans le modèle principal à l'aide de la balise `{include}`, qui contient des extraits, il est nécessaire d'envelopper à nouveau le modèle inclus dans une balise `snippetArea` et d'invalider à la fois l'extrait et la zone : ```latte -{* parent.latte *} -{snippetArea wrapper} - {include 'child.latte'} +{snippetArea include} + {include 'included.latte'} {/snippetArea} ``` + ```latte -{* child.latte *} +{* inclus.latte *} {snippet item} -... + ... {/snippet} ``` + ```php -$this->redrawControl('wrapper'); +$this->redrawControl('include'); $this->redrawControl('item'); ``` -Vous pouvez également la combiner avec des extraits dynamiques. - -Ajout et suppression .[#toc-adding-and-deleting] -================================================ +Les snippets dans les composants .[#toc-snippets-in-components] +--------------------------------------------------------------- -Si vous ajoutez un nouvel élément dans la liste et que vous invalidez `itemsContainer`, la requête AJAX renvoie des extraits incluant le nouvel élément, mais le gestionnaire javascript ne sera pas en mesure de le rendre. Cela est dû au fait qu'il n'y a pas d'élément HTML avec l'ID nouvellement créé. - -Dans ce cas, le moyen le plus simple est d'envelopper toute la liste dans un autre extrait et de l'invalider : +Vous pouvez créer des snippets dans les [composants |components], et Nette les redessinera automatiquement. Cependant, il y a une limitation spécifique : pour redessiner les snippets, il faut appeler la méthode `render()` sans aucun paramètre. Par conséquent, passer des paramètres dans le modèle ne fonctionnera pas : ```latte -{snippet wholeList} -
      - {foreach $list as $id => $item} -
    • {$item} update
    • - {/foreach} -
    -{/snippet} -Add +OK +{control productGrid} + +will not work: +{control productGrid $arg, $arg} +{control productGrid:paginator} ``` + +Envoi de données utilisateur .[#toc-sending-user-data] +------------------------------------------------------ + +En plus des snippets, vous pouvez envoyer des données supplémentaires au client. Il suffit de les écrire dans l'objet `payload`: + ```php -public function handleAdd(): void +public function actionDelete(int $id): void { - $this->template->list = $this->getTheWholeList(); - $this->template->list[] = 'New one'; - $this->redrawControl('wholeList'); + //... + if ($this->isAjax()) { + $this->payload->message = 'Success'; + } } ``` -Il en va de même pour la suppression d'un élément. Il serait possible d'envoyer un extrait vide, mais les listes peuvent généralement être paginées et il serait compliqué d'implémenter la suppression d'un élément et le chargement d'un autre (qui se trouvait sur une page différente de la liste paginée). - -Envoi de paramètres au composant .[#toc-sending-parameters-to-component] -======================================================================== +Paramètres d'envoi .[#toc-sending-parameters] +============================================= -Lorsque nous envoyons des paramètres au composant via une requête AJAX, qu'il s'agisse de paramètres de signal ou de paramètres persistants, nous devons fournir leur nom global, qui contient également le nom du composant. Le nom global du paramètre renvoie la méthode `getParameterId()`. +Lorsque nous envoyons des paramètres au composant via une requête AJAX, qu'il s'agisse de paramètres de signal ou de paramètres persistants, nous devons fournir leur nom global, qui contient également le nom du composant. Le nom complet du paramètre renvoie la méthode `getParameterId()`. ```js -$.getJSON( - {link changeCountBasket!}, - { - {$control->getParameterId('id')}: id, - {$control->getParameterId('count')}: count - } -}); +let url = new URL({link //foo!}); +url.searchParams.set({$control->getParameterId('bar')}, bar); + +fetch(url, { + headers: {'X-Requested-With': 'XMLHttpRequest'}, +}) ``` -Et traiter la méthode avec les paramètres correspondants dans le composant. +Une méthode handle avec les paramètres correspondants dans le composant : ```php -public function handleChangeCountBasket(int $id, int $count): void +public function handleFoo(int $bar): void { - } ``` diff --git a/application/fr/components.texy b/application/fr/components.texy index f2bee8ea59..b35c16a737 100644 --- a/application/fr/components.texy +++ b/application/fr/components.texy @@ -380,7 +380,7 @@ Les composants en profondeur .[#toc-components-in-depth] Les composants d'une application Nette sont les parties réutilisables d'une application Web que nous intégrons dans les pages, ce qui est le sujet de ce chapitre. Quelles sont exactement les capacités d'un tel composant ? 1) il peut être rendu dans un modèle -2) Il sait quelle partie de lui-même doit être rendue lors d'une [requête AJAX |ajax#invalidation] (snippets). +2) il sait [quelle partie de lui-même |ajax#snippets] rendre lors d'une requête AJAX (snippets) 3) il a la capacité de stocker son état dans une URL (paramètres persistants) 4) il a la capacité de répondre aux actions de l'utilisateur (signaux) 5) il crée une structure hiérarchique (dont la racine est le présentateur). diff --git a/application/hu/ajax.texy b/application/hu/ajax.texy index e086df6f19..24ec5880e0 100644 --- a/application/hu/ajax.texy +++ b/application/hu/ajax.texy @@ -3,10 +3,10 @@ AJAX & Snippetek
    -A modern webes alkalmazások manapság félig a szerveren, félig a böngészőben futnak. Az AJAX létfontosságú egyesítő tényező. Milyen támogatást nyújt a Nette Framework? -- sablonrészletek küldése (ún. *snippetek*) -- változók átadása PHP és JavaScript között -- AJAX-alkalmazások hibakeresése +A modern webes alkalmazások korában, ahol a funkciók gyakran a szerver és a böngésző között helyezkednek el, az AJAX elengedhetetlen összekötő elem. Milyen lehetőségeket kínál a Nette Framework ezen a területen? +- A sablon részeinek, az ún. snippeteknek a küldése. +- változók átadása a PHP és a JavaScript között +- AJAX-kérések hibakeresésére szolgáló eszközök
    @@ -14,29 +14,32 @@ A modern webes alkalmazások manapság félig a szerveren, félig a böngészőb AJAX kérés .[#toc-ajax-request] =============================== -Az AJAX-kérés nem különbözik a klasszikus kéréstől - a bemutatót egy adott nézettel és paraméterekkel hívják meg. Az is a prezenteren múlik, hogyan válaszol rá: használhat saját rutint, amely egy HTML kódrészletet (HTML snippet), egy XML-dokumentumot, egy JSON-objektumot vagy JavaScript-kódot ad vissza. +Az AJAX-kérés alapvetően nem különbözik a klasszikus HTTP-kéréstől. Egy bemutatót hívunk meg bizonyos paraméterekkel. A bemutatótól függ, hogyan válaszol a kérésre - adhat vissza adatokat JSON formátumban, küldhet egy HTML kódrészt, egy XML-dokumentumot stb. -Kiszolgálói oldalon az AJAX-kérés a [HTTP-kérést kapszulázó |http:request] szolgáltatási módszerrel detektálható `$httpRequest->isAjax()` (a HTTP fejléc alapján detektál `X-Requested-With`). A prezenteren belül a `$this->isAjax()` metódus formájában egy rövidítés áll rendelkezésre. +A böngésző oldalán AJAX-kérést kezdeményezünk a `fetch()` funkcióval: -Létezik egy `payload` nevű előfeldolgozott objektum, amely arra szolgál, hogy az adatokat JSON-ban küldje el a böngészőnek. - -```php -public function actionDelete(int $id): void -{ - if ($this->isAjax()) { - $this->payload->message = 'Success'; - } - // ... -} +```js +fetch(url, { + headers: {'X-Requested-With': 'XMLHttpRequest'}, +}) +.then(response => response.json()) +.then(payload => { + // a válasz feldolgozása +}); ``` -A JSON kimenet teljes ellenőrzéséhez használja a `sendJson` metódust a prezenterben. Ez azonnal befejezi a prezentert, és sablon nélkül is boldogulsz: +A szerveroldalon az AJAX-kérést a [HTTP-kérést kapszulázó |http:request] szolgáltatás `$httpRequest->isAjax()` módszere ismeri fel. Ez a `X-Requested-With` HTTP fejlécet használja, ezért elengedhetetlen a küldése. A prezenteren belül a `$this->isAjax()` metódust használhatja. + +Ha JSON formátumban szeretne adatokat küldeni, használja a [`sendJson()` |presenters#Sending a response] módszert. A metódus a prezenter tevékenységét is befejezi. ```php -$this->sendJson(['key' => 'value', /* ... */]); +public function actionExport(): void +{ + $this->sendJson($this->model->getData); +} ``` -Ha HTML-t szeretnénk küldeni, akkor vagy beállíthatunk egy speciális sablont az AJAX-kérésekhez: +Ha azt tervezi, hogy egy speciális, AJAX-hoz tervezett sablonnal válaszol, akkor azt a következőképpen teheti meg: ```php public function handleClick($param): void @@ -44,27 +47,37 @@ public function handleClick($param): void if ($this->isAjax()) { $this->template->setFile('path/to/ajax.latte'); } - // ... + //... } ``` +Snippets .[#toc-snippets] +========================= + +A Nette által kínált leghatékonyabb eszköz a szerver és az ügyfél összekapcsolására a snippetek. Segítségükkel egy közönséges alkalmazásból minimális erőfeszítéssel és néhány sornyi kóddal AJAX-alkalmazássá alakítható. A Fifteen példája bemutatja, hogyan működik mindez, és a kódja megtalálható a [GitHubon |https://github.com/nette-examples/fifteen]. + +A snippetek, vagyis a kivágások lehetővé teszik, hogy az oldalnak csak egyes részeit frissítsük, ahelyett, hogy az egész oldalt újratöltenénk. Ez gyorsabb és hatékonyabb, és kényelmesebb felhasználói élményt is nyújt. A snippetek a Ruby on Rails Hotwire vagy a Symfony UX Turbo programjára emlékeztethetnek. Érdekes módon a Nette 14 évvel korábban vezette be a snippeteket. + +Hogyan működnek a snippetek? Az oldal első betöltésekor (egy nem-AJAX kérés) a teljes oldal betöltődik, beleértve az összes snippetet is. Amikor a felhasználó interakcióba lép az oldallal (pl. rákattint egy gombra, elküld egy űrlapot stb.), a teljes oldal betöltése helyett AJAX-kérés történik. A prezenterben lévő kód végzi el a műveletet, és dönti el, hogy mely snippetek igényelnek frissítést. A Nette rendereli ezeket a részleteket, és egy JSON tömb formájában elküldi őket. A böngészőben lévő kezelő kód ezután visszahelyezi a kapott részleteket az oldalba. Ezért csak a módosított snippetek kódja kerül átvitelre, ami a teljes oldaltartalom átviteléhez képest sávszélességet takarít meg és gyorsítja a betöltést. + + Naja .[#toc-naja] -================= +----------------- -A [Naja könyvtár |https://naja.js.org] az AJAX kérések kezelésére szolgál a böngésző oldalán. [Telepítsd |https://naja.js.org/#/guide/01-install-setup-naja] node.js csomagként (Webpack, Rollup, Vite, Parcel és más csomagokkal való használathoz): +A snippetek böngészőoldali kezeléséhez a [Naja könyvtárat |https://naja.js.org] használjuk. [Telepítse |https://naja.js.org/#/guide/01-install-setup-naja] node.js csomagként (olyan alkalmazásokkal használható, mint a Webpack, Rollup, Vite, Parcel és mások): ```shell npm install naja ``` -...vagy illessze be közvetlenül az oldal sablonjába: +... vagy illessze be közvetlenül az oldal sablonjába: ```html ``` -Ahhoz, hogy AJAX-kérést hozzon létre egy hagyományos linkből (jel) vagy űrlapküldésből, egyszerűen jelölje meg az adott linket, űrlapot vagy gombot a `ajax` osztállyal: +Ahhoz, hogy egy közönséges linket (jelet) vagy űrlapküldést AJAX-kérelemmé tegyen, egyszerűen jelölje meg az adott linket, űrlapot vagy gombot a `ajax` osztállyal: ```html Go @@ -74,64 +87,39 @@ Ahhoz, hogy AJAX-kérést hozzon létre egy hagyományos linkből (jel) vagy űr or +
    ``` -Snippets .[#toc-snippets] -========================= - -A beépített AJAX-támogatásnak van egy sokkal hatékonyabb eszköze - a snippetek. Használatuk lehetővé teszi, hogy egy hagyományos alkalmazásból AJAX-alkalmazássá váljon mindössze néhány sornyi kóddal. Hogy mindez hogyan működik, azt a Fifteen példa mutatja be, amelynek kódja a buildben vagy a [GitHubon |https://github.com/nette-examples/fifteen] is elérhető. - -A snippetek úgy működnek, hogy a kezdeti (azaz nem AJAX) kérés során a teljes oldal átkerül, majd minden AJAX [alkérésnél |components#signal] (ugyanazon bemutató azonos nézetének kérése) csak a módosított részek kódja kerül át a már említett `payload` tárolóba. - -A Snippetek a Ruby on Rails Hotwire vagy a Symfony UX Turbo-ra emlékeztethetnek, de Nette tizennégy évvel korábban találta ki őket. - +Snippetek újrarajzolása .[#toc-redrawing-snippets] +-------------------------------------------------- -A Snippetek érvénytelenítése .[#toc-invalidation-of-snippets] -============================================================= - -A [Control |components] osztály minden leszármazottja (ami egy Presenter is) képes megjegyezni, hogy egy kérés során történt-e olyan változás, ami miatt újra kell rendeznie. Van egy pár módszer ennek kezelésére: `redrawControl()` és `isControlInvalid()`. Egy példa: +A [Control |components] osztály minden objektuma (beleértve magát a Presentert is) nyilvántartást vezet arról, hogy történtek-e olyan változások, amelyek miatt újra kell rajzolni. Erre a célra a `redrawControl()` metódus szolgál. ```php public function handleLogin(string $user): void { - // Az objektumot újra kell renderelni, miután a felhasználó bejelentkezett. + // a bejelentkezés után újra kell rajzolni a vonatkozó részt $this->redrawControl(); - // ... + //... } ``` -A Nette azonban még finomabb felbontást kínál, mint az egész komponensek. A felsorolt módszerek opcionális paraméterként elfogadják egy úgynevezett "snippet" nevét. A "snippet" alapvetően a sablonod egy eleme, amelyet erre a célra egy Latte makróval jelöltél meg, erről később. Így lehetőség van arra, hogy egy komponenst arra kérjünk, hogy csak a sablonjának *részeit* rajzolja újra. Ha a teljes komponens érvénytelenítésre kerül, akkor az összes snippetje újrarendezésre kerül. Egy komponens akkor is "érvénytelen", ha bármelyik alkomponense érvénytelen. - -```php -$this->isControlInvalid(); // -> false -$this->redrawControl('header'); // érvényteleníti a 'header' nevű snippet-t. -$this->isControlInvalid('header'); // -> true -$this->isControlInvalid('footer'); // -> false -$this->isControlInvalid(); // -> true, legalább egy snippet érvénytelen. +A Nette lehetővé teszi annak finomabb ellenőrzését is, hogy mit kell átrajzolni. A fent említett módszer argumentumként elfogadhatja a snippet nevét. Így lehetséges a sablonrész szintjén érvényteleníteni (azaz: újrarajzolást kikényszeríteni). Ha a teljes komponens érvénytelenítése megtörténik, akkor annak minden egyes részlete is újrarajzolásra kerül: -$this->redrawControl(); // érvényteleníti az egész komponenst, minden egyes snippet-tel együtt. -$this->isControlInvalid('footer'); // -> true +```php +// érvényteleníti a "fejléc"-részletet. +$this->redrawControl('header'); ``` -A jelzést kapó komponens automatikusan újrarajzolásra kerül. - -A snippet-újrarajzolásnak köszönhetően pontosan tudjuk, hogy mely elemek mely részeit kell újrarajzolni. - - -Tag `{snippet} … {/snippet}` .{toc: Tag snippet} -================================================ - -Az oldal megjelenítése nagyon hasonlóan zajlik, mint egy normál kérésnél: ugyanazok a sablonok töltődnek be stb. A lényeges rész azonban az, hogy a kimenetre nem szánt részek kimaradnak; a többi részhez egy azonosítót kell társítani, és egy JavaScript kezelő számára érthető formátumban kell elküldeni a felhasználónak. - -Szintaxis .[#toc-syntax] ------------------------- +Szemelvények a Latte-ban .[#toc-snippets-in-latte] +-------------------------------------------------- -Ha a sablonban van egy vezérlőelem vagy egy snippet, akkor azt a `{snippet} ... {/snippet}` páros taggel kell becsomagolnunk - ez biztosítja, hogy a renderelt snippet "kivágásra" kerüljön, és elküldjük a böngészőnek. Ez is egy segítőbe fogja beburkolni. `
    ` tagbe (lehet másikat is használni). A következő példában egy `header` nevű snippet van definiálva. Ez akár egy komponens sablonját is jelentheti: +A snippetek használata a Latte-ban rendkívül egyszerű. Ha a sablon egy részét snippetként szeretné definiálni, egyszerűen csomagolja be a `{snippet}` és `{/snippet}` címkékbe: ```latte {snippet header} @@ -139,7 +127,9 @@ Ha a sablonban van egy vezérlőelem vagy egy snippet, akkor azt a `{snippet} .. {/snippet} ``` -A snippet egy más típusú snippet, mint a `
    ` vagy egy további HTML-attribútumokkal ellátott snippet az attribútumváltozat használatával érhető el: +A snippet létrehoz egy elemet `
    ` a HTML-oldalon egy speciálisan generált `id` címmel. A snippet újrarajzolásakor ennek az elemnek a tartalma frissül. Ezért az oldal kezdeti megjelenítésekor az összes snippetet is meg kell jeleníteni, még akkor is, ha azok kezdetben üresek lehetnek. + +A snippet létrehozható egy másik elemmel is, mint a `
    ` n:attribútummal: ```latte
    @@ -148,138 +138,106 @@ A snippet egy más típusú snippet, mint a `
    ` vagy egy további HTML-attri ``` -Dynamic Snippets .[#toc-dynamic-snippets] -========================================= +Snippet területek .[#toc-snippet-areas] +--------------------------------------- -A Nette-ben egy futásidejű paraméter alapján dinamikus névvel ellátott snippeteket is definiálhat. Ez leginkább olyan különböző listákhoz alkalmas, ahol csak egy sort kell megváltoztatnunk, de nem akarjuk vele együtt az egész listát is átvinni. Egy példa erre a következő lenne: +A snippet nevek kifejezések is lehetnek: ```latte -
      - {foreach $list as $id => $item} -
    • {$item} update
    • - {/foreach} -
    +{foreach $items as $id => $item} +
  • {$item}
  • +{/foreach} ``` -Van egy statikus snippet, a `itemsContainer`, amely több dinamikus snippet tartalmaz: `item-0`, `item-1` és így tovább. + `item-0`, `item-1`, stb. Ha közvetlenül érvénytelenítenénk egy dinamikus snippetet (pl. `item-1`), akkor semmi sem rajzolódna újra. A snippetek ugyanis valódi részletként működnek, és csak maguk a snippetek kerülnek közvetlenül megjelenítésre. A sablonban azonban technikailag nincs `item-1` nevű snippet. Ez csak a snippet környező kódjának, jelen esetben a foreach ciklusnak a végrehajtásakor jelenik meg. Ezért a sablon azon részét, amelyet végre kell hajtani, a `{snippetArea}` címkével jelöljük: -Egy dinamikus snippet közvetlenül nem rajzolható újra (a `item-1` újrarajzolásának nincs hatása), a szülő snippetjét (ebben a példában `itemsContainer`) kell újrarajzolni. Ennek hatására a szülő snippet kódja végrehajtódik, de ezután csak az alszippetjei kerülnek elküldésre a böngészőnek. Ha csak az egyik alrészletet szeretné átküldeni, akkor a szülő részlet bemenetét úgy kell módosítania, hogy a többi alrészletet ne generálja. +```latte +
      + {foreach $items as $id => $item} +
    • {$item}
    • + {/foreach} +
    +``` -A fenti példában gondoskodnia kell arról, hogy egy AJAX-kérés esetén csak egy elem kerüljön a `$list` tömbhöz, ezért a `foreach` ciklus csak egy dinamikus snippetet fog kiírni. +És újrarajzoljuk mind az egyes snippetet, mind a teljes átfogó területet: ```php -class HomePresenter extends Nette\Application\UI\Presenter -{ - /** - * This method returns data for the list. - * Usually this would just request the data from a model. - * For the purpose of this example, the data is hard-coded. - */ - private function getTheWholeList(): array - { - return [ - 'First', - 'Second', - 'Third', - ]; - } - - public function renderDefault(): void - { - if (!isset($this->template->list)) { - $this->template->list = $this->getTheWholeList(); - } - } - - public function handleUpdate(int $id): void - { - $this->template->list = $this->isAjax() - ? [] - : $this->getTheWholeList(); - $this->template->list[$id] = 'Updated item'; - $this->redrawControl('itemsContainer'); - } -} +$this->redrawControl('itemsContainer'); +$this->redrawControl('item-1'); ``` +Lényeges annak biztosítása is, hogy a `$items` tömb csak azokat az elemeket tartalmazza, amelyeket újra kell rajzolni. -Snippetek egy belefoglalt sablonban .[#toc-snippets-in-an-included-template] -============================================================================ - -Előfordulhat, hogy a snippet egy olyan sablonban van, amely egy másik sablonból van beépítve. Ebben az esetben a második sablonban a `snippetArea` makróval be kell csomagolnunk a beillesztési kódot, majd újra kell rajzolnunk mind a snippetArea-t, mind a tényleges snippetet. - -A `snippetArea` makró biztosítja, hogy a benne lévő kód végrehajtásra kerül, de csak a tényleges snippet kerül a böngészőhöz a bevont sablonban. +Ha a `{include}` tag segítségével egy másik sablont illesztünk be a fő sablonba, amely szeleteket tartalmaz, akkor a bevont sablont ismét be kell csomagolni a `snippetArea` címkébe, és a szeletet és a területet együttesen érvényteleníteni kell: ```latte -{* parent.latte *} -{snippetArea wrapper} - {include 'child.latte'} +{snippetArea include} + {include 'included.latte'} {/snippetArea} ``` + ```latte -{* child.latte *} +{* included.latte *} {snippet item} -... + ... {/snippet} ``` + ```php -$this->redrawControl('wrapper'); +$this->redrawControl('include'); $this->redrawControl('item'); ``` -Dinamikus snippetekkel is kombinálható. +Snippetek az összetevőkben .[#toc-snippets-in-components] +--------------------------------------------------------- -Hozzáadás és törlés .[#toc-adding-and-deleting] -=============================================== - -Ha új elemet adsz hozzá a listához, és érvényteleníted a `itemsContainer` címet, az AJAX-kérés az új elemet is tartalmazó részleteket küldi vissza, de a javascript kezelő nem tudja megjeleníteni azt. Ennek oka, hogy nincs olyan HTML-elem, amely az újonnan létrehozott azonosítóval rendelkezik. - -Ebben az esetben a legegyszerűbb megoldás, ha az egész listát még egy snippetbe csomagoljuk, és az egészet érvénytelenítjük: + [Komponenseken |components] belül is létrehozhat snippeteket, amelyeket a Nette automatikusan átrajzol. Van azonban egy sajátos korlátozás: a snippetek újrarajzolásához paraméterek nélkül hívja meg a `render()` metódust. Így a paraméterek átadása a sablonban nem fog működni: ```latte -{snippet wholeList} -
      - {foreach $list as $id => $item} -
    • {$item} update
    • - {/foreach} -
    -{/snippet} -Add +OK +{control productGrid} + +will not work: +{control productGrid $arg, $arg} +{control productGrid:paginator} ``` + +Felhasználói adatok küldése .[#toc-sending-user-data] +----------------------------------------------------- + +A snippetek mellett bármilyen további adatot is küldhet az ügyfélnek. Egyszerűen írja őket a `payload` objektumba: + ```php -public function handleAdd(): void +public function actionDelete(int $id): void { - $this->template->list = $this->getTheWholeList(); - $this->template->list[] = 'New one'; - $this->redrawControl('wholeList'); + //... + if ($this->isAjax()) { + $this->payload->message = 'Success'; + } } ``` -Ugyanez vonatkozik egy elem törlésére is. Lehetséges lenne üres snippet küldése, de általában a listák lehetnek oldalszámozottak, és bonyolult lenne megvalósítani egy elem törlését és egy másik betöltését (amely korábban a oldalszámozott lista egy másik oldalán volt). - -Paraméterek küldése a komponensnek .[#toc-sending-parameters-to-component] -========================================================================== +Küldési paraméterek .[#toc-sending-parameters] +============================================== Amikor AJAX-kérésen keresztül paramétereket küldünk a komponensnek, legyenek azok jelparaméterek vagy állandó paraméterek, meg kell adnunk a globális nevüket, amely tartalmazza a komponens nevét is. A paraméter teljes nevét a `getParameterId()` metódus adja vissza. ```js -$.getJSON( - {link changeCountBasket!}, - { - {$control->getParameterId('id')}: id, - {$control->getParameterId('count')}: count - } -}); +let url = new URL({link //foo!}); +url.searchParams.set({$control->getParameterId('bar')}, bar); + +fetch(url, { + headers: {'X-Requested-With': 'XMLHttpRequest'}, +}) ``` -És kezelje a módszert s megfelelő paraméterekkel a komponensben. +A komponensben lévő megfelelő paraméterekkel rendelkező handle metódust: ```php -public function handleChangeCountBasket(int $id, int $count): void +public function handleFoo(int $bar): void { - } ``` diff --git a/application/hu/components.texy b/application/hu/components.texy index 410cca3a9e..d418cd212a 100644 --- a/application/hu/components.texy +++ b/application/hu/components.texy @@ -380,7 +380,7 @@ A komponensek mélysége .[#toc-components-in-depth] A komponensek egy Nette alkalmazásban a webalkalmazás újrafelhasználható részei, amelyeket oldalakba ágyazunk be, ez a fejezet témája. Pontosan milyen képességekkel rendelkezik egy ilyen komponens? 1) egy sablonban megjeleníthető. -2) tudja, hogy egy [AJAX-kérés |ajax#invalidation] során melyik részét kell renderelni (snippet) +2) tudja, hogy egy AJAX-kérés során [melyik |ajax#snippets] részét kell megjelenítenie (snippetek). 3) képes az állapotát egy URL-ben tárolni (állandó paraméterek). 4) képes reagálni a felhasználói műveletekre (jelek) 5) hierarchikus struktúrát hoz létre (ahol a gyökér a bemutató) diff --git a/application/it/ajax.texy b/application/it/ajax.texy index e6fd52b425..76658ce100 100644 --- a/application/it/ajax.texy +++ b/application/it/ajax.texy @@ -3,10 +3,10 @@ AJAX e Snippet
    -Le moderne applicazioni web oggi vengono eseguite per metà su un server e per metà in un browser. AJAX è un fattore di unione vitale. Quale supporto offre il Nette Framework? -- invio di frammenti di template (i cosiddetti *snippet*) +Nell'era delle moderne applicazioni web, in cui le funzionalità si estendono spesso tra il server e il browser, AJAX è un elemento di connessione essenziale. Quali opzioni offre Nette Framework in questo ambito? +- invio di parti del modello, i cosiddetti snippet - passaggio di variabili tra PHP e JavaScript -- debug delle applicazioni AJAX +- strumenti per il debug delle richieste AJAX
    @@ -14,29 +14,32 @@ Le moderne applicazioni web oggi vengono eseguite per metà su un server e per m Richiesta AJAX .[#toc-ajax-request] =================================== -Una richiesta AJAX non differisce da una richiesta classica: il presentatore viene chiamato con una vista e dei parametri specifici. Il presentatore può anche decidere come rispondere: può usare la propria routine, che restituisce un frammento di codice HTML (snippet HTML), un documento XML, un oggetto JSON o codice JavaScript. +Una richiesta AJAX fondamentalmente non differisce da una richiesta HTTP classica. Un presentatore viene chiamato con parametri specifici. Spetta al presentatore rispondere alla richiesta: può restituire dati in formato JSON, inviare una parte di codice HTML, un documento XML, ecc. -Sul lato server, una richiesta AJAX può essere rilevata utilizzando il metodo di servizio [che incapsula la richiesta HTTP |http:request] `$httpRequest->isAjax()` (rileva in base all'intestazione HTTP `X-Requested-With`). All'interno del presentatore, è disponibile una scorciatoia sotto forma del metodo `$this->isAjax()`. +Dal lato del browser, si avvia una richiesta AJAX utilizzando la funzione `fetch()`: -Esiste un oggetto pre-elaborato chiamato `payload`, dedicato all'invio di dati al browser in JSON. - -```php -public function actionDelete(int $id): void -{ - if ($this->isAjax()) { - $this->payload->message = 'Success'; - } - // ... -} +```js +fetch(url, { + headers: {'X-Requested-With': 'XMLHttpRequest'}, +}) +.then(response => response.json()) +.then(payload => { + // elaborazione della risposta +}); ``` -Per un controllo completo sull'output JSON, utilizzare il metodo `sendJson` nel presenter. Il metodo termina immediatamente il presentatore e si può fare a meno di un template: +Sul lato server, una richiesta AJAX viene riconosciuta dal metodo `$httpRequest->isAjax()` del servizio [che incapsula la richiesta HTTP |http:request]. Utilizza l'intestazione HTTP `X-Requested-With`, quindi è essenziale inviarla. All'interno del presenter, è possibile utilizzare il metodo `$this->isAjax()`. + +Se si desidera inviare dati in formato JSON, utilizzare il metodo [`sendJson()` |presenters#Sending a response] . Il metodo termina anche l'attività del presentatore. ```php -$this->sendJson(['key' => 'value', /* ... */]); +public function actionExport(): void +{ + $this->sendJson($this->model->getData); +} ``` -Se vogliamo inviare HTML, possiamo impostare un modello speciale per le richieste AJAX: +Se si intende rispondere con un modello speciale progettato per AJAX, si può procedere come segue: ```php public function handleClick($param): void @@ -44,27 +47,37 @@ public function handleClick($param): void if ($this->isAjax()) { $this->template->setFile('path/to/ajax.latte'); } - // ... + //... } ``` +Frammenti .[#toc-snippets] +========================== + +Lo strumento più potente offerto da Nette per collegare il server al client sono gli snippet. Con essi, è possibile trasformare un'applicazione ordinaria in una AJAX con il minimo sforzo e poche righe di codice. L'esempio di Fifteen ne dimostra il funzionamento e il suo codice è disponibile su [GitHub |https://github.com/nette-examples/fifteen]. + +Gli snippet, o ritagli, consentono di aggiornare solo alcune parti della pagina, invece di ricaricare l'intera pagina. Questo è più veloce ed efficiente e offre anche un'esperienza d'uso più confortevole. Gli snippet potrebbero ricordare Hotwire per Ruby on Rails o Symfony UX Turbo. È interessante notare che Nette ha introdotto gli snippet 14 anni prima. + +Come funzionano gli snippet? Quando la pagina viene caricata per la prima volta (una richiesta non-AJAX), viene caricata l'intera pagina, compresi tutti gli snippet. Quando l'utente interagisce con la pagina (ad esempio, fa clic su un pulsante, invia un modulo, ecc.), invece di caricare l'intera pagina, viene effettuata una richiesta AJAX. Il codice del presentatore esegue l'azione e decide quali snippet devono essere aggiornati. Nette esegue il rendering di questi frammenti e li invia sotto forma di array JSON. Il codice di gestione del browser inserisce quindi gli snippet ricevuti nella pagina. Pertanto, viene trasferito solo il codice degli snippet modificati, risparmiando larghezza di banda e velocizzando il caricamento rispetto al trasferimento dell'intero contenuto della pagina. + + Naja .[#toc-naja] -================= +----------------- -La [libreria Naja |https://naja.js.org] è usata per gestire le richieste AJAX sul lato browser. [Installarla |https://naja.js.org/#/guide/01-install-setup-naja] come pacchetto node.js (da usare con Webpack, Rollup, Vite, Parcel e altri): +Per gestire gli snippet sul lato browser, si usa la [libreria Naja |https://naja.js.org]. [Installarla |https://naja.js.org/#/guide/01-install-setup-naja] come pacchetto node.js (da usare con applicazioni come Webpack, Rollup, Vite, Parcel e altre): ```shell npm install naja ``` -... o inserirla direttamente nel modello della pagina: +... o inserirla direttamente nel modello di pagina: ```html ``` -Per creare una richiesta AJAX da un normale link (segnale) o dall'invio di un modulo, è sufficiente contrassegnare il relativo link, modulo o pulsante con la classe `ajax`: +Per rendere un normale link (segnale) o l'invio di un modulo una richiesta AJAX, è sufficiente contrassegnare il rispettivo link, modulo o pulsante con la classe `ajax`: ```html Go @@ -74,64 +87,39 @@ Per creare una richiesta AJAX da un normale link (segnale) o dall'invio di un mo or +
    ``` -Snippet .[#toc-snippets] -======================== - -Esiste uno strumento molto più potente del supporto AJAX integrato: gli snippet. Il loro utilizzo consente di trasformare una normale applicazione in un'applicazione AJAX utilizzando solo poche righe di codice. Il funzionamento è dimostrato nell'esempio di Fifteen, il cui codice è accessibile nella build o su [GitHub |https://github.com/nette-examples/fifteen]. - -Il modo in cui funzionano gli snippet è che l'intera pagina viene trasferita durante la richiesta iniziale (cioè non AJAX) e poi a ogni [sotto-richiesta |components#signal] AJAX (richiesta della stessa vista dello stesso presentatore) viene trasferito solo il codice delle parti modificate nel repository `payload` menzionato in precedenza. - -Gli snippet possono ricordare Hotwire per Ruby on Rails o Symfony UX Turbo, ma Nette li ha ideati quattordici anni prima. +Ridisegno degli snippet .[#toc-redrawing-snippets] +-------------------------------------------------- - -Invalidazione degli Snippet .[#toc-invalidation-of-snippets] -============================================================ - -Ogni discendente della classe [Control |components] (di cui fa parte anche un Presentatore) è in grado di ricordare se durante una richiesta sono state apportate modifiche che richiedono un nuovo rendering. Esistono due metodi per gestire questo aspetto: `redrawControl()` e `isControlInvalid()`. Un esempio: +Ogni oggetto della classe [Control |components] (compreso il Presentatore stesso) registra se sono avvenuti cambiamenti che richiedono il suo ridisegno. A tale scopo viene utilizzato il metodo `redrawControl()`. ```php public function handleLogin(string $user): void { - // L'oggetto deve essere ri-renderizzato dopo che l'utente ha effettuato il login + // dopo l'accesso, è necessario ridisegnare la parte pertinente $this->redrawControl(); - // ... + //... } ``` -Nette offre tuttavia una risoluzione ancora più fine rispetto ai componenti interi. I metodi elencati accettano il nome di un cosiddetto "snippet" come parametro opzionale. Uno "snippet" è fondamentalmente un elemento del modello contrassegnato a tale scopo da una tag di Latte, di cui si parlerà più avanti. In questo modo è possibile chiedere a un componente di ridisegnare solo *parti* del suo modello. Se l'intero componente viene invalidato, tutti i suoi frammenti vengono ridisegnati. Un componente è "invalido" anche se uno qualsiasi dei suoi sottocomponenti è invalido. - -```php -$this->isControlInvalid(); // -> false -$this->redrawControl('header'); // invalida lo snippet denominato 'header' -$this->isControlInvalid('header'); // -> true -$this->isControlInvalid('footer'); // -> false -$this->isControlInvalid(); // -> true, almeno uno snippet non è valido +Nette consente anche un controllo più preciso di ciò che deve essere ridisegnato. Il metodo summenzionato può accettare il nome dello snippet come argomento. In questo modo, è possibile invalidare (cioè forzare un ridisegno) a livello di parte del modello. Se l'intero componente viene invalidato, anche ogni frammento viene ridisegnato: -$this->redrawControl(); // invalida l'intero componente, ogni snippet -$this->isControlInvalid('footer'); // -> true +```php +// invalida lo snippet "header +$this->redrawControl('header'); ``` -Un componente che riceve un segnale viene automaticamente contrassegnato per essere ridisegnato. - -Grazie allo snippet redrawing sappiamo esattamente quali parti di quali elementi devono essere ridisegnate. - - -Tag `{snippet} … {/snippet}` .{toc: Tag snippet} -================================================ -Il rendering della pagina procede in modo molto simile a una normale richiesta: vengono caricati gli stessi template, ecc. La parte fondamentale è, tuttavia, lasciare fuori le parti che non devono raggiungere l'output; le altre parti devono essere associate a un identificatore e inviate all'utente in un formato comprensibile per un gestore JavaScript. +Frammenti in Latte .[#toc-snippets-in-latte] +-------------------------------------------- - -Sintassi .[#toc-syntax] ------------------------ - -Se c'è un controllo o uno snippet nel template, dobbiamo avvolgerlo usando il tag di coppia `{snippet} ... {/snippet}` - che farà in modo che lo snippet reso venga "tagliato" e inviato al browser. Lo racchiuderà anche in un tag di aiuto `
    ` (è possibile utilizzarne uno diverso). Nell'esempio seguente viene definito uno snippet chiamato `header`. Può anche rappresentare il modello di un componente: +L'uso degli snippet in Latte è estremamente semplice. Per definire una parte del modello come snippet, è sufficiente avvolgerla nei tag `{snippet}` e `{/snippet}`: ```latte {snippet header} @@ -139,7 +127,9 @@ Se c'è un controllo o uno snippet nel template, dobbiamo avvolgerlo usando il t {/snippet} ``` -Uno snippet di tipo diverso da `
    ` o uno snippet con attributi HTML aggiuntivi si ottiene utilizzando la variante dell'attributo: +Lo snippet crea un elemento `
    ` nella pagina HTML con un elemento `id` appositamente generato. Quando si ridisegna uno snippet, il contenuto di questo elemento viene aggiornato. Pertanto, quando la pagina viene inizialmente resa, devono essere resi anche tutti gli snippet, anche se inizialmente possono essere vuoti. + +È anche possibile creare uno snippet con un elemento diverso da `
    ` utilizzando l'attributo n:n: ```latte
    @@ -148,138 +138,106 @@ Uno snippet di tipo diverso da `
    ` o uno snippet con attributi HTML aggiunti ``` -Snippet dinamici .[#toc-dynamic-snippets] -========================================= +Aree Snippet .[#toc-snippet-areas] +---------------------------------- -In Nette è possibile definire snippet con un nome dinamico basato su un parametro di runtime. Ciò è particolarmente indicato per vari elenchi in cui è necessario modificare una sola riga, ma non si vuole trasferire l'intero elenco. Un esempio potrebbe essere: +I nomi dei frammenti possono anche essere espressioni: ```latte -
      - {foreach $list as $id => $item} -
    • {$item} update
    • - {/foreach} -
    +{foreach $items as $id => $item} +
  • {$item}
  • +{/foreach} ``` -Esiste uno snippet statico chiamato `itemsContainer`, che contiene diversi snippet dinamici: `item-0`, `item-1` e così via. +In questo modo si otterranno diversi snippet come `item-0`, `item-1`, ecc. Se si invalidasse direttamente uno snippet dinamico (ad esempio, `item-1`), non verrebbe ridisegnato nulla. Il motivo è che gli snippet funzionano come veri e propri estratti e solo essi vengono resi direttamente. Tuttavia, nel template non esiste tecnicamente uno snippet chiamato `item-1`. Emerge solo quando si esegue il codice circostante lo snippet, in questo caso il ciclo foreach. Pertanto, contrassegneremo la parte del template che deve essere eseguita con il tag `{snippetArea}`: -Non è possibile ridisegnare direttamente uno snippet dinamico (il ridisegno di `item-1` non ha alcun effetto), ma è necessario ridisegnare il suo snippet padre (in questo esempio `itemsContainer`). Questo provoca l'esecuzione del codice dello snippet padre, ma poi solo i suoi sotto-snippet vengono inviati al browser. Se si vuole inviare solo uno dei sotto-nippet, è necessario modificare l'input dello snippet padre per non generare gli altri sotto-nippet. +```latte +
      + {foreach $items as $id => $item} +
    • {$item}
    • + {/foreach} +
    +``` -Nell'esempio precedente, bisogna assicurarsi che per una richiesta AJAX venga aggiunto un solo elemento all'array `$list`, quindi il ciclo `foreach` stamperà un solo frammento dinamico. +E ridisegneremo sia il singolo snippet che l'intera area circostante: ```php -class HomePresenter extends Nette\Application\UI\Presenter -{ - /** - * This method returns data for the list. - * Usually this would just request the data from a model. - * For the purpose of this example, the data is hard-coded. - */ - private function getTheWholeList(): array - { - return [ - 'First', - 'Second', - 'Third', - ]; - } - - public function renderDefault(): void - { - if (!isset($this->template->list)) { - $this->template->list = $this->getTheWholeList(); - } - } - - public function handleUpdate(int $id): void - { - $this->template->list = $this->isAjax() - ? [] - : $this->getTheWholeList(); - $this->template->list[$id] = 'Updated item'; - $this->redrawControl('itemsContainer'); - } -} +$this->redrawControl('itemsContainer'); +$this->redrawControl('item-1'); ``` +È inoltre essenziale assicurarsi che l'array `$items` contenga solo gli elementi che devono essere ridisegnati. -Snippet in un template incluso .[#toc-snippets-in-an-included-template] -======================================================================= - -Può accadere che lo snippet si trovi in un template che viene incluso da un template diverso. In questo caso, occorre avvolgere il codice di inclusione nel secondo template con la tag `snippetArea`, quindi ridisegnare sia la snippetArea che lo snippet vero e proprio. - -La tag `snippetArea` assicura che il codice all'interno venga eseguito, ma che al browser venga inviato solo lo snippet effettivo nel modello incluso. +Quando si inserisce un altro modello in quello principale usando il tag `{include}`, che ha degli snippet, è necessario avvolgere nuovamente il modello incluso in un `snippetArea` e invalidare sia lo snippet che l'area insieme: ```latte -{* parent.latte *} -{snippetArea wrapper} - {include 'child.latte'} +{snippetArea include} + {include 'included.latte'} {/snippetArea} ``` + ```latte -{* child.latte *} +{* incluso.latte *} {snippet item} -... + ... {/snippet} ``` + ```php -$this->redrawControl('wrapper'); +$this->redrawControl('include'); $this->redrawControl('item'); ``` -Si può anche combinare con gli snippet dinamici. - -Aggiunta e cancellazione .[#toc-adding-and-deleting] -==================================================== +Snippet nei componenti .[#toc-snippets-in-components] +----------------------------------------------------- -Se si aggiunge un nuovo elemento all'elenco e si invalida `itemsContainer`, la richiesta AJAX restituisce gli snippet che includono il nuovo elemento, ma il gestore javascript non sarà in grado di renderlo. Questo perché non esiste un elemento HTML con l'ID appena creato. - -In questo caso, il modo più semplice è avvolgere l'intero elenco in un altro frammento e invalidare il tutto: +È possibile creare snippet all'interno dei [componenti |components] e Nette li ridisegna automaticamente. Tuttavia, c'è una limitazione specifica: per ridisegnare gli snippet, viene chiamato il metodo `render()` senza alcun parametro. Pertanto, il passaggio di parametri nel modello non funziona: ```latte -{snippet wholeList} -
      - {foreach $list as $id => $item} -
    • {$item} update
    • - {/foreach} -
    -{/snippet} -Add +OK +{control productGrid} + +will not work: +{control productGrid $arg, $arg} +{control productGrid:paginator} ``` + +Invio di dati utente .[#toc-sending-user-data] +---------------------------------------------- + +Oltre agli snippet, è possibile inviare qualsiasi altro dato al client. È sufficiente scriverli nell'oggetto `payload`: + ```php -public function handleAdd(): void +public function actionDelete(int $id): void { - $this->template->list = $this->getTheWholeList(); - $this->template->list[] = 'New one'; - $this->redrawControl('wholeList'); + //... + if ($this->isAjax()) { + $this->payload->message = 'Success'; + } } ``` -Lo stesso vale per la cancellazione di un elemento. Sarebbe possibile inviare uno snippet vuoto, ma di solito gli elenchi possono essere paginati e sarebbe complicato implementare la cancellazione di un elemento e il caricamento di un altro (che si trovava in una pagina diversa dell'elenco paginato). - -Invio di parametri al componente .[#toc-sending-parameters-to-component] -======================================================================== +Parametri di invio .[#toc-sending-parameters] +============================================= Quando si inviano parametri al componente tramite una richiesta AJAX, sia che si tratti di parametri di segnale che di parametri persistenti, occorre fornire il loro nome globale, che contiene anche il nome del componente. Il nome completo del parametro restituisce il metodo `getParameterId()`. ```js -$.getJSON( - {link changeCountBasket!}, - { - {$control->getParameterId('id')}: id, - {$control->getParameterId('count')}: count - } -}); +let url = new URL({link //foo!}); +url.searchParams.set({$control->getParameterId('bar')}, bar); + +fetch(url, { + headers: {'X-Requested-With': 'XMLHttpRequest'}, +}) ``` -E gestire il metodo con i parametri corrispondenti nel componente. +Un metodo handle con i parametri corrispondenti nel componente: ```php -public function handleChangeCountBasket(int $id, int $count): void +public function handleFoo(int $bar): void { - } ``` diff --git a/application/it/components.texy b/application/it/components.texy index ad8d123bb0..5bd93e7940 100644 --- a/application/it/components.texy +++ b/application/it/components.texy @@ -380,7 +380,7 @@ Componenti in profondità .[#toc-components-in-depth] I componenti di un'applicazione Nette sono le parti riutilizzabili di un'applicazione Web che vengono incorporate nelle pagine, argomento di questo capitolo. Quali sono esattamente le funzionalità di un componente? 1) è renderizzabile in un modello -2) sa quale parte di sé rendere durante una [richiesta AJAX |ajax#invalidation] (snippet) +2) sa [quale parte di se stesso |ajax#snippets] rendere durante una richiesta AJAX (snippet) 3) ha la capacità di memorizzare il proprio stato in un URL (parametri persistenti) 4) ha la capacità di rispondere alle azioni dell'utente (segnali) 5) crea una struttura gerarchica (dove la radice è il presenter) diff --git a/application/pl/ajax.texy b/application/pl/ajax.texy index 6dbade07b9..e38121342e 100644 --- a/application/pl/ajax.texy +++ b/application/pl/ajax.texy @@ -1,12 +1,12 @@ -AJAX i snippety -*************** +AJAX i fragmenty +****************
    -Nowoczesne aplikacje internetowe działają dziś w połowie na serwerze, w połowie w przeglądarce. AJAX jest kluczowym elementem łączącym. Jakie wsparcie oferuje Nette Framework? -- Wysyłanie fragmentów szablonów -- przekazywanie zmiennych między PHP a JavaScriptem -- debugowanie aplikacji AJAX +W dobie nowoczesnych aplikacji internetowych, w których funkcjonalność często rozciąga się między serwerem a przeglądarką, AJAX jest niezbędnym elementem łączącym. Jakie możliwości w tym zakresie oferuje Nette Framework? +- wysyłanie części szablonu, tzw. snippetów +- przekazywanie zmiennych między PHP i JavaScript +- narzędzia do debugowania żądań AJAX
    @@ -14,29 +14,32 @@ Nowoczesne aplikacje internetowe działają dziś w połowie na serwerze, w poł Żądanie AJAX .[#toc-ajax-request] ================================= -Żądanie AJAX nie różni się od klasycznego żądania - prezenter jest wywoływany z określonym widokiem i parametrami. Również od prezentera zależy, jak na nie odpowie: może użyć własnej procedury, która zwraca fragment kodu HTML (HTML snippet), dokument XML, obiekt JSON lub kod JavaScript. +Żądanie AJAX zasadniczo nie różni się od klasycznego żądania HTTP. Prezenter jest wywoływany z określonymi parametrami. To od prezentera zależy, jak odpowie na żądanie - może zwrócić dane w formacie JSON, wysłać fragment kodu HTML, dokument XML itp. -Po stronie serwera żądanie AJAX może zostać wykryte za pomocą metody serwisowej [obudowującej żądanie HTTP |http:request] `$httpRequest->isAjax()` (wykrywa na podstawie nagłówka HTTP `X-Requested-With`). Wewnątrz prezentera dostępny jest skrót w postaci metody `$this->isAjax()`. +Po stronie przeglądarki inicjujemy żądanie AJAX za pomocą funkcji `fetch()`: -Aby wysłać dane do przeglądarki w formacie JSON, możesz użyć gotowego obiektu `payload`: - -```php -public function actionDelete(int $id): void -{ - if ($this->isAjax()) { - $this->payload->message = 'Success'; - } - // ... -} +```js +fetch(url, { + headers: {'X-Requested-With': 'XMLHttpRequest'}, +}) +.then(response => response.json()) +.then(payload => { + // przetwarzanie odpowiedzi +}); ``` -Jeśli potrzebujesz pełnej kontroli nad wysłanym JSON, użyj metody `sendJson` w prezenterze. Spowoduje to natychmiastowe zakończenie prezentera i zrezygnowanie z szablonu: +Po stronie serwera żądanie AJAX jest rozpoznawane przez metodę `$httpRequest->isAjax()` usługi [hermetyzującej żądanie HTTP |http:request]. Używa ona nagłówka HTTP `X-Requested-With`, więc jest niezbędna do jego wysłania. W prezenterze można użyć metody `$this->isAjax()`. + +Jeśli chcesz wysłać dane w formacie JSON, użyj metody [`sendJson()` |presenters#Sending a response] . Metoda ta kończy również aktywność prezentera. ```php -$this->sendJson(['key' => 'value', /* ... */]); +public function actionExport(): void +{ + $this->sendJson($this->model->getData); +} ``` -Jeśli chcemy wysłać HTML, możemy wybrać specjalny szablon dla AJAX: +Jeśli planujesz odpowiedzieć za pomocą specjalnego szablonu zaprojektowanego dla AJAX, możesz to zrobić w następujący sposób: ```php public function handleClick($param): void @@ -44,27 +47,37 @@ public function handleClick($param): void if ($this->isAjax()) { $this->template->setFile('path/to/ajax.latte'); } - // ... + //... } ``` +Fragmenty .[#toc-snippets] +========================== + +Najpotężniejszym narzędziem oferowanym przez Nette do łączenia serwera z klientem są snippety. Dzięki nim można przekształcić zwykłą aplikację w aplikację AJAX przy minimalnym wysiłku i kilku linijkach kodu. Przykład Fifteen pokazuje, jak to wszystko działa, a jego kod można znaleźć na [GitHubie |https://github.com/nette-examples/fifteen]. + +Snippety lub wycinki pozwalają aktualizować tylko części strony, zamiast przeładowywać całą stronę. Jest to szybsze i bardziej wydajne, a także zapewnia wygodniejsze wrażenia użytkownika. Snippety mogą przypominać Hotwire dla Ruby on Rails lub Symfony UX Turbo. Co ciekawe, Nette wprowadziło snippety 14 lat wcześniej. + +Jak działają snippety? Kiedy strona jest ładowana po raz pierwszy (żądanie inne niż AJAX), ładowana jest cała strona, w tym wszystkie snippety. Gdy użytkownik wchodzi w interakcję ze stroną (np. klika przycisk, przesyła formularz itp.), zamiast ładowania całej strony, wykonywane jest żądanie AJAX. Kod w prezenterze wykonuje akcję i decyduje, które fragmenty wymagają aktualizacji. Nette renderuje te fragmenty i wysyła je w postaci tablicy JSON. Kod obsługi w przeglądarce wstawia następnie otrzymane fragmenty z powrotem na stronę. W związku z tym przesyłany jest tylko kod zmienionych fragmentów, co oszczędza przepustowość i przyspiesza ładowanie w porównaniu do przesyłania całej zawartości strony. + + Naja .[#toc-naja] -================= +----------------- -[Biblioteka Naja |https://naja.js.org] służy do obsługi żądań AJAX po stronie przeglądarki. [Zainstaluj |https://naja.js.org/#/guide/01-install-setup-naja] go jako pakiet node.js (do użytku z Webpack, Rollup, Vite, Parcel i innych): +Do obsługi snippetów po stronie przeglądarki używana jest [biblioteka Na |https://naja.js.org] ja. Należy [ją zainstal |https://naja.js.org/#/guide/01-install-setup-naja] ować jako pakiet node.js (do użytku z aplikacjami takimi jak Webpack, Rollup, Vite, Parcel i innymi): ```shell npm install naja ``` -...lub osadzić bezpośrednio w szablonie strony: +... lub wstawić ją bezpośrednio do szablonu strony: ```html ``` -Aby utworzyć żądanie AJAX ze zwykłego linku (sygnału) lub submitu formularza, wystarczy oznaczyć odpowiedni link, formularz lub przycisk klasą `ajax`: +Aby uczynić zwykły link (sygnał) lub przesłanie formularza żądaniem AJAX, wystarczy oznaczyć odpowiedni link, formularz lub przycisk klasą `ajax`: ```html Go @@ -74,64 +87,39 @@ Aby utworzyć żądanie AJAX ze zwykłego linku (sygnału) lub submitu formularz or +
    ``` -Snippets -======== - -Znacznie potężniejszym narzędziem jest wbudowana obsługa snippetów AJAX. Dzięki niemu można zamienić zwykłą aplikację w AJAXową za pomocą zaledwie kilku linijek kodu. Przykład Fifteen, którego kod można znaleźć na [GitHubie |https://github.com/nette-examples/fifteen], demonstruje jak to działa. - -Działanie snippetów polega na tym, że na początkowym (czyli nie-AJAX-owym) żądaniu przenoszona jest cała strona, a następnie na każdym [podżądaniu |components#Signal] AJAX-owym (= żądanie do tego samego prezentera i widoku) przenoszony jest tylko kod zmienionych fragmentów we wspomnianym repozytorium `payload`. Istnieją dwa mechanizmy tego działania: unieważnianie i renderowanie snippetów. - -Snippets mogą przypominać Hotwire dla Ruby on Rails lub Symfony UX Turbo, ale Nette wymyślił je czternaście lat wcześniej. +Przerysowywanie fragmentów .[#toc-redrawing-snippets] +----------------------------------------------------- - -Unieważnianie fragmentów .[#toc-invalidation-of-snippets] -========================================================= - -Każdy obiekt klasy [Control |components] (którą jest sam Presenter) potrafi zapamiętać, czy w sygnale zaszły zmiany wymagające jego przerysowania. Służy do tego para metod `redrawControl()` i `isControlInvalid()`. Przykład: +Każdy obiekt klasy [Control |components] (w tym sam Presenter) przechowuje informacje o tym, czy wystąpiły zmiany, które wymagają jego przerysowania. W tym celu wykorzystywana jest metoda `redrawControl()`. ```php public function handleLogin(string $user): void { - // po zalogowaniu się użytkownika obiekt musi zostać przerysowany + // po zalogowaniu konieczne jest przerysowanie odpowiedniego fragmentu $this->redrawControl(); - // ... + //... } ``` -Nette oferuje jednak jeszcze dokładniejszą rozdzielczość niż na poziomie komponentów. Metody te mogą przyjąć jako argument nazwę "snippet", czyli wycinka. Możliwe jest więc unieważnienie (czyli wymuszenie przerysowania) na poziomie tych wycinków (każdy obiekt może mieć dowolną liczbę wycinków). Jeśli cały komponent zostanie unieważniony, każdy wycinek zostanie przerysowany. Komponent jest "unieważniony" nawet jeśli podkomponent jest unieważniony. - -```php -$this->isControlInvalid(); // -> false -$this->redrawControl('header'); // unieważnia snippet 'header' -$this->isControlInvalid('header'); // -> true -$this->isControlInvalid('footer'); // -> false -$this->isControlInvalid(); // -> prawda, przynajmniej jeden fragment jest nieprawidłowy +Nette pozwala również na dokładniejszą kontrolę tego, co wymaga przerysowania. Wspomniana metoda może przyjąć nazwę fragmentu jako argument. W ten sposób możliwe jest unieważnienie (czyli wymuszenie przerysowania) na poziomie części szablonu. Jeśli cały komponent zostanie unieważniony, każdy jego fragment zostanie również przerysowany: -$this->redrawControl(); // unieważnia cały komponent, każdy fragment -$this->isControlInvalid('footer'); // -> true +```php +// unieważnia fragment "nagłówka +$this->redrawControl('header'); ``` -Komponent, który otrzymuje sygnał, jest automatycznie oznaczany jako wyłączony. - -Unieważniając snippety, wiemy dokładnie, które części których elementów będą musiały zostać przerysowane. - - -Tagi `{snippet} … {/snippet}` .{toc: Tag snippet} -================================================= -Renderowanie strony jest bardzo podobne do normalnego żądania: ładowane są te same szablony itp. Ważne jest jednak pominięcie części, które nie powinny być wyprowadzane; pozostałe części są przypisywane do identyfikatora i wysyłane do użytkownika w formacie zrozumiałym dla JavaScript handler. +Snippety w Latte .[#toc-snippets-in-latte] +------------------------------------------ - -Składnia .[#toc-syntax] ------------------------ - -Jeśli wewnątrz szablonu znajduje się kontrolka lub snippet, musimy owinąć go znacznikiem `{snippet} ... {/snippet}` para - zapewniają one wycięcie wyrenderowanego snippetu i wysłanie go do przeglądarki. Zawija go również za pomocą tagu pomocniczego `
    ` z wygenerowanym `id`. W powyższym przykładzie snippet nosi nazwę `header` i może również reprezentować np. szablon kontrolny: +Używanie snippetów w Latte jest niezwykle proste. Aby zdefiniować część szablonu jako snippet, wystarczy zawinąć go w znaczniki `{snippet}` i `{/snippet}`: ```latte {snippet header} @@ -139,7 +127,9 @@ Jeśli wewnątrz szablonu znajduje się kontrolka lub snippet, musimy owinąć g {/snippet} ``` -Fragment o typie innym niż `
    ` lub snippet z dodatkowymi atrybutami HTML uzyskuje się poprzez zastosowanie wariantu atrybutów: +Snippet tworzy element `
    ` na stronie HTML ze specjalnie wygenerowanym `id`. Podczas przerysowywania fragmentu zawartość tego elementu jest aktualizowana. Dlatego też, gdy strona jest początkowo renderowana, wszystkie snippety muszą być również renderowane, nawet jeśli początkowo mogą być puste. + +Można również utworzyć snippet z elementem innym niż `
    ` używając atrybutu n:attribute: ```latte
    @@ -148,138 +138,106 @@ Fragment o typie innym niż `
    ` lub snippet z dodatkowymi atrybutami HTML uz ``` -Dynamiczne fragmenty .[#toc-dynamic-snippets] -============================================= +Obszary wycinków .[#toc-snippet-areas] +-------------------------------------- -Nette pozwala również na stosowanie snippetów, których nazwa jest tworzona w czasie biegu - czyli dynamicznie. Jest to przydatne w przypadku różnych list, gdzie przy zmianie jednego wiersza nie chcemy AJAXować całej listy, a jedynie sam wiersz. Przykład: +Nazwy fragmentów mogą być również wyrażeniami: ```latte -
      - {foreach $list as $id => $item} -
    • {$item} update
    • - {/foreach} -
    +{foreach $items as $id => $item} +
  • {$item}
  • +{/foreach} ``` -Mamy tu statyczny snippet `itemsContainer`, zawierający kilka dynamicznych snippetów `item-0`, `item-1` itd. +W ten sposób otrzymamy kilka snippetów, takich jak `item-0`, `item-1`, itd. Gdybyśmy bezpośrednio unieważnili dynamiczny snippet (np. `item-1`), nic nie zostałoby przerysowane. Powodem jest to, że snippety działają jako prawdziwe fragmenty i tylko one są renderowane bezpośrednio. Jednak w szablonie nie ma technicznie snippetu o nazwie `item-1`. Pojawia się on dopiero podczas wykonywania otaczającego kodu snippetu, w tym przypadku pętli foreach. Dlatego część szablonu, która musi zostać wykonana, oznaczymy tagiem `{snippetArea}`: -Nie można bezpośrednio unieważnić dynamicznych snippetów (unieważnienie `item-1` nic nie daje), trzeba unieważnić ich nadrzędny statyczny snippet (tutaj snippet `itemsContainer`). Wówczas cały kod kontenera zostanie wykonany, ale do przeglądarki zostaną wysłane tylko jego podkontenerowe snippety. Jeśli chcesz, aby przeglądarka otrzymała tylko jeden z nich, musisz zmodyfikować dane wejściowe tego kontenera, aby nie generował pozostałych. +```latte +
      + {foreach $items as $id => $item} +
    • {$item}
    • + {/foreach} +
    +``` -W powyższym przykładzie musisz po prostu upewnić się, że gdy wykonasz żądanie ajaxowe, w zmiennej `$list` znajduje się tylko jeden wpis, a zatem, że pętla `foreach` wypełnia tylko jeden dynamiczny snippet: +I przerysujemy zarówno pojedynczy snippet, jak i cały obszar nadrzędny: ```php -class HomePresenter extends Nette\Application\UI\Presenter -{ - /** - * Tato metoda vrací data pro seznam. - * Obvykle se jedná pouze o vyžádání dat z modelu. - * Pro účely tohoto příkladu jsou data zadána natvrdo. - */ - private function getTheWholeList(): array - { - return [ - 'První', - 'Druhý', - 'Třetí', - ]; - } - - public function renderDefault(): void - { - if (!isset($this->template->list)) { - $this->template->list = $this->getTheWholeList(); - } - } - - public function handleUpdate(int $id): void - { - $this->template->list = $this->isAjax() - ? [] - : $this->getTheWholeList(); - $this->template->list[$id] = 'Updated item'; - $this->redrawControl('itemsContainer'); - } -} +$this->redrawControl('itemsContainer'); +$this->redrawControl('item-1'); ``` +Ważne jest również, aby upewnić się, że tablica `$items` zawiera tylko elementy, które powinny zostać przerysowane. -Snippety w dołączonym szablonie .[#toc-snippets-in-an-included-template] -======================================================================== - -Może się zdarzyć, że w jakimś szablonie mamy snippet, który dopiero chcemy włączyć do innego szablonu. W tym przypadku musimy owinąć osadzenie tego szablonu znacznikami `snippetArea`, które następnie unieważniamy wraz z samym snippetem. - -Znaczniki `snippetArea` gwarantują, że kod osadzający szablon zostanie wykonany, ale do przeglądarki zostanie wysłany tylko wycinek z osadzanego szablonu. +Podczas wstawiania innego szablonu do szablonu głównego za pomocą znacznika `{include}`, który zawiera snippety, konieczne jest ponowne zawinięcie dołączonego szablonu w `snippetArea` i unieważnienie zarówno snippetu, jak i obszaru razem: ```latte -{* parent.latte *} -{snippetArea wrapper} -{include 'child.latte'} +{snippetArea include} + {include 'included.latte'} {/snippetArea} ``` + ```latte -{* child.latte *} +{* included.latte *} {snippet item} -... + ... {/snippet} ``` + ```php -$this->redrawControl('wrapper'); +$this->redrawControl('include'); $this->redrawControl('item'); ``` -Takie podejście może być również stosowane w połączeniu z dynamicznymi snippetami. - -Dodawanie i usuwanie .[#toc-adding-and-deleting] -================================================ +Snippety w komponentach .[#toc-snippets-in-components] +------------------------------------------------------ -Jeśli dodasz nowy element i unieważnisz `itemsContainer`, to żądanie AJAX zwróci również nowy snippet, ale handler javascript nie może go nigdzie przypisać. W rzeczywistości na stronie nie ma jeszcze elementu HTML o tym identyfikatorze. - -W takim przypadku najłatwiej jest owinąć całą listę jeszcze jednym snippetem i unieważnić całość: +Możesz tworzyć fragmenty w [komponentach |components], a Nette automatycznie je przerysuje. Istnieje jednak pewne ograniczenie: aby przerysować snippety, Nette wywołuje metodę `render()` bez żadnych parametrów. Zatem przekazywanie parametrów w szablonie nie będzie działać: ```latte -{snippet wholeList} -
      - {foreach $list as $id => $item} -
    • {$item} update
    • - {/foreach} -
    -{/snippet} -Add +OK +{control productGrid} + +will not work: +{control productGrid $arg, $arg} +{control productGrid:paginator} ``` + +Wysyłanie danych użytkownika .[#toc-sending-user-data] +------------------------------------------------------ + +Wraz ze snippetami można wysyłać do klienta dowolne dodatkowe dane. Wystarczy zapisać je w obiekcie `payload`: + ```php -public function handleAdd(): void +public function actionDelete(int $id): void { - $this->template->list = $this->getTheWholeList(); - $this->template->list[] = 'New one'; - $this->redrawControl('wholeList'); + //... + if ($this->isAjax()) { + $this->payload->message = 'Success'; + } } ``` -To samo tyczy się usuwania. Można by jakoś wysłać pusty snippet, ale w praktyce większość list jest paginowana i byłoby to zbyt skomplikowane, aby bardziej ekonomicznie usunąć jeden plus ewentualnie załadować inny (który nie pasował wcześniej). - -Wysyłanie parametrów do komponentu .[#toc-sending-parameters-to-component] -========================================================================== +Wysyłanie parametrów .[#toc-sending-parameters] +=============================================== -Jeśli wysyłamy parametry do komponentu za pomocą żądania AJAX, zarówno parametry sygnałowe, jak i parametry trwałe, musimy określić ich globalną nazwę w żądaniu, które zawiera nazwę komponentu. Pełna nazwa parametru jest zwracana przez metodę `getParameterId()`. +Gdy wysyłamy parametry do komponentu za pośrednictwem żądania AJAX, niezależnie od tego, czy są to parametry sygnału, czy parametry trwałe, musimy podać ich globalną nazwę, która zawiera również nazwę komponentu. Pełną nazwę parametru zwraca metoda `getParameterId()`. ```js -$.getJSON( - {link changeCountBasket!}, - { - {$control->getParameterId('id')}: id, - {$control->getParameterId('count')}: count - } -}); +let url = new URL({link //foo!}); +url.searchParams.set({$control->getParameterId('bar')}, bar); + +fetch(url, { + headers: {'X-Requested-With': 'XMLHttpRequest'}, +}) ``` -Metoda handle z odpowiednimi parametrami w komponencie. +Metoda uchwytu z odpowiednimi parametrami w komponencie: ```php -public function handleChangeCountBasket(int $id, int $count): void +public function handleFoo(int $bar): void { - } ``` diff --git a/application/pl/components.texy b/application/pl/components.texy index 9a279ce4c5..1ae99ccb3e 100644 --- a/application/pl/components.texy +++ b/application/pl/components.texy @@ -380,7 +380,7 @@ Komponenty w głębi .[#toc-advanced-use-of-components] Komponenty w aplikacji Nette to części aplikacji internetowej wielokrotnego użytku, które osadzamy w stronach, co jest tematem tego rozdziału. Jakie dokładnie są możliwości takiego komponentu? 1) Jest renderowalny w szablonie -2) wie, która część siebie ma być renderowana podczas [żądania AJAX |ajax#Invalidation] (snippety) +2) wie [, którą część siebie |ajax#snippets] renderować podczas żądania AJAX (snippets) 3) ma możliwość przechowywania swojego stanu w URL (trwałe parametry) 4) posiada zdolność do reagowania na działania (sygnały) użytkownika 5) tworzy strukturę hierarchiczną (gdzie korzeniem jest prezenter) diff --git a/application/pt/ajax.texy b/application/pt/ajax.texy index 63906ac5e1..7eace28064 100644 --- a/application/pt/ajax.texy +++ b/application/pt/ajax.texy @@ -3,40 +3,43 @@ AJAX & Snippets
    -As aplicações web modernas atualmente rodam metade em um servidor e metade em um navegador. O AJAX é um fator de união vital. Que suporte o Nette Framework oferece? -- envio de fragmentos de modelos (os chamados *snippets*) -- passando variáveis entre PHP e JavaScript -- Depuração de aplicações AJAX +Na era dos aplicativos modernos da Web, em que a funcionalidade geralmente se estende entre o servidor e o navegador, o AJAX é um elemento de conexão essencial. Que opções o Nette Framework oferece nessa área? +- envio de partes do modelo, os chamados snippets +- passagem de variáveis entre PHP e JavaScript +- ferramentas para depuração de solicitações AJAX
    -Solicitação AJAX .[#toc-ajax-request] -===================================== +Solicitação de AJAX .[#toc-ajax-request] +======================================== -Uma solicitação AJAX não difere de uma solicitação clássica - o apresentador é chamado com uma visão e parâmetros específicos. Cabe também ao apresentador como responder a ela: ele pode usar sua própria rotina, que retorna um fragmento de código HTML (HTML snippet), um documento XML, um objeto JSON ou código JavaScript. +Basicamente, uma solicitação AJAX não difere de uma solicitação HTTP clássica. Um apresentador é chamado com parâmetros específicos. Cabe ao apresentador decidir como responder à solicitação: ele pode retornar dados no formato JSON, enviar uma parte do código HTML, um documento XML etc. -No lado do servidor, uma solicitação AJAX pode ser detectada usando o método de serviço [que encapsula a solicitação HTTP |http:request] `$httpRequest->isAjax()` (detecta com base no cabeçalho HTTP `X-Requested-With`). Dentro do apresentador, um atalho está disponível na forma do método `$this->isAjax()`. +No lado do navegador, iniciamos uma solicitação AJAX usando a função `fetch()`: -Há um objeto pré-processado chamado `payload` dedicado ao envio de dados para o navegador no JSON. - -```php -public function actionDelete(int $id): void -{ - if ($this->isAjax()) { - $this->payload->message = 'Success'; - } - // ... -} +```js +fetch(url, { + headers: {'X-Requested-With': 'XMLHttpRequest'}, +}) +.then(response => response.json()) +.then(payload => { + // processamento da resposta +}); ``` -Para um controle total sobre sua saída JSON, utilize o método `sendJson` em seu apresentador. Ele encerra o apresentador imediatamente e você não precisará de um modelo: +No lado do servidor, uma solicitação AJAX é reconhecida pelo método `$httpRequest->isAjax()` do serviço [que encapsula a solicitação HTTP |http:request]. Ele usa o cabeçalho HTTP `X-Requested-With`, portanto, é essencial enviá-lo. No apresentador, você pode usar o método `$this->isAjax()`. + +Se você quiser enviar dados no formato JSON, use o método [`sendJson()` |presenters#Sending a response] método. O método também encerra a atividade do apresentador. ```php -$this->sendJson(['key' => 'value', /* ... */]); +public function actionExport(): void +{ + $this->sendJson($this->model->getData); +} ``` -Se quisermos enviar HTML, podemos definir um modelo especial para pedidos AJAX: +Se você planeja responder com um modelo especial projetado para AJAX, pode fazer isso da seguinte forma: ```php public function handleClick($param): void @@ -44,27 +47,37 @@ public function handleClick($param): void if ($this->isAjax()) { $this->template->setFile('path/to/ajax.latte'); } - // ... + //... } ``` +Trechos .[#toc-snippets] +======================== + +A ferramenta mais poderosa oferecida pela Nette para conectar o servidor com o cliente são os snippets. Com eles, você pode transformar um aplicativo comum em um aplicativo AJAX com o mínimo de esforço e algumas linhas de código. O exemplo Fifteen demonstra como tudo isso funciona, e seu código pode ser encontrado no [GitHub |https://github.com/nette-examples/fifteen]. + +Os snippets, ou recortes, permitem que você atualize apenas partes da página, em vez de recarregar a página inteira. Isso é mais rápido e mais eficiente, além de proporcionar uma experiência de usuário mais confortável. Os snippets podem lembrá-lo do Hotwire para Ruby on Rails ou do Symfony UX Turbo. É interessante notar que a Nette introduziu os snippets 14 anos antes. + +Como os snippets funcionam? Quando a página é carregada pela primeira vez (uma solicitação não AJAX), a página inteira, incluindo todos os snippets, é carregada. Quando o usuário interage com a página (por exemplo, clica em um botão, envia um formulário etc.), em vez de carregar a página inteira, é feita uma solicitação AJAX. O código no apresentador executa a ação e decide quais trechos precisam ser atualizados. A Nette renderiza esses trechos e os envia na forma de uma matriz JSON. O código de manipulação no navegador insere os trechos recebidos de volta na página. Portanto, somente o código dos trechos alterados é transferido, economizando largura de banda e acelerando o carregamento em comparação com a transferência de todo o conteúdo da página. + + Naja .[#toc-naja] -================= +----------------- -A [biblioteca Naja |https://naja.js.org] é utilizada para lidar com pedidos AJAX no lado do navegador. [Instale-a |https://naja.js.org/#/guide/01-install-setup-naja] como um pacote node.js (para usar com Webpack, Rollup, Vite, Parcel e mais): +Para lidar com snippets no navegador, é usada a [biblioteca Naja |https://naja.js.org]. [Instale-a |https://naja.js.org/#/guide/01-install-setup-naja] como um pacote node.js (para uso com aplicativos como Webpack, Rollup, Vite, Parcel e outros): ```shell npm install naja ``` -...ou inseri-lo diretamente no modelo da página: +... ou insira-a diretamente no modelo da página: ```html ``` -Para criar uma solicitação AJAX a partir de um link regular (sinal) ou envio de formulário, basta marcar o link, formulário ou botão relevante com a classe `ajax`: +Para transformar um link comum (sinal) ou o envio de um formulário em uma solicitação AJAX, basta marcar o respectivo link, formulário ou botão com a classe `ajax`: ```html Go @@ -74,64 +87,39 @@ Para criar uma solicitação AJAX a partir de um link regular (sinal) ou envio d or +
    ``` -Snippets .[#toc-snippets] -========================= - -Há uma ferramenta muito mais poderosa de suporte AJAX incorporado - trechos. O uso deles torna possível transformar uma aplicação regular em AJAX, utilizando apenas algumas linhas de código. Como tudo funciona é demonstrado no exemplo dos Quinze, cujo código também é acessível no build ou no [GitHub |https://github.com/nette-examples/fifteen]. - -A forma como os trechos funcionam é que a página inteira é transferida durante a solicitação inicial (isto é, não-AJAX) e depois com cada [sub solicitação |components#signal] AJAX (solicitação da mesma visão do mesmo apresentador) apenas o código das partes alteradas é transferido no repositório `payload` mencionado anteriormente. - -Snippets podem lembrá-lo da Hotwire para Ruby on Rails ou Symfony UX Turbo, mas a Nette surgiu com eles catorze anos antes. +Redesenho de snippets .[#toc-redrawing-snippets] +------------------------------------------------ - -Invalidação de Snippets .[#toc-invalidation-of-snippets] -======================================================== - -Cada descendente do [Controle de |components] Classe (que um Apresentador também é) é capaz de lembrar se houve alguma mudança durante um pedido que requeira sua reapresentação. Há um par de métodos para lidar com isso: `redrawControl()` e `isControlInvalid()`. Um exemplo: +Todos os objetos da classe [Control |components] (inclusive o próprio Presenter) mantêm um registro da ocorrência de alterações que exijam o redesenho. O método `redrawControl()` é usado para essa finalidade. ```php public function handleLogin(string $user): void { - // O objeto tem de ser restituído após o usuário ter feito o login + // depois de fazer login, é necessário redesenhar a parte relevante $this->redrawControl(); - // ... + //... } ``` -A Nette, entretanto, oferece uma resolução ainda mais fina do que os componentes inteiros. Os métodos listados aceitam o nome do chamado "snippet" como um parâmetro opcional. Um "snippet" é basicamente um elemento em seu modelo marcado para esse fim por uma tag Latte, mais sobre isso depois. Assim, é possível pedir a um componente para redesenhar apenas *partes* de seu gabarito. Se o componente inteiro for invalidado, então todos os seus trechos serão restituídos. Um componente é "inválido" também se qualquer um de seus subcomponentes for inválido. - -```php -$this->isControlInvalid(); // -> false -$this->redrawControl('header'); // invalida o snippet chamado 'header'. -$this->isControlInvalid('header'); // -> true -$this->isControlInvalid('footer'); // -> false -$this->isControlInvalid(); // -> true, at least one snippet is invalid +O Nette também permite um controle mais preciso do que precisa ser redesenhado. O método mencionado acima pode usar o nome do snippet como argumento. Assim, é possível invalidar (ou seja, forçar um redesenho) no nível da parte do modelo. Se o componente inteiro for invalidado, todos os trechos dele também serão redesenhados: -$this->redrawControl(); // invalida todo o componente, todos os snippet -$this->isControlInvalid('footer'); // -> true +```php +// invalida o trecho de "cabeçalho +$this->redrawControl('header'); ``` -Um componente que recebe um sinal é automaticamente marcado para ser redesenhado. - -Graças ao desenho de snippet, sabemos exatamente quais partes de quais elementos devem ser novamente entregues. - - -Tag `{snippet} … {/snippet}` .{toc: Tag snippet} -================================================ -A renderização da página procede de forma muito semelhante a um pedido regular: os mesmos modelos são carregados, etc. A parte vital é, no entanto, deixar de fora as partes que não devem chegar à saída; as outras partes devem ser associadas a um identificador e enviadas ao usuário em um formato compreensível para um manipulador de JavaScript. +Snippets em Latte .[#toc-snippets-in-latte] +------------------------------------------- - -Sintaxe .[#toc-syntax] ----------------------- - -Se houver um controle ou um snippet no modelo, temos que embrulhá-lo usando a tag do par `{snippet} ... {/snippet}` - ele assegurará que o snippet renderizado será "cortado" e enviado para o navegador. Ele também o anexará em um helper `
    ` (é possível utilizar uma etiqueta diferente). No exemplo a seguir, um trecho chamado `header` está definido. Ele pode também representar o modelo de um componente: +Usar snippets no Latte é extremamente fácil. Para definir uma parte do modelo como um snippet, basta envolvê-la nas tags `{snippet}` e `{/snippet}`: ```latte {snippet header} @@ -139,7 +127,9 @@ Se houver um controle ou um snippet no modelo, temos que embrulhá-lo usando a t {/snippet} ``` -Um fragmento de um tipo diferente de `
    ` ou um snippet com atributos HTML adicionais é obtido usando a variante de atributo: +O snippet cria um elemento `
    ` na página HTML com um `id` especialmente gerado. Ao redesenhar um snippet, o conteúdo desse elemento é atualizado. Portanto, quando a página é renderizada inicialmente, todos os snippets também devem ser renderizados, mesmo que inicialmente estejam vazios. + +Você também pode criar um snippet com um elemento diferente de `
    ` usando um atributo n:: ```latte
    @@ -148,138 +138,106 @@ Um fragmento de um tipo diferente de `
    ` ou um snippet com atributos HTML ad ``` -Snippets dinâmicos .[#toc-dynamic-snippets] -=========================================== +Áreas de snippet .[#toc-snippet-areas] +-------------------------------------- -Em Nette você também pode definir trechos com um nome dinâmico baseado em um parâmetro de tempo de execução. Isto é mais adequado para várias listas onde precisamos mudar apenas uma linha, mas não queremos transferir a lista inteira junto com ela. Um exemplo disto seria: +Os nomes dos snippets também podem ser expressões: ```latte -
      - {foreach $list as $id => $item} -
    • {$item} update
    • - {/foreach} -
    +{foreach $items as $id => $item} +
  • {$item}
  • +{/foreach} ``` -Há um trecho estático chamado `itemsContainer`, contendo vários trechos dinâmicos: `item-0`, `item-1` e assim por diante. +Dessa forma, obteremos vários snippets como `item-0`, `item-1`, etc. Se invalidássemos diretamente um snippet dinâmico (por exemplo, `item-1`), nada seria redesenhado. O motivo é que os snippets funcionam como verdadeiros trechos e somente eles são renderizados diretamente. Entretanto, no modelo, não há tecnicamente um trecho chamado `item-1`. Ele só aparece quando se executa o código ao redor do snippet, nesse caso, o loop foreach. Por isso, marcaremos a parte do modelo que precisa ser executada com a tag `{snippetArea}`: -Você não pode redesenhar um trecho dinâmico diretamente (o redesenho de `item-1` não tem efeito), você tem que redesenhar seu trecho pai (neste exemplo `itemsContainer`). Isto faz com que o código do snippet pai seja executado, mas então apenas seus sub-snippets são enviados para o navegador. Se você quiser enviar apenas um dos sub-snippets, você tem que modificar a entrada para que o trecho pai não gere os outros sub-snippets. +```latte +
      + {foreach $items as $id => $item} +
    • {$item}
    • + {/foreach} +
    +``` -No exemplo acima você tem que ter certeza de que para um pedido AJAX apenas um item será adicionado à matriz `$list`, portanto o laço `foreach` imprimirá apenas um trecho dinâmico. +E redesenharemos tanto o snippet individual quanto toda a área abrangente: ```php -class HomePresenter extends Nette\Application\UI\Presenter -{ - /** - * This method returns data for the list. - * Usually this would just request the data from a model. - * For the purpose of this example, the data is hard-coded. - */ - private function getTheWholeList(): array - { - return [ - 'First', - 'Second', - 'Third', - ]; - } - - public function renderDefault(): void - { - if (!isset($this->template->list)) { - $this->template->list = $this->getTheWholeList(); - } - } - - public function handleUpdate(int $id): void - { - $this->template->list = $this->isAjax() - ? [] - : $this->getTheWholeList(); - $this->template->list[$id] = 'Updated item'; - $this->redrawControl('itemsContainer'); - } -} +$this->redrawControl('itemsContainer'); +$this->redrawControl('item-1'); ``` +Também é essencial garantir que a matriz `$items` contenha apenas os itens que devem ser redesenhados. -Snippets em um Modelo Incluído .[#toc-snippets-in-an-included-template] -======================================================================= - -Pode acontecer que o trecho esteja em um modelo que está sendo incluído a partir de um modelo diferente. Nesse caso, precisamos embrulhar o código de inclusão no segundo modelo com a tag `snippetArea`, então redesenhamos tanto o snippetArea quanto o snippet real. - -A tag `snippetArea` assegura que o código interno seja executado, mas apenas o trecho real no modelo incluído é enviado para o navegador. +Ao inserir outro modelo no modelo principal usando a tag `{include}`, que tem snippets, é necessário envolver novamente o modelo incluído em um `snippetArea` e invalidar o snippet e a área juntos: ```latte -{* parent.latte *} -{snippetArea wrapper} - {include 'child.latte'} +{snippetArea include} + {include 'included.latte'} {/snippetArea} ``` + ```latte -{* child.latte *} +{* incluído.latte *} {snippet item} -... + ... {/snippet} ``` + ```php -$this->redrawControl('wrapper'); +$this->redrawControl('include'); $this->redrawControl('item'); ``` -Você também pode combiná-lo com trechos dinâmicos. - -Adicionando e excluindo .[#toc-adding-and-deleting] -=================================================== +Snippets em componentes .[#toc-snippets-in-components] +------------------------------------------------------ -Se você acrescentar um novo item à lista e invalidar `itemsContainer`, o pedido AJAX devolve trechos incluindo o novo, mas o manipulador de javascript não será capaz de renderizá-lo. Isto porque não há nenhum elemento HTML com o ID recém-criado. - -Neste caso, a maneira mais simples é envolver toda a lista em mais um trecho e invalidar tudo isso: +Você pode criar snippets em [componentes |components], e o Nette os redesenha automaticamente. Entretanto, há uma limitação específica: para redesenhar os snippets, ele chama o método `render()` sem nenhum parâmetro. Portanto, a passagem de parâmetros no modelo não funcionará: ```latte -{snippet wholeList} -
      - {foreach $list as $id => $item} -
    • {$item} update
    • - {/foreach} -
    -{/snippet} -Add +OK +{control productGrid} + +will not work: +{control productGrid $arg, $arg} +{control productGrid:paginator} ``` + +Envio de dados do usuário .[#toc-sending-user-data] +--------------------------------------------------- + +Juntamente com os snippets, você pode enviar quaisquer dados adicionais ao cliente. Basta gravá-los no objeto `payload`: + ```php -public function handleAdd(): void +public function actionDelete(int $id): void { - $this->template->list = $this->getTheWholeList(); - $this->template->list[] = 'New one'; - $this->redrawControl('wholeList'); + //... + if ($this->isAjax()) { + $this->payload->message = 'Success'; + } } ``` -O mesmo vale para a eliminação de um item. Seria possível enviar um trecho vazio, mas geralmente as listas podem ser paginadas e seria complicado implementar a exclusão de um item e o carregamento de outro (que costumava estar em uma página diferente da lista paginada). - -Parâmetros de envio para o componente .[#toc-sending-parameters-to-component] -============================================================================= +Parâmetros de envio .[#toc-sending-parameters] +============================================== -Quando enviamos parâmetros para o componente via solicitação AJAX, sejam parâmetros de sinal ou parâmetros persistentes, devemos fornecer seu nome global, que também contém o nome do componente. O nome completo do parâmetro retorna o método `getParameterId()`. +Quando enviamos parâmetros ao componente por meio de solicitação AJAX, sejam eles parâmetros de sinal ou parâmetros persistentes, devemos fornecer seu nome global, que também contém o nome do componente. O nome completo do parâmetro retorna o método `getParameterId()`. ```js -$.getJSON( - {link changeCountBasket!}, - { - {$control->getParameterId('id')}: id, - {$control->getParameterId('count')}: count - } -}); +let url = new URL({link //foo!}); +url.searchParams.set({$control->getParameterId('bar')}, bar); + +fetch(url, { + headers: {'X-Requested-With': 'XMLHttpRequest'}, +}) ``` -E método de manuseio com s parâmetros correspondentes em componente. +Um método handle com os parâmetros correspondentes no componente: ```php -public function handleChangeCountBasket(int $id, int $count): void +public function handleFoo(int $bar): void { - } ``` diff --git a/application/pt/components.texy b/application/pt/components.texy index e8df613355..33a0a01398 100644 --- a/application/pt/components.texy +++ b/application/pt/components.texy @@ -380,7 +380,7 @@ Componentes em profundidade .[#toc-components-in-depth] Os componentes de uma aplicação Nette são as partes reutilizáveis de uma aplicação web que incorporamos nas páginas, que é o tema deste capítulo. Quais são exatamente as capacidades de um componente desse tipo? 1) é renderizável em um modelo -2) ela sabe qual parte de si mesma deve prestar durante um [pedido AJAX |ajax#invalidation] (trechos) +2) ele sabe [qual parte de si mesmo |ajax#snippets] deve ser renderizada durante uma solicitação AJAX (snippets) 3) tem a capacidade de armazenar seu estado em uma URL (parâmetros persistentes) 4) tem a capacidade de responder às ações (sinais) do usuário 5) cria uma estrutura hierárquica (onde a raiz é o apresentador) diff --git a/application/ro/ajax.texy b/application/ro/ajax.texy index ce4963a704..3f20c912bc 100644 --- a/application/ro/ajax.texy +++ b/application/ro/ajax.texy @@ -3,10 +3,10 @@ AJAX & Snippets
    -În prezent, aplicațiile web moderne rulează pe jumătate pe un server și pe jumătate în browser. AJAX este un factor vital de unificare. Ce suport oferă Nette Framework? -- trimiterea de fragmente de șabloane (așa-numitele *snippets*) +În era aplicațiilor web moderne, în care funcționalitatea se întinde adesea între server și browser, AJAX este un element de legătură esențial. Ce opțiuni oferă Nette Framework în acest domeniu? +- trimiterea unor părți din șablon, așa-numitele snippet-uri - transmiterea de variabile între PHP și JavaScript -- depanarea aplicațiilor AJAX +- instrumente de depanare a cererilor AJAX
    @@ -14,29 +14,32 @@ AJAX & Snippets Cerere AJAX .[#toc-ajax-request] ================================ -O cerere AJAX nu diferă de o cerere clasică - prezentatorul este apelat cu o vizualizare și parametri specifici. De asemenea, este la latitudinea prezentatorului cum să răspundă la aceasta: poate utiliza propria rutină, care returnează un fragment de cod HTML (fragment HTML), un document XML, un obiect JSON sau cod JavaScript. +O cerere AJAX nu diferă în mod fundamental de o cerere HTTP clasică. Un prezentator este apelat cu parametri specifici. Depinde de prezentator cum să răspundă la cerere - acesta poate returna date în format JSON, poate trimite o parte din codul HTML, un document XML etc. -Pe partea serverului, o cerere AJAX poate fi detectată cu ajutorul metodei de serviciu care [încapsulează cererea HTTP |http:request] `$httpRequest->isAjax()` (detectează pe baza antetului HTTP `X-Requested-With`). În interiorul prezentatorului, este disponibilă o scurtătură sub forma metodei `$this->isAjax()`. +Pe partea de browser, inițiem o cerere AJAX utilizând funcția `fetch()`: -Există un obiect preprocesat numit `payload` dedicat trimiterii de date către browser în JSON. - -```php -public function actionDelete(int $id): void -{ - if ($this->isAjax()) { - $this->payload->message = 'Success'; - } - // ... -} +```js +fetch(url, { + headers: {'X-Requested-With': 'XMLHttpRequest'}, +}) +.then(response => response.json()) +.then(payload => { + // prelucrarea răspunsului +}); ``` -Pentru un control complet asupra ieșirii JSON, utilizați metoda `sendJson` în prezentator. Aceasta termină imediat presenterul și vă veți descurca fără șablon: +Pe partea serverului, o cerere AJAX este recunoscută de metoda `$httpRequest->isAjax()` a serviciului [care încapsulează cererea HTTP |http:request]. Aceasta utilizează antetul HTTP `X-Requested-With`, deci este esențial să o trimitem. În cadrul prezentatorului, puteți utiliza metoda `$this->isAjax()`. + +Dacă doriți să trimiteți date în format JSON, utilizați metoda [`sendJson()` |presenters#Sending a response] metoda . Metoda încheie, de asemenea, activitatea prezentatorului. ```php -$this->sendJson(['key' => 'value', /* ... */]); +public function actionExport(): void +{ + $this->sendJson($this->model->getData); +} ``` -Dacă dorim să trimitem HTML, putem fie să setăm un șablon special pentru cererile AJAX: +Dacă intenționați să răspundeți cu un șablon special conceput pentru AJAX, puteți face acest lucru după cum urmează: ```php public function handleClick($param): void @@ -44,27 +47,37 @@ public function handleClick($param): void if ($this->isAjax()) { $this->template->setFile('path/to/ajax.latte'); } - // ... + //... } ``` +Fragmente .[#toc-snippets] +========================== + +Cel mai puternic instrument oferit de Nette pentru conectarea serverului cu clientul sunt snippets. Cu ajutorul acestora, puteți transforma o aplicație obișnuită într-una AJAX cu un efort minim și câteva linii de cod. Exemplul Fifteen demonstrează cum funcționează totul, iar codul său poate fi găsit pe [GitHub |https://github.com/nette-examples/fifteen]. + +Snippets, sau clippings, vă permit să actualizați doar părți ale paginii, în loc să reîncărcați întreaga pagină. Acest lucru este mai rapid și mai eficient și oferă, de asemenea, o experiență mai confortabilă pentru utilizator. Snippets s-ar putea să vă amintească de Hotwire pentru Ruby on Rails sau Symfony UX Turbo. Interesant este că Nette a introdus snippets cu 14 ani mai devreme. + +Cum funcționează snippets? Atunci când pagina este încărcată pentru prima dată (o cerere non-AJAX), se încarcă întreaga pagină, inclusiv toate snippet-urile. Atunci când utilizatorul interacționează cu pagina (de exemplu, face clic pe un buton, trimite un formular etc.), în loc să se încarce întreaga pagină, se face o cerere AJAX. Codul din prezentator execută acțiunea și decide ce fragmente trebuie actualizate. Nette redă aceste fragmente și le trimite sub forma unei matrice JSON. Codul de manipulare din browser inserează apoi fragmentele primite înapoi în pagină. Prin urmare, este transferat doar codul fragmentelor modificate, ceea ce permite economisirea lățimii de bandă și accelerarea încărcării în comparație cu transferul întregului conținut al paginii. + + Naja .[#toc-naja] -================= +----------------- - [Librăria Naja |https://naja.js.org] este utilizată pentru a gestiona cererile AJAX din partea browserului. [Instalați-o |https://naja.js.org/#/guide/01-install-setup-naja] ca un pachet node.js (pentru a o utiliza cu Webpack, Rollup, Vite, Parcel și altele): +Pentru a gestiona fragmente de text în browser, se utilizează [biblioteca Naja |https://naja.js.org]. [Instalați-o |https://naja.js.org/#/guide/01-install-setup-naja] ca un pachet node.js (pentru a fi utilizată cu aplicații precum Webpack, Rollup, Vite, Parcel și altele): ```shell npm install naja ``` -...sau inserați-o direct în șablonul de pagină: +... sau inserați-o direct în șablonul de pagină: ```html ``` -Pentru a crea o solicitare AJAX dintr-un link obișnuit (semnal) sau un formular de trimitere, trebuie doar să marcați link-ul, formularul sau butonul respectiv cu clasa `ajax`: +Pentru a transforma un link obișnuit (semnal) sau un formular de trimitere într-o cerere AJAX, este suficient să marcați link-ul, formularul sau butonul respectiv cu clasa `ajax`: ```html Go @@ -74,64 +87,39 @@ Pentru a crea o solicitare AJAX dintr-un link obișnuit (semnal) sau un formular or +
    ``` -Snippets .[#toc-snippets] -========================= - -Există un instrument mult mai puternic de suport AJAX încorporat - snippets. Utilizarea acestora face posibilă transformarea unei aplicații obișnuite într-una AJAX folosind doar câteva linii de cod. Modul în care funcționează totul este demonstrat în exemplul Fifteen, al cărui cod este, de asemenea, accesibil în build sau pe [GitHub |https://github.com/nette-examples/fifteen]. - -Modul în care funcționează snippet-urile este că întreaga pagină este transferată în timpul cererii inițiale (adică non-AJAX) și apoi, la fiecare [subcerere |components#signal] AJAX (cerere a aceleiași vizualizări a aceluiași prezentator), doar codul părților modificate este transferat în depozitul `payload` menționat anterior. - -Snippets vă poate aminti de Hotwire pentru Ruby on Rails sau de Symfony UX Turbo, dar Nette a venit cu ele cu paisprezece ani mai devreme. - +Redesenarea fragmentelor .[#toc-redrawing-snippets] +--------------------------------------------------- -Invalidarea Snippets .[#toc-invalidation-of-snippets] -===================================================== - -Fiecare descendent al clasei [Control |components] (care este, de asemenea, un prezentator) este capabil să își amintească dacă au existat modificări în timpul unei solicitări care să necesite o nouă redare. Există o pereche de metode pentru a gestiona acest lucru: `redrawControl()` și `isControlInvalid()`. Un exemplu: +Fiecare obiect al clasei [Control |components] (inclusiv prezentatorul însuși) păstrează o evidență a modificărilor care au avut loc și care necesită redesenarea sa. Metoda `redrawControl()` este utilizată în acest scop. ```php public function handleLogin(string $user): void { - // Obiectul trebuie să se redea după ce utilizatorul s-a logat + // după logare, este necesar să se redeseneze partea relevantă $this->redrawControl(); - // ... + //... } ``` -Nette oferă însă o rezoluție și mai fină decât componentele întregi. Metodele enumerate acceptă ca parametru opțional numele unui așa-numit "snippet". Un "snippet" este practic un element din șablonul dvs. marcat în acest scop de o etichetă Latte, mai multe detalii în continuare. Astfel, este posibil să cereți unei componente să redeseneze doar *părți* din șablonul său. Dacă întreaga componentă este invalidată, atunci toate "snippet-urile" sale sunt reredimensionate. O componentă este "invalidată" și dacă oricare dintre subcomponentele sale este invalidată. - -```php -$this->isControlInvalid(); // -> fals -$this->redrawControl('header'); // invalidează fragmentul numit "header -$this->isControlInvalid('header'); // -> true -$this->isControlInvalid('footer'); // -> false -$this->isControlInvalid(); // -> true, cel puțin un fragment este invalidat +Nette permite, de asemenea, un control mai fin al elementelor care trebuie redesenate. Metoda menționată mai sus poate primi ca argument numele fragmentului. Astfel, este posibil să se invalideze (adică să se forțeze o redesenare) la nivelul părții de șablon. În cazul în care întreaga componentă este invalidată, fiecare fragment din aceasta este, de asemenea, redesenat: -$this->redrawControl(); // invalidează întreaga componentă, fiecare fragment -$this->isControlInvalid('footer'); // -> true +```php +// invalidează fragmentul de "antet +$this->redrawControl('header'); ``` -O componentă care primește un semnal este marcată automat pentru redesenare. -Mulțumită redimensionării fragmentelor, știm exact ce părți din ce elemente trebuie redimensionate. +Fragmente în Latte .[#toc-snippets-in-latte] +-------------------------------------------- - -Etichetă `{snippet} … {/snippet}` .{toc: Tag snippet} -===================================================== - -Redarea paginii se desfășoară în mod similar cu o cerere obișnuită: sunt încărcate aceleași șabloane etc. Partea vitală este, totuși, să se lase deoparte părțile care nu trebuie să ajungă la ieșire; celelalte părți trebuie asociate cu un identificator și trimise utilizatorului într-un format inteligibil pentru un manipulator JavaScript. - - -Sintaxa .[#toc-syntax] ----------------------- - -Dacă există un control sau un fragment în șablon, trebuie să îl înfășurăm cu ajutorul etichetei `{snippet} ... {/snippet}` - aceasta se va asigura că fragmentul redat va fi "tăiat" și trimis către browser. De asemenea, acesta va fi inclus într-un helper `
    ` (este posibil să se folosească o altă etichetă). În exemplul următor este definit un fragment numit `header`. Acesta poate reprezenta la fel de bine șablonul unei componente: +Utilizarea snippet-urilor în Latte este extrem de ușoară. Pentru a defini o parte a șablonului ca fiind un snippet, este suficient să o înfășurați în etichetele `{snippet}` și `{/snippet}`: ```latte {snippet header} @@ -139,7 +127,9 @@ Dacă există un control sau un fragment în șablon, trebuie să îl înfășur {/snippet} ``` -Un fragment de alt tip decât `
    ` sau un fragment cu atribute HTML suplimentare se obține prin utilizarea variantei de atribut: +Snippet-ul creează un element `
    ` în pagina HTML cu o etichetă special generată `id`. Atunci când se redesenează un fragment, conținutul acestui element este actualizat. Prin urmare, atunci când pagina este redată inițial, toate fragmentele trebuie, de asemenea, redate, chiar dacă acestea pot fi inițial goale. + +De asemenea, puteți crea un fragment cu un alt element decât `
    ` utilizând un atribut n:: ```latte
    @@ -148,138 +138,106 @@ Un fragment de alt tip decât `
    ` sau un fragment cu atribute HTML supliment ``` -Snippets dinamice .[#toc-dynamic-snippets] -========================================== +Zone de fragmente .[#toc-snippet-areas] +--------------------------------------- -În Nette puteți defini, de asemenea, fragmente cu un nume dinamic bazat pe un parametru de execuție. Acest lucru este cel mai potrivit pentru diverse liste în cazul în care trebuie să modificăm doar un singur rând, dar nu dorim să transferăm întreaga listă odată cu el. Un exemplu în acest sens ar fi: +Numele snippet-urilor pot fi, de asemenea, expresii: ```latte -
      - {foreach $list as $id => $item} -
    • {$item} update
    • - {/foreach} -
    +{foreach $items as $id => $item} +
  • {$item}
  • +{/foreach} ``` -Există un fragment static numit `itemsContainer`, care conține mai multe fragmente dinamice: `item-0`, `item-1` și așa mai departe. +În acest fel, vom obține mai multe fragmente precum `item-0`, `item-1`, etc. Dacă ar fi să invalidăm direct un fragment dinamic (de exemplu, `item-1`), nimic nu ar fi redesenat. Motivul este că snippet-urile funcționează ca adevărate extrase și doar ele însele sunt redate direct. Cu toate acestea, în șablon, nu există, din punct de vedere tehnic, un fragment numit `item-1`. Acesta apare doar atunci când se execută codul care înconjoară fragmentul, în acest caz, bucla foreach. Prin urmare, vom marca partea din șablon care trebuie executată cu eticheta `{snippetArea}`: -Nu puteți redesena direct un fragment dinamic (redesenarea lui `item-1` nu are niciun efect), ci trebuie să redesenați fragmentul său părinte (în acest exemplu `itemsContainer`). Acest lucru determină executarea codului snippet-ului părinte, dar apoi doar sub-snippet-urile sale sunt trimise către browser. Dacă doriți să trimiteți doar unul dintre sub-snippet-uri, trebuie să modificați intrarea pentru snippet-ul părinte pentru a nu genera celelalte sub-snippet-uri. +```latte +
      + {foreach $items as $id => $item} +
    • {$item}
    • + {/foreach} +
    +``` -În exemplul de mai sus, trebuie să vă asigurați că, pentru o cerere AJAX, doar un singur element va fi adăugat la matricea `$list`, prin urmare, bucla `foreach` va imprima doar un singur fragment dinamic. +Și vom redesena atât fragmentul individual, cât și întreaga zonă de ansamblu: ```php -class HomePresenter extends Nette\Application\UI\Presenter -{ - /** - * This method returns data for the list. - * Usually this would just request the data from a model. - * For the purpose of this example, the data is hard-coded. - */ - private function getTheWholeList(): array - { - return [ - 'First', - 'Second', - 'Third', - ]; - } - - public function renderDefault(): void - { - if (!isset($this->template->list)) { - $this->template->list = $this->getTheWholeList(); - } - } - - public function handleUpdate(int $id): void - { - $this->template->list = $this->isAjax() - ? [] - : $this->getTheWholeList(); - $this->template->list[$id] = 'Updated item'; - $this->redrawControl('itemsContainer'); - } -} +$this->redrawControl('itemsContainer'); +$this->redrawControl('item-1'); ``` +De asemenea, este esențial să ne asigurăm că matricea `$items` conține doar elementele care trebuie redesenate. -Fragmente într-un șablon inclus .[#toc-snippets-in-an-included-template] -======================================================================== - -Se poate întâmpla ca fragmentul să se afle într-un șablon care este inclus dintr-un alt șablon. În acest caz, trebuie să înfășurăm codul de includere în cel de-al doilea șablon cu eticheta `snippetArea`, apoi redesenăm atât snippetArea, cât și fragmentul propriu-zis. - -Eticheta `snippetArea` asigură că codul din interior este executat, dar numai fragmentul real din șablonul inclus este trimis către browser. +Atunci când se inserează un alt șablon în șablonul principal folosind eticheta `{include}`, care are fragmente, este necesar să se înfășoare din nou șablonul inclus într-un `snippetArea` și să se invalideze atât fragmentul, cât și zona împreună: ```latte -{* parent.latte *} -{snippetArea wrapper} - {include 'child.latte'} +{snippetArea include} + {include 'included.latte'} {/snippetArea} ``` + ```latte -{* copil.latte *} +{* inclus.latte *} {snippet item} -... + ... {/snippet} ``` + ```php -$this->redrawControl('wrapper'); +$this->redrawControl('include'); $this->redrawControl('item'); ``` -De asemenea, îl puteți combina cu snippet-uri dinamice. - - -Adăugarea și ștergerea .[#toc-adding-and-deleting] -================================================== -Dacă adăugați un nou element în listă și invalidați `itemsContainer`, cererea AJAX returnează fragmente, inclusiv pe cel nou, dar gestionarul javascript nu va putea să îl redea. Acest lucru se datorează faptului că nu există un element HTML cu ID-ul nou creat. +Snippets în componente .[#toc-snippets-in-components] +----------------------------------------------------- -În acest caz, cea mai simplă metodă este de a îngloba întreaga listă într-un alt fragment și de a-l invalida pe tot: +Puteți crea fragmente în cadrul [componentelor |components], iar Nette le va redesena automat. Cu toate acestea, există o limitare specifică: pentru a redesena snippets, se apelează metoda `render()` fără niciun parametru. Astfel, trecerea parametrilor în șablon nu va funcționa: ```latte -{snippet wholeList} -
      - {foreach $list as $id => $item} -
    • {$item} update
    • - {/foreach} -
    -{/snippet} -Add +OK +{control productGrid} + +will not work: +{control productGrid $arg, $arg} +{control productGrid:paginator} ``` + +Trimiterea datelor de utilizator .[#toc-sending-user-data] +---------------------------------------------------------- + +Împreună cu fragmente, puteți trimite orice date suplimentare către client. Pur și simplu scrieți-le în obiectul `payload`: + ```php -public function handleAdd(): void +public function actionDelete(int $id): void { - $this->template->list = $this->getTheWholeList(); - $this->template->list[] = 'New one'; - $this->redrawControl('wholeList'); + //... + if ($this->isAjax()) { + $this->payload->message = 'Success'; + } } ``` -Același lucru este valabil și pentru ștergerea unui element. Ar fi posibil să se trimită un fragment gol, dar, de obicei, listele pot fi paginate și ar fi complicat să se implementeze ștergerea unui element și încărcarea altuia (care se afla pe o pagină diferită a listei paginate). +Parametrii de trimitere .[#toc-sending-parameters] +================================================== -Trimiterea parametrilor către componentă .[#toc-sending-parameters-to-component] -================================================================================ - -Atunci când trimitem parametrii către componentă prin intermediul unei cereri AJAX, fie că este vorba de parametri de semnal sau de parametri persistenți, trebuie să furnizăm numele global al acestora, care conține și numele componentei. Numele complet al parametrului returnează metoda `getParameterId()`. +Atunci când trimitem parametrii către componentă prin intermediul unei cereri AJAX, fie că este vorba de parametri de semnal sau de parametri persistenți, trebuie să furnizăm numele lor global, care conține și numele componentei. Numele complet al parametrului returnează metoda `getParameterId()`. ```js -$.getJSON( - {link changeCountBasket!}, - { - {$control->getParameterId('id')}: id, - {$control->getParameterId('count')}: count - } -}); +let url = new URL({link //foo!}); +url.searchParams.set({$control->getParameterId('bar')}, bar); + +fetch(url, { + headers: {'X-Requested-With': 'XMLHttpRequest'}, +}) ``` -Și gestionează metoda cu s parametrii corespunzători în componentă. +O metodă handle cu parametrii corespunzători din componentă: ```php -public function handleChangeCountBasket(int $id, int $count): void +public function handleFoo(int $bar): void { - } ``` diff --git a/application/ro/components.texy b/application/ro/components.texy index 13ee93eb88..90d2c70502 100644 --- a/application/ro/components.texy +++ b/application/ro/components.texy @@ -380,7 +380,7 @@ Componente în profunzime .[#toc-components-in-depth] Componentele într-o aplicație Nette sunt părțile reutilizabile ale unei aplicații web pe care le încorporăm în pagini, care reprezintă subiectul acestui capitol. Care sunt mai exact capacitățile unei astfel de componente? 1) este redabilă într-un șablon -2) știe ce parte din ea însăși trebuie să redea în timpul unei [cereri AJAX |ajax#invalidation] (fragmente) +2) știe [ce parte din el însuși |ajax#snippets] să redea în timpul unei cereri AJAX (fragmente) 3) are capacitatea de a stoca starea sa într-un URL (parametri persistenți) 4) are capacitatea de a răspunde la acțiunile utilizatorului (semnale) 5) creează o structură ierarhică (în care rădăcina este prezentatorul) diff --git a/application/ru/ajax.texy b/application/ru/ajax.texy index 8815f25f16..bed9143e1e 100644 --- a/application/ru/ajax.texy +++ b/application/ru/ajax.texy @@ -3,10 +3,10 @@ AJAX и сниппеты
    -Современные веб-приложения сегодня работают наполовину на сервере, а наполовину в браузере. AJAX является жизненно важным объединяющим фактором. Какую поддержку предлагает фреймворк Nette? -- отправка фрагментов шаблонов (так называемых *сниппетов*) +В эпоху современных веб-приложений, когда функциональность часто разрывается между сервером и браузером, AJAX является необходимым связующим элементом. Какие возможности предлагает Nette Framework в этой области? +- передача частей шаблона, так называемых сниппетов - передача переменных между PHP и JavaScript -- Отладка приложений AJAX +- инструменты для отладки AJAX-запросов
    @@ -14,29 +14,32 @@ AJAX и сниппеты Запрос AJAX .[#toc-ajax-request] ================================ -AJAX-запрос не отличается от классического запроса - к ведущему обращаются с определенным представлением и параметрами. Ведущий также решает, как ответить на него: он может использовать свою собственную процедуру, которая возвращает фрагмент HTML-кода (HTML snippet), XML-документ, JSON-объект или JavaScript-код. +AJAX-запрос принципиально не отличается от классического HTTP-запроса. Вызывается презентатор с определенными параметрами. Как ответить на запрос, зависит от ведущего - он может вернуть данные в формате JSON, отправить часть HTML-кода, XML-документ и т.д. -На стороне сервера AJAX-запрос может быть обнаружен с помощью сервисного метода, [инкапсулирующего HTTP-запрос |http:request] `$httpRequest->isAjax()` (определяет на основе HTTP-заголовка `X-Requested-With`). Внутри презентатора доступен ярлык в виде метода `$this->isAjax()`. +На стороне браузера мы инициируем AJAX-запрос с помощью функции `fetch()`: -Существует предварительно обработанный объект `payload`, предназначенный для отправки данных в браузер в формате JSON. - -```php -public function actionDelete(int $id): void -{ - if ($this->isAjax()) { - $this->payload->message = 'Успешно'; - } - // ... -} +```js +fetch(url, { + headers: {'X-Requested-With': 'XMLHttpRequest'}, +}) +.then(response => response.json()) +.then(payload => { + // обработка ответа +}); ``` -Для полного контроля над выводом JSON используйте метод `sendJson` в презентере. Это немедленно прервет работу презентера, и вы обойдетесь без шаблона: +На стороне сервера AJAX-запрос распознается методом `$httpRequest->isAjax()` сервиса, [инкапсулирующего HTTP-запрос |http:request]. Он использует HTTP-заголовок `X-Requested-With`, поэтому его необходимо отправить. Внутри презентатора можно использовать метод `$this->isAjax()`. + +Если необходимо отправить данные в формате JSON, используйте метод [`sendJson()` |presenters#Sending a response] метод. Метод также завершает работу презентера. ```php -$this->sendJson(['key' => 'value', /* ... */]); +public function actionExport(): void +{ + $this->sendJson($this->model->getData); +} ``` -Если мы хотим отправить HTML, мы можем установить специальный шаблон для AJAX-запросов: +Если вы планируете отвечать с помощью специального шаблона, предназначенного для AJAX, то это можно сделать следующим образом: ```php public function handleClick($param): void @@ -44,27 +47,37 @@ public function handleClick($param): void if ($this->isAjax()) { $this->template->setFile('path/to/ajax.latte'); } - // ... + //... } ``` -Naja -==== +Фрагменты .[#toc-snippets] +========================== + +Наиболее мощным инструментом, предлагаемым Nette для связи сервера с клиентом, являются сниппеты. С их помощью можно превратить обычное приложение в AJAX-приложение, затратив минимум усилий и написав несколько строк кода. Пример Fifteen демонстрирует, как это работает, а его код можно найти на [GitHub |https://github.com/nette-examples/fifteen]. + +Сниппеты, или вырезки, позволяют обновлять только отдельные части страницы, а не перезагружать ее целиком. Это быстрее и эффективнее, а также обеспечивает более комфортную работу пользователя. Возможно, сниппеты напомнят вам Hotwire для Ruby on Rails или Symfony UX Turbo. Интересно, что компания Nette представила сниппеты на 14 лет раньше. + +Как работают сниппеты? При первой загрузке страницы (не-AJAX-запрос) загружается вся страница, включая все сниппеты. Когда пользователь взаимодействует со страницей (например, нажимает кнопку, отправляет форму и т.д.), вместо загрузки всей страницы выполняется AJAX-запрос. Код в презентере выполняет это действие и решает, какие фрагменты необходимо обновить. Nette рендерит эти фрагменты и отправляет их в виде массива JSON. Затем код обработки в браузере вставляет полученные фрагменты обратно на страницу. Таким образом, передается только код измененных фрагментов, что позволяет экономить пропускную способность и ускорять загрузку по сравнению с передачей всего содержимого страницы. + + +Naja .[#toc-naja] +----------------- -[Библиотека Naja |https://naja.js.org] используется для обработки AJAX-запросов на стороне браузера. [Установите |https://naja.js.org/#/guide/01-install-setup-naja] его как пакет node.js (для использования с Webpack, Rollup, Vite, Parcel и другими): +Для работы со сниппетами на стороне браузера используется [библиотека Naja |https://naja.js.org]. [Установите ее |https://naja.js.org/#/guide/01-install-setup-naja] как пакет node.js (для использования с такими приложениями, как Webpack, Rollup, Vite, Parcel и другими): ```shell npm install naja ``` -...или вставить непосредственно в шаблон страницы: +... или вставьте ее непосредственно в шаблон страницы: ```html ``` -Чтобы создать AJAX-запрос из обычной ссылки (сигнала) или отправки формы, просто пометьте соответствующую ссылку, форму или кнопку классом `ajax`: +Чтобы превратить обычную ссылку (сигнал) или отправку формы в AJAX-запрос, достаточно пометить соответствующую ссылку, форму или кнопку классом `ajax`: ```html Go @@ -74,64 +87,39 @@ npm install naja or +
    ``` -Сниппеты -======== - -Однако существует гораздо более мощный инструмент встроенной поддержки AJAX — сниппеты. Их использование позволяет превратить обычное приложение в AJAX-приложение с помощью всего нескольких строк кода. Как всё это работает, показано в примере Fifteen, код которого также доступен в сборке или на [GitHub |https://github.com/nette-examples/fifteen]. - -Принцип работы сниппетов заключается в том, что вся страница передается во время начального (т. е. не-AJAX) запроса и затем с каждым AJAX [subrequest |components#Signal] (запрос того же представления того же презентера) только код измененных частей передается в хранилище `payload`, упомянутое ранее. - -Сниппеты могут напомнить вам Hotwire для Ruby on Rails или Symfony UX Turbo, но Nette придумал их четырнадцатью годами раньше. +Перерисовка фрагментов .[#toc-redrawing-snippets] +------------------------------------------------- - -Инвалидация .[#toc-invalidation-of-snippets] -============================================ - -Каждый потомок класса [Control |components] (которым является и Presenter) способен помнить, были ли какие-либо изменения во время запроса, требующие повторного отображения. Существует несколько способов справиться с этим: `redrawControl()` и `isControlInvalid()`. Пример: +Каждый объект класса [Control |components] (в том числе и сам Presenter) хранит информацию о том, произошли ли изменения, требующие его перерисовки. Для этого используется метод `redrawControl()`. ```php public function handleLogin(string $user): void { - // Объект должен повторно отображаться после того, как пользователь вошел в систему + // после входа в систему необходимо перерисовать соответствующую часть $this->redrawControl(); - // ... + //... } ``` -Однако Nette обеспечивает ещё более тонкое разрешение, чем целые компоненты. Перечисленные методы принимают имя так называемого «фрагмента» в качестве необязательного параметра. «Фрагмет» это, по сути, элемент в вашем шаблоне, помеченный для этой цели макросом Latte, подробнее об этом позже. Таким образом, можно попросить компонент перерисовать только *часть* своего шаблона. Если весь компонент недействителен, то все его фрагменты отображаются заново. Компонент является «недействительным», если любой из его субкомпонентов является недействительным. - -```php -$this->isControlInvalid(); // -> false -$this->redrawControl('header'); // аннулирует фрагмент с именем 'header' -$this->isControlInvalid('header'); // -> true -$this->isControlInvalid('footer'); // -> false -$this->isControlInvalid(); // -> true, по крайней мере один фрагмент недействителен +Nette также позволяет более тонко контролировать, что именно нужно перерисовывать. Упомянутый выше метод может принимать в качестве аргумента имя фрагмента. Таким образом, можно аннулировать (то есть принудительно перерисовать) на уровне части шаблона. Если аннулируется весь компонент, то перерисовывается и каждый его фрагмент: -$this->redrawControl(); // делает недействительным весь компонент, каждый фрагмент -$this->isControlInvalid('footer'); // -> true +```php +// аннулирует фрагмент 'header' +$this->redrawControl('header'); ``` -Компонент, получивший сигнал, автоматически помечается для перерисовки. - -Благодаря перерисовке фрагментов мы точно знаем, какие части каких элементов должны быть перерисованы. - - -Тег `{snippet} … {/snippet}` .{toc: Tag snippet} -================================================ -Рендеринг страницы происходит точно так же, как и при обычном запросе: загружаются одни и те же шаблоны и т. д. Однако самое важное — это не допустить попадания в выходной сигнал тех частей, которые не должны попасть в выходной сигнал; остальные части должны быть связаны с идентификатором и отправлены пользователю в формате, понятном для обработчика JavaScript. +Фрагменты в Latte .[#toc-snippets-in-latte] +------------------------------------------- - -Синтаксис ---------- - -Если в шаблоне есть элемент управления или фрагмент, мы должны обернуть его с помощью парного тега `{snippet} ... {/snippet}` — отрисованный фрагмент будет «вырезан» и отправится в браузер. Он также заключит его в вспомогательный тег `
    ` (можно использовать другой). В следующем примере определен сниппет с именем `header`. Он также может представлять собой шаблон компонента: +Использовать сниппеты в Latte очень просто. Чтобы определить часть шаблона как сниппет, достаточно обернуть ее в теги `{snippet}` и `{/snippet}`: ```latte {snippet header} @@ -139,7 +127,9 @@ $this->isControlInvalid('footer'); // -> true {/snippet} ``` -Если вы хотите создать сниппет с другим содержащим элементом, отличным от `
    `, или добавить пользовательские атрибуты к элементу, вы можете использовать следующее определение: +Сниппет создает элемент `
    ` в HTML-странице со специально сгенерированным `id`. При перерисовке сниппета содержимое этого элемента обновляется. Поэтому при первоначальном рендеринге страницы все сниппеты также должны быть рендерированы, даже если они изначально могут быть пустыми. + +Также можно создать сниппет с элементом, отличным от `
    ` с помощью атрибута n:attribute: ```latte
    @@ -148,138 +138,106 @@ $this->isControlInvalid('footer'); // -> true ``` -Динамические сниппеты -===================== +Области фрагментов .[#toc-snippet-areas] +---------------------------------------- -В Nette вы также можете определить сниппеты с динамическим именем, основанным на параметре времени выполнения. Это наиболее подходит для различных списков, где нам нужно изменить только одну строку, но мы не хотим переносить весь список вместе с ней. Примером этого может быть: +Имена сниппетов также могут быть выражениями: ```latte - +{foreach $items as $id => $item} +
  • {$item}
  • +{/foreach} ``` -Существует один статический сниппет `itemsContainer`, содержащий несколько динамических сниппетов: `пункт-0`, `пункт-1` и так далее. +Таким образом, мы получим несколько фрагментов типа `item-0`, `item-1`, и т.д. Если мы напрямую аннулируем динамический сниппет (например, `item-1`), то ничего не будет перерисовано. Причина в том, что сниппеты работают как настоящие выдержки, и непосредственно отрисовываются только они сами. Однако в шаблоне технически нет фрагмента с именем `item-1`. Он появляется только при выполнении окружающего сниппета кода, в данном случае цикла foreach. Поэтому часть шаблона, которую необходимо выполнить, мы пометим тегом `{snippetArea}`: -Вы не можете перерисовать динамический фрагмент напрямую (перерисовка `item-1` не имеет эффекта), вы должны перерисовать его родительский фрагмент (в данном примере `itemsContainer`). При этом выполняется код родительского сниппета, но браузеру передаются только его вложенные сниппеты. Если вы хотите передать только один из вложенных сниппетов, вам нужно изменить ввод для родительского сниппета, чтобы не генерировать другие вложенные сниппеты. +```latte +
      + {foreach $items as $id => $item} +
    • {$item}
    • + {/foreach} +
    +``` -В приведенном примере необходимо убедиться, что при AJAX-запросе в массив `$list` будет добавлен только один элемент, поэтому цикл `foreach` будет выводить только один динамический фрагмент. +И перерисуем как отдельный фрагмент, так и всю общую область: ```php -class HomePresenter extends Nette\Application\UI\Presenter -{ - /** - * Этот метод возвращает данные для списка. - * Обычно это просто запрос данных из модели. - * Для целей этого примера данные жёстко закодированы. - */ - private function getTheWholeList(): array - { - return [ - 'First', - 'Second', - 'Third', - ]; - } - - public function renderDefault(): void - { - if (!isset($this->template->list)) { - $this->template->list = $this->getTheWholeList(); - } - } - - public function handleUpdate(int $id): void - { - $this->template->list = $this->isAjax() - ? [] - : $this->getTheWholeList(); - $this->template->list[$id] = 'Updated item'; - $this->redrawControl('itemsContainer'); - } -} +$this->redrawControl('itemsContainer'); +$this->redrawControl('item-1'); ``` +Также необходимо убедиться, что массив `$items` содержит только те элементы, которые должны быть перерисованы. -Сниппеты во включенном шаблоне -============================== - -Может случиться так, что сниппет находится в шаблоне, который включается из другого шаблона. В этом случае необходимо обернуть код включения во втором шаблоне макросом `snippetArea`, затем перерисовать как snippetArea, так и сам сниппет. - -Макрос `snippetArea` гарантирует, что код внутри него будет выполнен, но браузеру будет отправлен только фактический фрагмент включенного шаблона. +При вставке другого шаблона в основной с помощью тега `{include}`, содержащего сниппеты, необходимо снова обернуть включаемый шаблон в `snippetArea` и сделать недействительными и сниппет, и область вместе: ```latte -{* parent.latte *} -{snippetArea wrapper} - {include 'child.latte'} +{snippetArea include} + {include 'included.latte'} {/snippetArea} ``` + ```latte -{* child.latte *} +{* included.latte *} {snippet item} -... + ... {/snippet} ``` + ```php -$this->redrawControl('wrapper'); +$this->redrawControl('include'); $this->redrawControl('item'); ``` -Вы также можете сочетать его с динамическими сниппетами. - -Добавление и удаление -===================== +Сниппеты в компонентах .[#toc-snippets-in-components] +----------------------------------------------------- -Если добавить новый элемент в список и аннулировать `itemsContainer`, AJAX-запрос вернет фрагменты, включая новый, но javascript-обработчик не сможет его отобразить. Это происходит потому, что нет HTML-элемента с вновь созданным ID. - -В этом случае самый простой способ — обернуть весь список в ещё один сниппет и признать его недействительным: +Вы можете создавать сниппеты внутри [компонентов |components], и Nette будет автоматически перерисовывать их. Однако есть одно ограничение: для перерисовки сниппетов вызывается метод `render()` без параметров. Таким образом, передача параметров в шаблоне не работает: ```latte -{snippet wholeList} - -{/snippet} -Добавить +OK +{control productGrid} + +will not work: +{control productGrid $arg, $arg} +{control productGrid:paginator} ``` + +Отправка пользовательских данных .[#toc-sending-user-data] +---------------------------------------------------------- + +Наряду со сниппетами можно отправлять клиенту любые дополнительные данные. Для этого достаточно записать их в объект `payload`: + ```php -public function handleAdd(): void +public function actionDelete(int $id): void { - $this->template->list = $this->getTheWholeList(); - $this->template->list[] = 'New one'; - $this->redrawControl('wholeList'); + //... + if ($this->isAjax()) { + $this->payload->message = 'Success'; + } } ``` -То же самое относится и к удалению элемента. Можно было бы отправить пустой сниппет, но обычно списки могут быть постраничными, и было бы сложно реализовать удаление одного элемента и загрузку другого (который раньше находился на другой странице постраничного списка). - -Отправка параметров компоненту -============================== +Параметры отправки .[#toc-sending-parameters] +============================================= -Когда мы отправляем параметры компоненту через AJAX-запрос, будь то сигнальные или постоянные параметры, мы должны предоставить их глобальное имя, которое также содержит имя компонента. Полное имя параметра возвращает метод `getParameterId()`. +Когда мы отправляем в компонент через AJAX-запрос параметры, будь то сигнальные или постоянные, мы должны указать их глобальное имя, которое также содержит имя компонента. Полное имя параметра возвращает метод `getParameterId()`. ```js -$.getJSON( - {link changeCountBasket!}, - { - {$control->getParameterId('id')}: id, - {$control->getParameterId('count')}: count - } -}); +let url = new URL({link //foo!}); +url.searchParams.set({$control->getParameterId('bar')}, bar); + +fetch(url, { + headers: {'X-Requested-With': 'XMLHttpRequest'}, +}) ``` -И обработать метод с соответствующими параметрами в компоненте. +handle метод с соответствующими параметрами в компоненте: ```php -public function handleChangeCountBasket(int $id, int $count): void +public function handleFoo(int $bar): void { - } ``` diff --git a/application/ru/components.texy b/application/ru/components.texy index 65adfeff51..7d3e1e2133 100644 --- a/application/ru/components.texy +++ b/application/ru/components.texy @@ -380,7 +380,7 @@ interface PollControlFactory Компоненты в Nette Application - это многократно используемые части веб-приложения, которые мы встраиваем в страницы, о чем и пойдет речь в этой главе. Каковы возможности такого компонента? 1) он может быть отображен в шаблоне -2) он знает, какую часть себя отображать во время [AJAX-запроса |ajax#invalidation] (сниппеты) +2) он знает [, какую часть себя от |ajax#snippets] рисовывать при AJAX-запросе (сниппеты) 3) он имеет возможность хранить свое состояние в URL (постоянные параметры) 4) имеет возможность реагировать на действия пользователя (сигналы) 5) создает иерархическую структуру (где корнем является ведущий) diff --git a/application/sl/ajax.texy b/application/sl/ajax.texy index 6e285a54ed..bfbc97906b 100644 --- a/application/sl/ajax.texy +++ b/application/sl/ajax.texy @@ -3,10 +3,10 @@ AJAX in sličice
    -Sodobne spletne aplikacije danes tečejo pol na strežniku in pol v brskalniku. AJAX je ključni povezovalni dejavnik. Kakšno podporo ponuja ogrodje Nette? -- pošiljanje fragmentov predlog (tako imenovanih *snippets*) +V dobi sodobnih spletnih aplikacij, kjer je funkcionalnost pogosto razpeta med strežnikom in brskalnikom, je AJAX bistven povezovalni element. Katere možnosti ponuja ogrodje Nette na tem področju? +- pošiljanje delov predloge, tako imenovanih snippets - posredovanje spremenljivk med PHP in JavaScriptom -- razhroščevanje aplikacij AJAX +- orodja za razhroščevanje zahtevkov AJAX
    @@ -14,29 +14,32 @@ Sodobne spletne aplikacije danes tečejo pol na strežniku in pol v brskalniku. Zahteva AJAX .[#toc-ajax-request] ================================= -Zahteva AJAX se ne razlikuje od klasične zahteve - predvajalnik se pokliče z določenim pogledom in parametri. Prav tako je od predstavnika odvisno, kako se bo nanjo odzval: uporabi lahko svojo rutino, ki vrne fragment kode HTML (fragment HTML), dokument XML, objekt JSON ali kodo JavaScript. +Zahteva AJAX se v osnovi ne razlikuje od klasične zahteve HTTP. Predlagatelj se pokliče z določenimi parametri. Od predstavnika je odvisno, kako se bo odzval na zahtevo - lahko vrne podatke v obliki JSON, pošlje del kode HTML, dokument XML itd. -Na strani strežnika je mogoče zahtevo AJAX zaznati s storitveno metodo, ki [enkapsulira zahtevo HTTP |http:request] `$httpRequest->isAjax()` (zazna na podlagi glave HTTP `X-Requested-With`). Znotraj predstavnika je na voljo bližnjica v obliki metode `$this->isAjax()`. +Na strani brskalnika sprožimo zahtevo AJAX s funkcijo `fetch()`: -Na voljo je vnaprej obdelan objekt, imenovan `payload`, namenjen pošiljanju podatkov brskalniku v obliki JSON. - -```php -public function actionDelete(int $id): void -{ - if ($this->isAjax()) { - $this->payload->message = 'Success'; - } - // ... -} +```js +fetch(url, { + headers: {'X-Requested-With': 'XMLHttpRequest'}, +}) +.then(response => response.json()) +.then(payload => { + // obdelava odziva +}); ``` -Za popoln nadzor nad izpisom JSON uporabite metodo `sendJson` v svojem predstavitvenem programu. S tem se takoj zaključi predstavitveni program, vi pa boste opravili brez predloge: +Na strani strežnika zahtevo AJAX prepozna metoda `$httpRequest->isAjax()` storitve, ki [enkapsulira zahtevo HTTP |http:request]. Uporablja glavo HTTP `X-Requested-With`, zato jo je nujno poslati. V predstavitvenem programu lahko uporabite metodo `$this->isAjax()`. + +Če želite poslati podatke v obliki JSON, uporabite metodo [`sendJson()` |presenters#Sending a response] metodo. Metoda tudi zaključi dejavnost predstavitvenega programa. ```php -$this->sendJson(['key' => 'value', /* ... */]); +public function actionExport(): void +{ + $this->sendJson($this->model->getData); +} ``` -Če želimo poslati HTML, lahko nastavimo posebno predlogo za zahteve AJAX: +Če se nameravate odzvati s posebno predlogo, zasnovano za AJAX, lahko to storite na naslednji način: ```php public function handleClick($param): void @@ -44,27 +47,37 @@ public function handleClick($param): void if ($this->isAjax()) { $this->template->setFile('path/to/ajax.latte'); } - // ... + //... } ``` +Utrinki .[#toc-snippets] +======================== + +Najzmogljivejše orodje, ki ga ponuja Nette za povezovanje strežnika z odjemalcem, so snippets. Z njimi lahko navadno aplikacijo spremenite v aplikacijo AJAX z minimalnim naporom in nekaj vrsticami kode. Primer Fifteen prikazuje, kako vse to deluje, njegovo kodo pa lahko najdete na [GitHubu |https://github.com/nette-examples/fifteen]. + +Snippets ali clippings omogočajo posodabljanje samo delov strani, namesto da bi ponovno naložili celotno stran. To je hitrejše in učinkovitejše, poleg tega pa zagotavlja udobnejšo uporabniško izkušnjo. Snippets vas morda spominjajo na Hotwire za Ruby on Rails ali Symfony UX Turbo. Zanimivo pa je, da je Nette snippets predstavil že 14 let prej. + +Kako delujejo odlomki? Ob prvem nalaganju strani (zahteva, ki ni zahteva AJAX) se naloži celotna stran, vključno z vsemi snippets. Ko uporabnik komunicira s stranjo (npr. klikne gumb, odda obrazec itd.), se namesto nalaganja celotne strani izvede zahteva AJAX. Koda v predstavniku izvede dejanje in odloči, katere utrinke je treba posodobiti. Nette te utrinke prikaže in jih pošlje v obliki polja JSON. Obdelovalna koda v brskalniku nato vstavi prejete utrinke nazaj na stran. Zato se prenese samo koda spremenjenih izsekov, kar prihrani pasovno širino in pospeši nalaganje v primerjavi s prenosom celotne vsebine strani. + + Naja .[#toc-naja] -================= +----------------- - [Knjižnica Naja |https://naja.js.org] se uporablja za obdelavo zahtevkov AJAX na strani brskalnika. [Namestite |https://naja.js.org/#/guide/01-install-setup-naja] jo kot paket node.js (za uporabo s programi Webpack, Rollup, Vite, Parcel in drugimi): +Za obdelavo izsekov na strani brskalnika se uporablja [knjižnica Naja |https://naja.js.org]. [Namestite jo |https://naja.js.org/#/guide/01-install-setup-naja] kot paket node.js (za uporabo z aplikacijami, kot so Webpack, Rollup, Vite, Parcel in druge): ```shell npm install naja ``` -...ali pa jo vstavite neposredno v predlogo strani: +... ali jo vstavite neposredno v predlogo strani: ```html ``` -Če želite ustvariti zahtevo AJAX iz običajne povezave (signala) ali oddaje obrazca, preprosto označite ustrezno povezavo, obrazec ali gumb z razredom `ajax`: +Če želite, da običajna povezava (signal) ali oddaja obrazca postane zahteva AJAX, preprosto označite ustrezno povezavo, obrazec ali gumb z razredom `ajax`: ```html Go @@ -74,64 +87,39 @@ npm install naja or +
    ``` -. .[#toc-snippets] -================== - -Obstaja veliko močnejše orodje vgrajene podpore AJAX - snippets. Z njihovo uporabo je mogoče navadno aplikacijo spremeniti v aplikacijo AJAX z uporabo le nekaj vrstic kode. Kako vse to deluje, je prikazano v primeru Fifteen, katerega koda je na voljo tudi v sestavi ali na [GitHubu |https://github.com/nette-examples/fifteen]. - -Snippets delujejo tako, da se med začetno zahtevo (tj. zahtevo brez AJAX-a) prenese celotna stran, nato pa se pri vsaki [podpovprašitvi |components#signal] AJAX-a (zahteva istega pogleda istega predstavnika) v prej omenjeno shrambo `payload` prenese le koda spremenjenih delov. - -Snippets vas morda spominjajo na Hotwire za Ruby on Rails ali Symfony UX Turbo, vendar jih je Nette zasnoval že štirinajst let prej. +Ponovno risanje utrinkov .[#toc-redrawing-snippets] +--------------------------------------------------- - -Neveljavnost nizov (Snippets) .[#toc-invalidation-of-snippets] -============================================================== - -Vsak potomec razreda [Control |components] (kar je tudi Presenter) si lahko zapomni, ali je med zahtevo prišlo do kakšnih sprememb, zaradi katerih je treba ponovno prikazati. Za to obstaja par metod: `redrawControl()` in `isControlInvalid()`. Primer: +Vsak objekt razreda [Control |components] (vključno s samim Presenterjem) beleži, ali so se zgodile spremembe, ki zahtevajo njegovo ponovno izrisovanje. V ta namen se uporablja metoda `redrawControl()`. ```php public function handleLogin(string $user): void { - // Objekt se mora ponovno prikazati, ko se uporabnik prijavi + // po prijavi je treba ponovno narisati ustrezni del $this->redrawControl(); - // ... + //... } ``` -Nette pa ponuja še natančnejšo ločljivost kot celotne komponente. Navedeni metodi kot neobvezni parameter sprejmeta ime tako imenovanega "snippeta". "Snippet" je v bistvu element v vaši predlogi, ki je v ta namen označen z oznako Latte, več o tem pozneje. Tako je mogoče od komponente zahtevati, da na novo nariše samo *delčke* svoje predloge. Če je celotna komponenta razveljavljena, se ponovno izrišejo vse njene sličice. Komponenta je "neveljavna" tudi, če je neveljavna katera koli njena podkomponenta. - -```php -$this->isControlInvalid(); // -> false -$this->redrawControl('header'); // razveljavi odlomek z imenom 'header' -$this->isControlInvalid('header'); // -> true -$this->isControlInvalid('footer'); // -> false -$this->isControlInvalid(); // -> true, vsaj en delček je neveljaven +Nette omogoča tudi natančnejši nadzor nad tem, kaj je treba ponovno narisati. Zgoraj omenjena metoda lahko kot argument sprejme ime izseka. Tako je mogoče razveljaviti (kar pomeni: prisiliti k ponovnemu izrisu) na ravni dela predloge. Če je celotna komponenta razveljavljena, se na novo nariše tudi vsak njen delček: -$this->redrawControl(); // razveljavi celotno komponento, vsak odlomek -$this->isControlInvalid('footer'); // -> true +```php +// razveljavi odlomek 'header' +$this->redrawControl('header'); ``` -Komponenta, ki prejme signal, je samodejno označena za ponovno izrisovanje. - -Zahvaljujoč ponovnemu izrisu snippetov natančno vemo, katere dele katerih elementov je treba ponovno izrisati. - - -Oznaka `{snippet} … {/snippet}` .{toc: Tag snippet} -=================================================== -Prikazovanje strani poteka zelo podobno kot pri običajni zahtevi: naložijo se iste predloge itd. Bistveno pa je, da se izpustijo deli, ki naj ne bi dosegli izpisa; drugi deli se povežejo z identifikatorjem in pošljejo uporabniku v obliki, razumljivi za obdelovalnik JavaScript. +Utrinki v Latte .[#toc-snippets-in-latte] +----------------------------------------- - -Sintaksa .[#toc-syntax] ------------------------ - -Če je v predlogi kontrolni element ali izsek, ga moramo oviti z uporabo oznake `{snippet} ... {/snippet}` pair - ta bo poskrbela, da bo izrisani izsek "izrezan" in poslan brskalniku. Prav tako ga bo zaprla v pomožno vrstico `
    ` (možno je uporabiti tudi drugačno oznako). V naslednjem primeru je opredeljen izsek z imenom `header`. Prav tako lahko predstavlja predlogo komponente: +Uporaba snippetov v Latte je zelo preprosta. Če želite del predloge opredeliti kot izsek, ga preprosto ovijte v oznake `{snippet}` in `{/snippet}`: ```latte {snippet header} @@ -139,7 +127,9 @@ Sintaksa .[#toc-syntax] {/snippet} ``` -Snippet tipa, ki ni `
    ` ali izsek z dodatnimi atributi HTML se doseže z uporabo različice atributa: +Snippet ustvari element `
    ` na strani HTML s posebej ustvarjeno oznako `id`. Pri ponovnem izrisu sličice se vsebina tega elementa posodobi. Zato je treba ob začetnem izrisu strani izrisati tudi vse sličice, čeprav so lahko na začetku prazne. + +Fragment lahko ustvarite tudi z elementom, ki ni `
    ` z uporabo atributa n:: ```latte
    @@ -148,138 +138,106 @@ Snippet tipa, ki ni `
    ` ali izsek z dodatnimi atributi HTML se doseže z upo ``` -Dinamični utrinki .[#toc-dynamic-snippets] -========================================== +Območja sličic .[#toc-snippet-areas] +------------------------------------ -V programu Nette lahko na podlagi parametra v času izvajanja določite tudi dinamično ime snippetov. To je najbolj primerno za različne sezname, kjer moramo spremeniti samo eno vrstico, vendar ne želimo skupaj z njo prenesti celotnega seznama. Primer tega je: +Imena snippetov so lahko tudi izrazi: ```latte -
      - {foreach $list as $id => $item} -
    • {$item} update
    • - {/foreach} -
    +{foreach $items as $id => $item} +
  • {$item}
  • +{/foreach} ``` -Obstaja en statični niz z imenom `itemsContainer`, ki vsebuje več dinamičnih nizov: `item-0`, `item-1` in tako naprej. +Tako bomo dobili več izsekov, kot so `item-0`, `item-1`, itd. Če bi neposredno razveljavili dinamični snippet (npr. `item-1`), se ne bi nič na novo izrisalo. Razlog za to je, da utrinki delujejo kot pravi izvlečki in se neposredno izrisujejo le oni sami. Vendar v predlogi tehnično ni nobenega odlomka z imenom `item-1`. Pojavi se šele ob izvajanju okoliške kode snippeta, v tem primeru zanke foreach. Zato bomo del predloge, ki ga je treba izvesti, označili z oznako `{snippetArea}`: -Dinamičnega utrinka ne morete narisati neposredno (ponovno narisanje `item-1` nima učinka), temveč morate narisati njegov nadrejeni utrinek (v tem primeru `itemsContainer`). To povzroči, da se izvede koda nadrejenega odlomka, vendar se nato brskalniku pošljejo samo njegovi pododlomki. Če želite poslati samo enega od podnapisov, morate spremeniti vnos za nadrejeni odlomek, da ne bo ustvaril drugih podnapisov. +```latte +
      + {foreach $items as $id => $item} +
    • {$item}
    • + {/foreach} +
    +``` -V zgornjem primeru morate poskrbeti, da bo za zahtevo AJAX v polje `$list` dodan samo en element, zato bo zanka `foreach` izpisala samo en dinamični odlomek. +In na novo bomo narisali tako posamezni izsek kot celotno krovno območje: ```php -class HomePresenter extends Nette\Application\UI\Presenter -{ - /** - * This method returns data for the list. - * Usually this would just request the data from a model. - * For the purpose of this example, the data is hard-coded. - */ - private function getTheWholeList(): array - { - return [ - 'First', - 'Second', - 'Third', - ]; - } - - public function renderDefault(): void - { - if (!isset($this->template->list)) { - $this->template->list = $this->getTheWholeList(); - } - } - - public function handleUpdate(int $id): void - { - $this->template->list = $this->isAjax() - ? [] - : $this->getTheWholeList(); - $this->template->list[$id] = 'Updated item'; - $this->redrawControl('itemsContainer'); - } -} +$this->redrawControl('itemsContainer'); +$this->redrawControl('item-1'); ``` +Prav tako je treba zagotoviti, da polje `$items` vsebuje samo elemente, ki jih je treba ponovno narisati. -Utrinki v vključeni predlogi .[#toc-snippets-in-an-included-template] -===================================================================== - -Lahko se zgodi, da je snippet v predlogi, ki je vključena iz druge predloge. V tem primeru moramo vključitveno kodo v drugi predlogi oviti z oznako `snippetArea`, nato pa ponovno narišemo območje snippetArea in dejanski snippet. - -Oznaka `snippetArea` zagotavlja, da se koda v njej izvrši, vendar se brskalniku pošlje le dejanski odlomek iz vključene predloge. +Pri vstavljanju druge predloge v glavno s pomočjo oznake `{include}`, ki ima izseke, je treba vključeno predlogo ponovno zaviti v `snippetArea` in razveljaviti tako izsek kot območje skupaj: ```latte -{* parent.latte *} -{snippetArea wrapper} - {include 'child.latte'} +{snippetArea include} + {include 'included.latte'} {/snippetArea} ``` + ```latte -{* child.latte *} +{* included.latte *} {snippet item} -... + ... {/snippet} ``` + ```php -$this->redrawControl('wrapper'); +$this->redrawControl('include'); $this->redrawControl('item'); ``` -Kombinirate jo lahko tudi z dinamičnimi utrinki. - -Dodajanje in brisanje .[#toc-adding-and-deleting] -================================================= +Utrinki v sestavinah .[#toc-snippets-in-components] +--------------------------------------------------- -Če na seznam dodate nov element in razveljavite `itemsContainer`, zahteva AJAX vrne odlomke, vključno z novim elementom, vendar ga obdelovalnik javascript ne bo mogel prikazati. Razlog za to je, da ni elementa HTML z novo ustvarjenim ID. - -V tem primeru je najpreprostejši način, da celoten seznam zavijete v še en izsek in ga razveljavite: +V [komponentah |components] lahko ustvarite sličice in Nette jih bo samodejno ponovno narisal. Vendar pa obstaja posebna omejitev: za ponovno izrisovanje snippetov je treba poklicati metodo `render()` brez parametrov. Tako posredovanje parametrov v predlogi ne bo delovalo: ```latte -{snippet wholeList} -
      - {foreach $list as $id => $item} -
    • {$item} update
    • - {/foreach} -
    -{/snippet} -Add +OK +{control productGrid} + +will not work: +{control productGrid $arg, $arg} +{control productGrid:paginator} ``` + +Pošiljanje uporabniških podatkov .[#toc-sending-user-data] +---------------------------------------------------------- + +Skupaj z odlomki lahko odjemalcu pošljete vse dodatne podatke. Preprosto jih zapišite v objekt `payload`: + ```php -public function handleAdd(): void +public function actionDelete(int $id): void { - $this->template->list = $this->getTheWholeList(); - $this->template->list[] = 'New one'; - $this->redrawControl('wholeList'); + //... + if ($this->isAjax()) { + $this->payload->message = 'Success'; + } } ``` -Enako velja za brisanje elementa. Možno bi bilo poslati prazen snippet, vendar so običajno seznami lahko oštevilčeni in bi bilo zapleteno izvesti brisanje enega elementa in nalaganje drugega (ki je bil prej na drugi strani oštevilčenega seznama). - -Pošiljanje parametrov sestavini .[#toc-sending-parameters-to-component] -======================================================================= +Pošiljanje parametrov .[#toc-sending-parameters] +================================================ -Ko komponenti prek zahteve AJAX pošiljamo parametre, bodisi signalne bodisi trajne, moramo navesti njihovo globalno ime, ki vsebuje tudi ime komponente. Polno ime parametra vrne metoda `getParameterId()`. +Ko komponenti z zahtevo AJAX pošiljamo parametre, bodisi signalne bodisi trajne, moramo navesti njihovo globalno ime, ki vsebuje tudi ime komponente. Polno ime parametra vrne metoda `getParameterId()`. ```js -$.getJSON( - {link changeCountBasket!}, - { - {$control->getParameterId('id')}: id, - {$control->getParameterId('count')}: count - } -}); +let url = new URL({link //foo!}); +url.searchParams.set({$control->getParameterId('bar')}, bar); + +fetch(url, { + headers: {'X-Requested-With': 'XMLHttpRequest'}, +}) ``` -In obdela metodo z ustreznimi parametri v komponenti. +Metoda handle z ustreznimi parametri v komponenti: ```php -public function handleChangeCountBasket(int $id, int $count): void +public function handleFoo(int $bar): void { - } ``` diff --git a/application/sl/components.texy b/application/sl/components.texy index 9947ac0b0f..6b1ee7044b 100644 --- a/application/sl/components.texy +++ b/application/sl/components.texy @@ -380,7 +380,7 @@ Komponente poglobljeno .[#toc-components-in-depth] Komponente v aplikaciji Nette so ponovno uporabni deli spletne aplikacije, ki jih vgrajujemo v strani, kar je predmet tega poglavja. Kakšne natančno so zmožnosti takšne komponente? 1) mogoče jo je izrisati v predlogi -2) ve, kateri del sebe naj prikaže med [zahtevo AJAX |ajax#invalidation] (odlomki) +2) ve, [kateri del sebe |ajax#snippets] naj prikaže med zahtevo AJAX (fragmenti). 3) ima možnost shranjevanja svojega stanja v naslovu URL (trajni parametri). 4) ima sposobnost odzivanja na dejanja uporabnika (signali) 5) ustvarja hierarhično strukturo (kjer je korenski element predstavnik) diff --git a/application/tr/ajax.texy b/application/tr/ajax.texy index 2252cb0a0a..05804fd81c 100644 --- a/application/tr/ajax.texy +++ b/application/tr/ajax.texy @@ -3,10 +3,10 @@ AJAX ve Snippet'ler
    -Günümüzde modern web uygulamalarının yarısı sunucuda, yarısı da tarayıcıda çalışmaktadır. AJAX hayati bir birleştirici faktördür. Nette Framework ne gibi destekler sunuyor? -- Şablon parçaları gönderme (*snippet* olarak adlandırılır) +İşlevselliğin genellikle sunucu ve tarayıcı arasında yayıldığı modern web uygulamaları çağında, AJAX önemli bir bağlantı unsurudur. Nette Framework bu alanda hangi seçenekleri sunuyor? +- Şablonun snippet olarak adlandırılan parçalarını gönderme - PHP ve JavaScript arasında değişken aktarımı -- AJAX uygulamaları hata ayıklama +- AJAX isteklerinde hata ayıklama araçları
    @@ -14,29 +14,32 @@ Günümüzde modern web uygulamalarının yarısı sunucuda, yarısı da tarayı AJAX İsteği .[#toc-ajax-request] ================================ -Bir AJAX isteği klasik bir istekten farklı değildir - sunum yapan kişi belirli bir görünüm ve parametrelerle çağrılır. Buna nasıl yanıt verileceği de sunucuya bağlıdır: bir HTML kod parçası (HTML snippet), bir XML belgesi, bir JSON nesnesi veya JavaScript kodu döndüren kendi rutinini kullanabilir. +Bir AJAX isteği temelde klasik bir HTTP isteğinden farklı değildir. Bir sunucu belirli parametrelerle çağrılır. İsteğe nasıl yanıt verileceği sunucuya bağlıdır - JSON biçiminde veri döndürebilir, HTML kodunun bir bölümünü, bir XML belgesini vb. gönderebilir. -Sunucu tarafında, bir AJAX isteği `$httpRequest->isAjax()` [HTTP isteğini kapsülleyen |http:request] hizmet yöntemi kullanılarak algılanabilir ( `X-Requested-With` HTTP başlığına dayalı olarak algılar). Sunucunun içinde, `$this->isAjax()` yöntemi şeklinde bir kısayol mevcuttur. +Tarayıcı tarafında, `fetch()` işlevini kullanarak bir AJAX isteği başlatıyoruz: -JSON'da tarayıcıya veri göndermeye adanmış `payload` adında önceden işlenmiş bir nesne vardır. - -```php -public function actionDelete(int $id): void -{ - if ($this->isAjax()) { - $this->payload->message = 'Success'; - } - // ... -} +```js +fetch(url, { + headers: {'X-Requested-With': 'XMLHttpRequest'}, +}) +.then(response => response.json()) +.then(payload => { + // yanıtın işlenmesi +}); ``` -JSON çıktınız üzerinde tam kontrol sahibi olmak için sunumunuzda `sendJson` yöntemini kullanın. Sunucuyu hemen sonlandırır ve şablon olmadan yaparsınız: +Sunucu tarafında, bir AJAX isteği, [HTTP isteğini kapsülleyen |http:request] hizmetin `$httpRequest->isAjax()` yöntemi tarafından tanınır. Bu yöntem `X-Requested-With` HTTP başlığını kullanır, bu yüzden bunu göndermek çok önemlidir. Sunucu içinde `$this->isAjax()` yöntemini kullanabilirsiniz. + +Verileri JSON biçiminde göndermek istiyorsanız [`sendJson()` |presenters#Sending a response] yöntemi. Yöntem ayrıca sunum yapan kişinin etkinliğini de sonlandırır. ```php -$this->sendJson(['key' => 'value', /* ... */]); +public function actionExport(): void +{ + $this->sendJson($this->model->getData); +} ``` -HTML göndermek istiyorsak, AJAX istekleri için özel bir şablon ayarlayabiliriz: +AJAX için tasarlanmış özel bir şablonla yanıt vermeyi planlıyorsanız, bunu aşağıdaki şekilde yapabilirsiniz: ```php public function handleClick($param): void @@ -44,27 +47,37 @@ public function handleClick($param): void if ($this->isAjax()) { $this->template->setFile('path/to/ajax.latte'); } - // ... + //... } ``` +Parçacıklar .[#toc-snippets] +============================ + +Sunucuyu istemciye bağlamak için Nette tarafından sunulan en güçlü araç snippet'lerdir. Bunlarla, sıradan bir uygulamayı minimum çaba ve birkaç satır kodla bir AJAX uygulamasına dönüştürebilirsiniz. Fifteen örneği tüm bunların nasıl çalıştığını göstermektedir ve kodu [GitHub |https://github.com/nette-examples/fifteen]'da bulunabilir. + +Parçacıklar veya kırpmalar, tüm sayfayı yeniden yüklemek yerine sayfanın yalnızca bazı bölümlerini güncellemenize olanak tanır. Bu daha hızlı ve daha verimlidir ve ayrıca daha rahat bir kullanıcı deneyimi sağlar. Snippet'ler size Ruby on Rails için Hotwire veya Symfony UX Turbo'yu hatırlatabilir. İlginç bir şekilde, Nette snippet'leri 14 yıl önce tanıtmıştı. + +Parçacıklar nasıl çalışır? Sayfa ilk yüklendiğinde (AJAX olmayan bir istek), tüm snippet'ler dahil olmak üzere sayfanın tamamı yüklenir. Kullanıcı sayfayla etkileşime girdiğinde (örneğin, bir düğmeye tıkladığında, bir form gönderdiğinde vb.), sayfanın tamamını yüklemek yerine bir AJAX isteği yapılır. Sunucudaki kod eylemi gerçekleştirir ve hangi parçacıkların güncellenmesi gerektiğine karar verir. Nette bu parçacıkları işler ve bir JSON dizisi şeklinde gönderir. Tarayıcıdaki işleme kodu daha sonra alınan parçacıkları sayfaya geri ekler. Bu nedenle, yalnızca değiştirilen parçacıkların kodu aktarılır, bant genişliğinden tasarruf edilir ve tüm sayfa içeriğinin aktarılmasına kıyasla yükleme hızlandırılır. + + Naja .[#toc-naja] -================= +----------------- -[Naja kütüphanesi |https://naja.js.org], tarayıcı tarafında AJAX isteklerini işlemek için kullanılır. Bir node.js paketi olarak [yükleyin |https://naja.js.org/#/guide/01-install-setup-naja] (Webpack, Rollup, Vite, Parcel ve daha fazlası ile kullanmak için): +Tarayıcı tarafında snippet'leri işlemek için [Naja kütüphanesi |https://naja.js.org] kullanılır. [Bunu |https://naja.js.org/#/guide/01-install-setup-naja] bir node.js paketi olarak [yükleyin |https://naja.js.org/#/guide/01-install-setup-naja] (Webpack, Rollup, Vite, Parcel ve diğerleri gibi uygulamalarla kullanmak için): ```shell npm install naja ``` -...veya doğrudan sayfa şablonuna ekleyin: +... veya doğrudan sayfa şablonuna ekleyin: ```html ``` -Normal bir bağlantıdan (sinyal) veya form gönderiminden bir AJAX isteği oluşturmak için ilgili bağlantıyı, formu veya düğmeyi `ajax` sınıfıyla işaretlemeniz yeterlidir: +Sıradan bir bağlantıyı (sinyal) veya form gönderimini AJAX isteği haline getirmek için ilgili bağlantıyı, formu veya düğmeyi `ajax` sınıfıyla işaretlemeniz yeterlidir: ```html Go @@ -74,64 +87,39 @@ Normal bir bağlantıdan (sinyal) veya form gönderiminden bir AJAX isteği olu or +
    ``` -Parçacıklar .[#toc-snippets] -============================ - -Yerleşik AJAX desteğinin çok daha güçlü bir aracı vardır - snippet'ler. Bunları kullanmak, normal bir uygulamayı yalnızca birkaç satır kod kullanarak bir AJAX uygulamasına dönüştürmeyi mümkün kılar. Tüm bunların nasıl çalıştığı, koduna derlemede veya [GitHub'da |https://github.com/nette-examples/fifteen] da erişilebilen Fifteen örneğinde gösterilmiştir. - -Snippet'lerin çalışma şekli, ilk (yani AJAX olmayan) istek sırasında tüm sayfanın aktarılması ve ardından her AJAX [alt |components#signal] isteğinde (aynı sunucunun aynı görünümünün isteği) yalnızca değiştirilen parçaların kodunun daha önce bahsedilen `payload` deposuna aktarılmasıdır. - -Snippet'ler size Ruby on Rails için Hotwire veya Symfony UX Turbo'yu hatırlatabilir, ancak Nette bunları on dört yıl önce buldu. - +Parçacıkları Yeniden Çizme .[#toc-redrawing-snippets] +----------------------------------------------------- -Snippet'lerin Geçersiz Kılınması .[#toc-invalidation-of-snippets] -================================================================= - -[Control |components] sınıfının her bir torunu (ki bir Presenter da öyledir), bir istek sırasında yeniden oluşturmasını gerektiren herhangi bir değişiklik olup olmadığını hatırlayabilir. Bunu işlemek için bir çift yöntem vardır: `redrawControl()` ve `isControlInvalid()`. Bir örnek: + [Control |components] sınıfının her nesnesi (Presenter'ın kendisi de dahil olmak üzere) yeniden çizilmesini gerektirecek değişikliklerin olup olmadığının kaydını tutar. Bu amaç için `redrawControl()` yöntemi kullanılır. ```php public function handleLogin(string $user): void { - // Nesne, kullanıcı giriş yaptıktan sonra yeniden oluşturulmalıdır + // giriş yaptıktan sonra ilgili kısmı yeniden çizmek gerekir $this->redrawControl(); - // ... + //... } ``` -Ancak Nette, tüm bileşenlerden daha da ince bir çözünürlük sunar. Listelenen yöntemler, isteğe bağlı bir parametre olarak "snippet" olarak adlandırılan bir ismi kabul eder. Bir "snippet" temel olarak şablonunuzdaki bir Latte makrosu tarafından bu amaç için işaretlenmiş bir öğedir, daha sonra bu konuda daha fazla bilgi verilecektir. Böylece bir bileşenden şablonunun sadece *parçalarını* yeniden çizmesini istemek mümkündür. Bileşenin tamamı geçersiz kılınırsa, tüm parçacıkları yeniden oluşturulur. Bir bileşen, alt bileşenlerinden herhangi birinin geçersiz olması durumunda da "geçersiz" olur. - -```php -$this->isControlInvalid(); // -> false -$this->redrawControl('header'); // 'header' adlı parçacığı geçersiz kılar -$this->isControlInvalid('header'); // -> true -$this->isControlInvalid('footer'); // -> false -$this->isControlInvalid(); // -> true, en az bir snippet geçersiz +Nette ayrıca nelerin yeniden çizilmesi gerektiğinin daha iyi kontrol edilmesini sağlar. Yukarıda bahsedilen yöntem, snippet adını bir argüman olarak alabilir. Böylece, şablon parçası düzeyinde geçersiz kılmak (yani yeniden çizmeye zorlamak) mümkündür. Bileşenin tamamı geçersiz kılınırsa, her parçacığı da yeniden çizilir: -$this->redrawControl(); // tüm bileşeni, her parçacığı geçersiz kılar -$this->isControlInvalid('footer'); // -> true +```php +// 'header' parçacığını geçersiz kılar +$this->redrawControl('header'); ``` -Sinyal alan bir bileşen otomatik olarak yeniden çizilmek üzere işaretlenir. - -Snippet yeniden çizimi sayesinde hangi öğelerin hangi kısımlarının yeniden işlenmesi gerektiğini tam olarak biliyoruz. - - -Etiket `{snippet} … {/snippet}` .{toc: Tag snippet} -=================================================== - -Sayfanın oluşturulması normal bir istekle çok benzer şekilde ilerler: aynı şablonlar yüklenir, vb. Ancak önemli olan, çıktıya ulaşmaması gereken kısımların dışarıda bırakılmasıdır; diğer kısımlar bir tanımlayıcı ile ilişkilendirilmeli ve bir JavaScript işleyicisi için anlaşılabilir bir biçimde kullanıcıya gönderilmelidir. - -Sözdizimi .[#toc-syntax] ------------------------- +Latte'de Parçacıklar .[#toc-snippets-in-latte] +---------------------------------------------- -Şablonda bir kontrol veya snippet varsa, bunu `{snippet} ... {/snippet}` pair etiketini kullanarak sarmalıyız - bu, işlenen snippet'in "kesilip çıkarılmasını" ve tarayıcıya gönderilmesini sağlayacaktır. Ayrıca onu bir yardımcı içine alacaktır `
    ` etiketi (farklı bir etiket kullanmak mümkündür). Aşağıdaki örnekte `header` adında bir snippet tanımlanmıştır. Bir bileşenin şablonunu da temsil edebilir: +Latte'de snippet'leri kullanmak son derece kolaydır. Şablonun bir bölümünü snippet olarak tanımlamak için, onu `{snippet}` ve `{/snippet}` etiketlerine sarmanız yeterlidir: ```latte {snippet header} @@ -139,7 +127,9 @@ Sözdizimi .[#toc-syntax] {/snippet} ``` -dışındaki bir türden bir snippet `
    ` veya ek HTML öznitelikleri içeren bir snippet, öznitelik varyantı kullanılarak elde edilir: +Kod parçacığı bir öğe oluşturur `
    ` HTML sayfasında özel olarak oluşturulmuş bir `id`. Bir snippet yeniden çizilirken, bu öğenin içeriği güncellenir. Bu nedenle, sayfa ilk kez render edildiğinde, başlangıçta boş olsalar bile tüm snippet'ler de render edilmelidir. + +dışında bir öğe ile de bir snippet oluşturabilirsiniz `
    ` bir n:özniteliği kullanarak: ```latte
    @@ -148,138 +138,106 @@ dışındaki bir türden bir snippet `
    ` veya ek HTML öznitelikleri içeren ``` -Dinamik Parçacıklar .[#toc-dynamic-snippets] -============================================ +Snippet Alanları .[#toc-snippet-areas] +-------------------------------------- -Nette'de ayrıca bir çalışma zamanı parametresine dayalı olarak dinamik bir adla snippet'ler tanımlayabilirsiniz. Bu, sadece bir satırı değiştirmemiz gereken ancak tüm listeyi onunla birlikte aktarmak istemediğimiz çeşitli listeler için en uygun olanıdır. Bunun bir örneği şöyle olabilir: +Snippet adları ifadeler de olabilir: ```latte -
      - {foreach $list as $id => $item} -
    • {$item} update
    • - {/foreach} -
    +{foreach $items as $id => $item} +
  • {$item}
  • +{/foreach} ``` -Birkaç dinamik snippet içeren `itemsContainer` adında bir statik snippet vardır: `item-0`, `item-1` ve benzeri. +Bu şekilde, `item-0`, `item-1`, vb. gibi birkaç snippet elde edeceğiz. Dinamik bir snippet'i (örneğin, `item-1`) doğrudan geçersiz kılacak olursak, hiçbir şey yeniden çizilmeyecektir. Bunun nedeni, snippet'lerin gerçek alıntılar olarak işlev görmesi ve yalnızca kendilerinin doğrudan render edilmesidir. Ancak, şablonda teknik olarak `item-1` adında bir snippet yoktur. Yalnızca snippet'in çevresindeki kod, bu durumda foreach döngüsü çalıştırıldığında ortaya çıkar. Bu nedenle, şablonun çalıştırılması gereken kısmını `{snippetArea}` etiketiyle işaretleyeceğiz: -Dinamik bir snippet'i doğrudan yeniden çizemezsiniz ( `item-1` adresinin yeniden çizilmesinin hiçbir etkisi yoktur), üst snippet'ini yeniden çizmeniz gerekir (bu örnekte `itemsContainer`). Bu, üst snippet'in kodunun yürütülmesine neden olur, ancak daha sonra tarayıcıya yalnızca alt snippet'leri gönderilir. Alt snippet'lerden yalnızca birini göndermek istiyorsanız, diğer alt snippet'leri oluşturmamak için ana snippet'in girdisini değiştirmeniz gerekir. +```latte +
      + {foreach $items as $id => $item} +
    • {$item}
    • + {/foreach} +
    +``` -Yukarıdaki örnekte, bir AJAX isteği için `$list` dizisine yalnızca bir öğe ekleneceğinden emin olmanız gerekir, bu nedenle `foreach` döngüsü yalnızca bir dinamik parçacık yazdıracaktır. +Ve hem bireysel parçacığı hem de tüm alanı yeniden çizeceğiz: ```php -class HomePresenter extends Nette\Application\UI\Presenter -{ - /** - * This method returns data for the list. - * Usually this would just request the data from a model. - * For the purpose of this example, the data is hard-coded. - */ - private function getTheWholeList(): array - { - return [ - 'First', - 'Second', - 'Third', - ]; - } - - public function renderDefault(): void - { - if (!isset($this->template->list)) { - $this->template->list = $this->getTheWholeList(); - } - } - - public function handleUpdate(int $id): void - { - $this->template->list = $this->isAjax() - ? [] - : $this->getTheWholeList(); - $this->template->list[$id] = 'Updated item'; - $this->redrawControl('itemsContainer'); - } -} +$this->redrawControl('itemsContainer'); +$this->redrawControl('item-1'); ``` +Ayrıca `$items` dizisinin yalnızca yeniden çizilmesi gereken öğeleri içerdiğinden emin olmak da önemlidir. -Dahil Edilen Bir Şablondaki Parçacıklar .[#toc-snippets-in-an-included-template] -================================================================================ - -Snippet, farklı bir şablondan dahil edilen bir şablonda olabilir. Bu durumda, ikinci şablondaki dahil etme kodunu `snippetArea` makrosuyla sarmamız gerekir, ardından hem snippetArea'yı hem de gerçek snippet'i yeniden çizeriz. - -Makro `snippetArea`, içindeki kodun yürütülmesini sağlar, ancak tarayıcıya yalnızca dahil edilen şablondaki gerçek parçacık gönderilir. +Parçacıkları olan `{include}` etiketini kullanarak ana şablona başka bir şablon eklerken, dahil edilen şablonu tekrar bir `snippetArea` içine sarmak ve hem parçacığı hem de alanı birlikte geçersiz kılmak gerekir: ```latte -{* parent.latte *} -{snippetArea wrapper} - {include 'child.latte'} +{snippetArea include} + {include 'included.latte'} {/snippetArea} ``` + ```latte -{* child.latte *} +{* dahil.latte *} {snippet item} -... + ... {/snippet} ``` + ```php -$this->redrawControl('wrapper'); +$this->redrawControl('include'); $this->redrawControl('item'); ``` -Ayrıca dinamik snippet'lerle de birleştirebilirsiniz. +Bileşenlerdeki Snippet'ler .[#toc-snippets-in-components] +--------------------------------------------------------- -Ekleme ve Silme .[#toc-adding-and-deleting] -=========================================== - -Listeye yeni bir öğe ekler ve `itemsContainer` adresini geçersiz kılarsanız, AJAX isteği yenisini de içeren parçacıkları döndürür, ancak javascript işleyicisi bunu işleyemez. Bunun nedeni, yeni oluşturulan ID'ye sahip bir HTML öğesi olmamasıdır. - -Bu durumda, en basit yol tüm listeyi bir parçacığa daha sarmak ve hepsini geçersiz kılmaktır: + [Bileşenler |components] içinde parçacıklar oluşturabilirsiniz ve Nette bunları otomatik olarak yeniden çizer. Bununla birlikte, belirli bir sınırlama vardır: parçacıkları yeniden çizmek için, herhangi bir parametre olmadan `render()` yöntemini çağırır. Bu nedenle, şablonda parametre geçmek işe yaramayacaktır: ```latte -{snippet wholeList} -
      - {foreach $list as $id => $item} -
    • {$item} update
    • - {/foreach} -
    -{/snippet} -Add +OK +{control productGrid} + +will not work: +{control productGrid $arg, $arg} +{control productGrid:paginator} ``` + +Kullanıcı Verilerinin Gönderilmesi .[#toc-sending-user-data] +------------------------------------------------------------ + +Parçacıkların yanı sıra, istemciye herhangi bir ek veri gönderebilirsiniz. Bunları `payload` nesnesine yazmanız yeterlidir: + ```php -public function handleAdd(): void +public function actionDelete(int $id): void { - $this->template->list = $this->getTheWholeList(); - $this->template->list[] = 'New one'; - $this->redrawControl('wholeList'); + //... + if ($this->isAjax()) { + $this->payload->message = 'Success'; + } } ``` -Aynı şey bir öğeyi silmek için de geçerlidir. Boş snippet göndermek mümkün olabilir, ancak genellikle listeler sayfalandırılabilir ve bir öğeyi silip diğerini (sayfalandırılmış listenin farklı bir sayfasında bulunan) yüklemek karmaşık olacaktır. - -Bileşene Parametre Gönderme .[#toc-sending-parameters-to-component] -=================================================================== +Parametreleri Gönderme .[#toc-sending-parameters] +================================================= AJAX isteği aracılığıyla bileşene parametreler gönderdiğimizde, ister sinyal parametreleri ister kalıcı parametreler olsun, bileşenin adını da içeren global adlarını sağlamalıyız. Parametrenin tam adı `getParameterId()` yöntemini döndürür. ```js -$.getJSON( - {link changeCountBasket!}, - { - {$control->getParameterId('id')}: id, - {$control->getParameterId('count')}: count - } -}); +let url = new URL({link //foo!}); +url.searchParams.set({$control->getParameterId('bar')}, bar); + +fetch(url, { + headers: {'X-Requested-With': 'XMLHttpRequest'}, +}) ``` -Ve bileşende karşılık gelen parametrelerle yöntemi işleyin. +Bileşende ilgili parametreleri içeren bir tutamaç yöntemi: ```php -public function handleChangeCountBasket(int $id, int $count): void +public function handleFoo(int $bar): void { - } ``` diff --git a/application/tr/components.texy b/application/tr/components.texy index c0f7bd4c4a..e2c61f23ec 100644 --- a/application/tr/components.texy +++ b/application/tr/components.texy @@ -380,7 +380,7 @@ Derinlemesine Bileşenler .[#toc-components-in-depth] Bir Nette Uygulamasındaki bileşenler, bu bölümün konusu olan sayfalara gömdüğümüz bir web uygulamasının yeniden kullanılabilir parçalarıdır. Böyle bir bileşenin yetenekleri tam olarak nelerdir? 1) bir şablon içinde oluşturulabilir -2) [AJAX isteği |ajax#invalidation] sırasında hangi bölümünün işleneceğini bilir (snippet'ler) +2) AJAX isteği sırasında [hangi bölümünün |ajax#snippets] işleneceğini bilir (snippet'ler) 3) durumunu bir URL'de saklama yeteneğine sahiptir (kalıcı parametreler) 4) kullanıcı eylemlerine (sinyallere) yanıt verme yeteneğine sahiptir 5) hiyerarşik bir yapı oluşturur (kökün sunum yapan kişi olduğu) diff --git a/application/uk/ajax.texy b/application/uk/ajax.texy index df78fc20b8..b6d0aac241 100644 --- a/application/uk/ajax.texy +++ b/application/uk/ajax.texy @@ -1,12 +1,12 @@ -AJAX і сніпети -************** +AJAX та сніппети +****************
    -Сучасні веб-додатки сьогодні працюють наполовину на сервері, а наполовину в браузері. AJAX є життєво важливим об'єднуючим фактором. Яку підтримку пропонує фреймворк Nette? -- надсилання фрагментів шаблонів (так званих *сніпетів*) -- передача змінних між PHP і JavaScript -- Налагодження додатків AJAX +В епоху сучасних веб-додатків, де функціональність часто поширюється між сервером і браузером, AJAX є важливим сполучним елементом. Які можливості пропонує Nette Framework у цій сфері? +- надсилання частин шаблону, так званих фрагментів (snippets) +- передача змінних між PHP та JavaScript +- інструменти для налагодження AJAX-запитів
    @@ -14,29 +14,32 @@ AJAX і сніпети AJAX запит .[#toc-ajax-request] =============================== -AJAX-запит нічим не відрізняється від класичного запиту - викликається доповідач з певним представленням і параметрами. Як на нього відповісти, також залежить від доповідача: він може використовувати власну процедуру, яка повертає фрагмент HTML-коду (HTML-сніппет), XML-документ, JSON-об'єкт або JavaScript-код. +AJAX-запит принципово не відрізняється від класичного HTTP-запиту. Викликається презентер з певними параметрами. Ведучий сам вирішує, як відповісти на запит - він може повернути дані у форматі JSON, надіслати частину HTML-коду, XML-документ тощо. -На стороні сервера AJAX-запит можна виявити за допомогою сервісного методу, що [інкапсулює HTTP-запит |http:request] `$httpRequest->isAjax()` (виявляє на основі HTTP-заголовка `X-Requested-With`). Усередині доповідача доступний ярлик у вигляді методу `$this->isAjax()`. +На стороні браузера ми ініціюємо AJAX-запит за допомогою функції `fetch()`: -Існує попередньо оброблений об'єкт `payload`, призначений для надсилання даних у браузер у форматі JSON. - -```php -public function actionDelete(int $id): void -{ - if ($this->isAjax()) { - $this->payload->message = 'Успішно'; - } - // ... -} +```js +fetch(url, { + headers: {'X-Requested-With': 'XMLHttpRequest'}, +}) +.then(response => response.json()) +.then(payload => { + // обробка відповіді +}); ``` -Для повного контролю над виведенням JSON використовуйте метод `sendJson` у презентері. Це негайно перерве роботу презентера, і ви обійдетеся без шаблону: +На стороні сервера AJAX-запит розпізнається методом `$httpRequest->isAjax()` сервісу, що [інкапсулює HTTP-запит |http:request]. Він використовує HTTP-заголовок `X-Requested-With`, тому його обов'язково потрібно відправити. У презентері ви можете використовувати метод `$this->isAjax()`. + +Якщо ви хочете відправити дані у форматі JSON, використовуйте метод [`sendJson()` |presenters#Sending a response] метод. Метод також завершує роботу доповідача. ```php -$this->sendJson(['key' => 'value', /* ... */]); +public function actionExport(): void +{ + $this->sendJson($this->model->getData); +} ``` -Якщо ми хочемо надіслати HTML, ми можемо встановити спеціальний шаблон для AJAX-запитів: +Якщо ви плануєте відповідати за допомогою спеціального шаблону, розробленого для AJAX, ви можете зробити це наступним чином: ```php public function handleClick($param): void @@ -44,27 +47,37 @@ public function handleClick($param): void if ($this->isAjax()) { $this->template->setFile('path/to/ajax.latte'); } - // ... + //... } ``` -Naja .[#toc-naja] -================= +Фрагменти .[#toc-snippets] +========================== + +Найпотужнішим інструментом, який пропонує Nette для зв'язку сервера з клієнтом, є сніппети. З їх допомогою ви можете перетворити звичайний додаток на AJAX з мінімальними зусиллями та кількома рядками коду. Приклад Fifteen демонструє, як це все працює, а його код можна знайти на [GitHub |https://github.com/nette-examples/fifteen]. + +Сніппети, або вирізки, дозволяють оновлювати лише частини сторінки, замість того, щоб перезавантажувати всю сторінку. Це швидше і ефективніше, а також забезпечує більш комфортний користувацький досвід. Сніппети можуть нагадати вам Hotwire для Ruby on Rails або Symfony UX Turbo. Цікаво, що Nette представила сніппети на 14 років раніше. + +Як працюють фрагменти? При першому завантаженні сторінки (не AJAX-запит) завантажується вся сторінка, включаючи всі фрагменти. Коли користувач взаємодіє зі сторінкою (наприклад, натискає кнопку, відправляє форму тощо), замість завантаження всієї сторінки виконується AJAX-запит. Код у презентері виконує дію і вирішує, які фрагменти потрібно оновити. Nette рендерить ці фрагменти і надсилає їх у вигляді масиву JSON. Потім код обробки в браузері вставляє отримані фрагменти назад на сторінку. Таким чином, передається лише код змінених фрагментів, що економить пропускну здатність і прискорює завантаження порівняно з передачею всього вмісту сторінки. + + +Наджа .[#toc-naja] +------------------ -[Бібліотека Naja |https://naja.js.org] використовується для обробки AJAX-запитів на стороні браузера. [Встановіть |https://naja.js.org/#/guide/01-install-setup-naja] його як пакет node.js (для використання з Webpack, Rollup, Vite, Parcel та іншими): +Для обробки фрагментів на стороні браузера використовується [бібліотека Naja |https://naja.js.org]. [Встановіть її |https://naja.js.org/#/guide/01-install-setup-naja] як пакет node.js (для використання з такими додатками, як Webpack, Rollup, Vite, Parcel та іншими): ```shell npm install naja ``` -...або вставити безпосередньо в шаблон сторінки: +... або вставте її безпосередньо в шаблон сторінки: ```html ``` -Щоб створити AJAX-запит зі звичайного посилання (сигналу) або форми, просто позначте відповідне посилання, форму або кнопку класом `ajax`: +Щоб зробити звичайне посилання (сигнал) або відправку форми AJAX-запитом, просто позначте відповідне посилання, форму або кнопку класом `ajax`: ```html Go @@ -74,64 +87,39 @@ npm install naja or +
    ``` -Сніпети .[#toc-snippety] -======================== - -Однак існує набагато потужніший інструмент вбудованої підтримки AJAX - сніпети. Їхнє використання дає змогу перетворити звичайний застосунок на AJAX-додаток за допомогою лише кількох рядків коду. Як усе це працює, показано в прикладі Fifteen, код якого також доступний у збірці або на [GitHub |https://github.com/nette-examples/fifteen]. - -Принцип роботи сніпетів полягає в тому, що всю сторінку передають під час початкового (тобто не-AJAX) запиту, а потім із кожним AJAX [subrequest |components#Signal] (запит до того самого подання того самого презентера) тільки код змінених частин передають до сховища `payload`, згаданого раніше. - -Сніпети можуть нагадати вам Hotwire для Ruby on Rails або Symfony UX Turbo, але Nette придумав їх чотирнадцятьма роками раніше. +Перемальовуємо фрагменти .[#toc-redrawing-snippets] +--------------------------------------------------- - -Інвалідація .[#toc-invalidation-of-snippets] -============================================ - -Кожен нащадок класу [Control |components] (яким є і Presenter) здатний пам'ятати, чи були якісь зміни під час запиту, що вимагають повторного відображення. Існує кілька способів впоратися з цим: `redrawControl()` і `isControlInvalid()`. Приклад: +Кожен об'єкт класу [Control |components] (в тому числі і сам доповідач) зберігає інформацію про те, чи відбулися зміни, які вимагають його перемальовування. Для цього використовується метод `redrawControl()`. ```php public function handleLogin(string $user): void { - // Об'єкт має повторно відображатися після того, як користувач увійшов у систему + // після входу в систему необхідно перемалювати відповідну частину $this->redrawControl(); - // ... + //... } ``` -Однак Nette забезпечує ще більш тонкий дозвіл, ніж цілі компоненти. Перераховані методи приймають ім'я так званого "фрагмента" як необов'язковий параметр. "Фрагмет" це, по суті, елемент у вашому шаблоні, позначений для цієї мети макросом Latte, докладніше про це пізніше. Таким чином, можна попросити компонент перемалювати тільки *частину* свого шаблону. Якщо весь компонент недійсний, то всі його фрагменти відображаються заново. Компонент є "недійсним", якщо будь-який з його субкомпонентів є недійсним. - -```php -$this->isControlInvalid(); // -> false -$this->redrawControl('header'); // анулює фрагмент з ім'ям 'header' -$this->isControlInvalid('header'); // -> true -$this->isControlInvalid('footer'); // -> false -$this->isControlInvalid(); // -> true, принаймні один фрагмент недійсний +Nette також дозволяє краще контролювати те, що потрібно перемалювати. Вищезгаданий метод може приймати назву фрагмента як аргумент. Таким чином, його можна анулювати (тобто примусово перемалювати) на рівні частини шаблону. Якщо весь компонент анулюється, кожен його фрагмент також перемальовується: -$this->redrawControl(); // робить недійсним весь компонент, кожен фрагмент -$this->isControlInvalid('footer'); // -> true +```php +// робить недійсним фрагмент 'header' +$this->redrawControl('header'); ``` -Компонент, який отримав сигнал, автоматично позначається для перемальовування. - -Завдяки перемальовуванню фрагментів ми точно знаємо, які частини яких елементів мають бути перемальовані. - - -Тег `{snippet} … {/snippet}` .{toc: Tag snippet} -================================================ -Рендеринг сторінки відбувається так само, як і під час звичайного запиту: завантажуються одні й ті самі шаблони тощо. Однак найважливіше - це не допустити потрапляння до вихідного сигналу тих частин, які не повинні потрапити до вихідного сигналу; інші частини мають бути пов'язані з ідентифікатором і надіслані користувачеві у форматі, зрозумілому для обробника JavaScript. +Фрагменти в Latte .[#toc-snippets-in-latte] +------------------------------------------- - -Синтаксис .[#toc-sintaksis] ---------------------------- - -Якщо в шаблоні є елемент управління або фрагмент, ми повинні обернути його за допомогою парного тега `{snippet} ... {/snippet}` - відмальований фрагмент буде "вирізаний" і відправиться в браузер. Він також укладе його в допоміжний тег `
    ` (можна використовувати інший). У наступному прикладі визначено сніппет з ім'ям `header`. Він також може являти собою шаблон компонента: +Використовувати фрагменти в Latte надзвичайно просто. Щоб визначити частину шаблону як фрагмент, просто оберніть його тегами `{snippet}` та `{/snippet}`: ```latte {snippet header} @@ -139,7 +127,9 @@ $this->isControlInvalid('footer'); // -> true {/snippet} ``` -Якщо ви хочете створити сніппет з іншим елементом, що містить, відмінним від `
    `, або додати користувацькі атрибути до елемента, ви можете використовувати таке визначення: +Фрагмент створює елемент `
    ` в HTML-сторінці зі спеціально згенерованим `id`. При перемальовуванні фрагмента вміст цього елемента оновлюється. Тому під час першого відображення сторінки всі сніппети також повинні бути відображені, навіть якщо спочатку вони можуть бути порожніми. + +Ви також можете створити фрагмент з елементом, відмінним від `
    ` використовуючи атрибут n:: ```latte
    @@ -148,138 +138,106 @@ $this->isControlInvalid('footer'); // -> true ``` -Динамічні сніпети .[#toc-dinamiceskie-snippety] -=============================================== +Області фрагментів .[#toc-snippet-areas] +---------------------------------------- -У Nette ви також можете визначити сніпети з динамічним ім'ям, заснованим на параметрі часу виконання. Це найбільше підходить для різних списків, де нам потрібно змінити лише один рядок, але ми не хочемо переносити весь список разом із ним. Прикладом цього може бути: +Назви фрагментів також можуть бути виразами: ```latte - +{foreach $items as $id => $item} +
  • {$item}
  • +{/foreach} ``` -Існує один статичний сніппет `itemsContainer`, що містить кілька динамічних сніпетів: `пункт-0`, `пункт-1` і так далі. +Таким чином, ми отримаємо кілька фрагментів на кшталт `item-0`, `item-1` і т.д. Якщо ми безпосередньо зробимо недійсним динамічний фрагмент (наприклад, `item-1`), нічого не буде перемальовано. Причина в тому, що сніппети функціонують як справжні уривки, і тільки вони безпосередньо рендерингуються. Однак у шаблоні технічно не існує фрагмента з назвою `item-1`. Він з'являється лише при виконанні коду, що оточує фрагмент, в даному випадку - циклу foreach. Тому ми позначимо частину шаблону, яку потрібно виконати, тегом `{snippetArea}`: -Ви не можете перемалювати динамічний фрагмент безпосередньо (перемальовування `item-1` не має ефекту), ви маєте перемалювати його батьківський фрагмент (у цьому прикладі `itemsContainer`). При цьому виконується код батьківського сніпета, але браузеру передаються тільки його вкладені сніпети. Якщо ви хочете передати тільки один із вкладених сніпетів, вам потрібно змінити введення для батьківського сніпета, щоб не генерувати інші вкладені сніпети. +```latte +
      + {foreach $items as $id => $item} +
    • {$item}
    • + {/foreach} +
    +``` -У наведеному прикладі необхідно переконатися, що під час AJAX-запиту до масиву `$list` буде додано тільки один елемент, тому цикл `foreach` виводитиме тільки один динамічний фрагмент. +І перемалюємо як окремий фрагмент, так і всю область, що охоплює його: ```php -class HomePresenter extends Nette\Application\UI\Presenter -{ - /** - * Этот метод возвращает данные для списка. - * Обычно это просто запрос данных из модели. - * Для целей этого примера данные жёстко закодированы. - */ - private function getTheWholeList(): array - { - return [ - 'First', - 'Second', - 'Third', - ]; - } - - public function renderDefault(): void - { - if (!isset($this->template->list)) { - $this->template->list = $this->getTheWholeList(); - } - } - - public function handleUpdate(int $id): void - { - $this->template->list = $this->isAjax() - ? [] - : $this->getTheWholeList(); - $this->template->list[$id] = 'Updated item'; - $this->redrawControl('itemsContainer'); - } -} +$this->redrawControl('itemsContainer'); +$this->redrawControl('item-1'); ``` +Важливо також переконатися, що масив `$items` містить лише ті елементи, які потрібно перемалювати. -Сніпети в увімкненому шаблоні .[#toc-snippety-vo-vklyucennom-sablone] -===================================================================== - -Може трапитися так, що сніппет міститься в шаблоні, який вмикається з іншого шаблону. У цьому разі необхідно обернути код включення в другому шаблоні макросом `snippetArea`, потім перемалювати як snippetArea, так і сам сніппет. - -Макрос `snippetArea` гарантує, що код усередині нього буде виконано, але браузеру буде надіслано тільки фактичний фрагмент включеного шаблону. +При вставці іншого шаблону в основний за допомогою тегу `{include}`, який містить фрагменти, необхідно знову загорнути включений шаблон в `snippetArea` і зробити недійсним як фрагмент, так і область разом: ```latte -{* parent.latte *} -{snippetArea wrapper} - {include 'child.latte'} +{snippetArea include} + {include 'included.latte'} {/snippetArea} ``` + ```latte -{* child.latte *} +{* included.latte *} {snippet item} -... + ... {/snippet} ``` + ```php -$this->redrawControl('wrapper'); +$this->redrawControl('include'); $this->redrawControl('item'); ``` -Ви також можете поєднувати його з динамічними сніпетами. - -Додавання та видалення .[#toc-dobavlenie-i-udalenie] -==================================================== +Сніппети в компонентах .[#toc-snippets-in-components] +----------------------------------------------------- -Якщо додати новий елемент у список і анулювати `itemsContainer`, AJAX-запит поверне фрагменти, включно з новим, але javascript-обробник не зможе його відобразити. Це відбувається тому, що немає HTML-елемента з новоствореним ID. - -У цьому випадку найпростіший спосіб - обернути весь список у ще один сніпет і визнати його недійсним: +Ви можете створювати фрагменти всередині [компонентів |components], і Nette автоматично перемальовуватиме їх. Однак є певне обмеження: для перемальовування фрагментів він викликає метод `render()` без жодних параметрів. Таким чином, передача параметрів у шаблоні не спрацює: ```latte -{snippet wholeList} - -{/snippet} -Добавить +OK +{control productGrid} + +will not work: +{control productGrid $arg, $arg} +{control productGrid:paginator} ``` + +Надсилання даних користувача .[#toc-sending-user-data] +------------------------------------------------------ + +Разом зі сніппетами ви можете надсилати клієнту будь-які додаткові дані. Просто впишіть їх в об'єкт `payload`: + ```php -public function handleAdd(): void +public function actionDelete(int $id): void { - $this->template->list = $this->getTheWholeList(); - $this->template->list[] = 'New one'; - $this->redrawControl('wholeList'); + //... + if ($this->isAjax()) { + $this->payload->message = 'Success'; + } } ``` -Те ж саме стосується і видалення елемента. Можна було б надіслати порожній сніппет, але зазвичай списки можуть бути посторінковими, і було б складно реалізувати видалення одного елемента і завантаження іншого (який раніше перебував на іншій сторінці посторінкового списку). - -Надсилання параметрів компоненту .[#toc-otpravka-parametrov-komponentu] -======================================================================= +Параметри відправки .[#toc-sending-parameters] +============================================== -Коли ми надсилаємо параметри компоненту через AJAX-запит, чи то сигнальні, чи постійні параметри, ми повинні надати їхнє глобальне ім'я, яке також містить ім'я компонента. Повне ім'я параметра повертає метод `getParameterId()`. +Коли ми надсилаємо параметри компоненту за допомогою AJAX-запиту, будь то сигнальні параметри або постійні параметри, ми повинні вказати їх глобальне ім'я, яке також містить ім'я компонента. Повне ім'я параметра повертає метод `getParameterId()`. ```js -$.getJSON( - {link changeCountBasket!}, - { - {$control->getParameterId('id')}: id, - {$control->getParameterId('count')}: count - } -}); +let url = new URL({link //foo!}); +url.searchParams.set({$control->getParameterId('bar')}, bar); + +fetch(url, { + headers: {'X-Requested-With': 'XMLHttpRequest'}, +}) ``` -І обробити метод з відповідними параметрами в компоненті. +Метод обробки з відповідними параметрами в компоненті: ```php -public function handleChangeCountBasket(int $id, int $count): void +public function handleFoo(int $bar): void { - } ``` diff --git a/application/uk/components.texy b/application/uk/components.texy index 834fb55a2f..9b1e067d5d 100644 --- a/application/uk/components.texy +++ b/application/uk/components.texy @@ -380,7 +380,7 @@ interface PollControlFactory Компоненти в Nette Application - це багаторазово використовувані частини веб-додатка, які ми вбудовуємо в сторінки, про що і піде мова в цьому розділі. Які можливості такого компонента? 1) він може бути відображений у шаблоні -2) він знає, яку частину себе відображати під час [AJAX-запиту |ajax#invalidation] (сніпети) +2) він знає, [яку частину себе |ajax#snippets] рендерити під час AJAX-запиту (фрагменти) 3) має можливість зберігати свій стан в URL (постійні параметри) 4) має можливість реагувати на дії користувача (сигнали) 5) створює ієрархічну структуру (де коренем є ведучий) diff --git a/latte/bg/tags.texy b/latte/bg/tags.texy index 61dc6b378b..2d53f63639 100644 --- a/latte/bg/tags.texy +++ b/latte/bg/tags.texy @@ -97,8 +97,8 @@ | `{link}` |00 | [отпечатва връзка |application:creating-links#In-the-Presenter-Template] | `{plink}` | [отпечатва връзката към главния модул |application:creating-links#In-the-Presenter-Template] | `{control}` | [отпечатва компонент |application:components#Rendering] -| `{snippet}`... `{/snippet}` | [откъс от шаблон, който може да бъде изпратен чрез AJAX |application:ajax#Tag-snippet] -| `{snippetArea}` | плик за фрагмент +| `{snippet}`... `{/snippet}` | [откъс от шаблон, който може да бъде изпратен чрез AJAX |application:ajax#snippets-in-latte] +| `{snippetArea}` | [плик за фрагмент |application:ajax#snippet-areas] | `{cache}`... `{/cache}` | [кеширане на секцията с шаблони |caching:#Caching-in-Latte] .[table-latte-tags language-latte] diff --git a/latte/cs/tags.texy b/latte/cs/tags.texy index 8d410cd225..1f075e08d8 100644 --- a/latte/cs/tags.texy +++ b/latte/cs/tags.texy @@ -97,8 +97,8 @@ Přehled a popis všech tagů (neboli značek či maker) šablonovacího systém | `{link}` | [vypíše odkaz |application:creating-links#V šabloně presenteru] | `{plink}` | [vypíše odkaz na presenter |application:creating-links#V šabloně presenteru] | `{control}` | [vykreslí komponentu |application:components#Vykreslení] -| `{snippet}` … `{/snippet}` | [výstřižek, který lze odeslat AJAXem |application:ajax#tag-snippet] -| `{snippetArea}` | obálka pro výstřižky +| `{snippet}` … `{/snippet}` | [výstřižek, který lze odeslat AJAXem |application:ajax#snippety-v-latte] +| `{snippetArea}` | [obálka pro výstřižky |application:ajax#oblasti-snippetu] | `{cache}` … `{/cache}` | [cachuje část šablony |caching:#cachovani-v-latte] .[table-latte-tags language-latte] diff --git a/latte/de/tags.texy b/latte/de/tags.texy index 52df4f4ecd..b816bb1e31 100644 --- a/latte/de/tags.texy +++ b/latte/de/tags.texy @@ -97,8 +97,8 @@ Zusammenfassung und Beschreibung aller in Latte integrierten Tags. | `{link}` | [gibt einen Link aus |application:creating-links#In the Presenter Template] | `{plink}` | [druckt einen Link zu einem Presenter |application:creating-links#In the Presenter Template] | `{control}` | [druckt eine Komponente |application:components#Rendering] -| `{snippet}`... `{/snippet}` | [ein Template-Snippet, das per AJAX gesendet werden kann |application:ajax#tag-snippet] -| `{snippetArea}` | Schnipsel Umschlag +| `{snippet}`... `{/snippet}` | [ein Template-Snippet, das per AJAX gesendet werden kann |application:ajax#snippets-in-latte] +| `{snippetArea}` | [Schnipsel Umschlag |application:ajax#snippet-areas] | `{cache}`... `{/cache}` | [zwischenspeichert einen Vorlagenabschnitt |caching:#caching-in-latte] .[table-latte-tags language-latte] diff --git a/latte/el/tags.texy b/latte/el/tags.texy index de069be3da..3b072d07d0 100644 --- a/latte/el/tags.texy +++ b/latte/el/tags.texy @@ -97,8 +97,8 @@ | `{link}` | [εκτυπώνει έναν σύνδεσμο |application:creating-links#In the Presenter Template] | `{plink}` | [εκτυπώνει έναν σύνδεσμο προς έναν παρουσιαστή |application:creating-links#In the Presenter Template] | `{control}` | [εκτυπώνει ένα στοιχείο |application:components#Rendering] -| `{snippet}`... `{/snippet}` | [ένα απόσπασμα προτύπου που μπορεί να σταλεί μέσω AJAX |application:ajax#tag-snippet] -| `{snippetArea}` | φάκελος αποσπασμάτων +| `{snippet}`... `{/snippet}` | [ένα απόσπασμα προτύπου που μπορεί να σταλεί μέσω AJAX |application:ajax#snippets-in-latte] +| `{snippetArea}` | [φάκελος αποσπασμάτων |application:ajax#snippet-areas] | `{cache}`... `{/cache}` | [προσωρινή αποθήκευση ενός τμήματος προτύπου |caching:en#caching-in-latte] .[table-latte-tags language-latte] diff --git a/latte/en/tags.texy b/latte/en/tags.texy index 2df615fc3a..40f20ce675 100644 --- a/latte/en/tags.texy +++ b/latte/en/tags.texy @@ -97,8 +97,8 @@ Summary and description of all Latte built-in tags. | `{link}` | [prints a link |application:creating-links#In the Presenter Template] | `{plink}` | [prints a link to a presenter |application:creating-links#In the Presenter Template] | `{control}` | [prints a component |application:components#Rendering] -| `{snippet}` … `{/snippet}` | [a template snippet that can be sent by AJAX |application:ajax#tag-snippet] -| `{snippetArea}` | snippets envelope +| `{snippet}` … `{/snippet}` | [a template snippet that can be sent by AJAX |application:ajax#snippets-in-latte] +| `{snippetArea}` | [snippets envelope |application:ajax#snippet-areas] | `{cache}` … `{/cache}` | [caches a template section |caching:#caching-in-latte] .[table-latte-tags language-latte] diff --git a/latte/es/tags.texy b/latte/es/tags.texy index 333de04aa1..9a1a83768b 100644 --- a/latte/es/tags.texy +++ b/latte/es/tags.texy @@ -97,8 +97,8 @@ Resumen y descripción de todas las etiquetas Latte incorporadas. | `{link}` | [imprime un enlace |application:creating-links#In the Presenter Template] | `{plink}` | [imprime un enlace a un [presentador |application:creating-links#In the Presenter Template] | `{control}` | [imprime un componente |application:components#Rendering] -| `{snippet}`... `{/snippet}` | [un fragmento de plantilla que puede ser enviado por AJAX |application:ajax#tag-snippet] -| `{snippetArea}` | snippets sobre +| `{snippet}`... `{/snippet}` | [un fragmento de plantilla que puede ser enviado por AJAX |application:ajax#snippets-in-latte] +| `{snippetArea}` | [snippets sobre |application:ajax#snippet-areas] | `{cache}`... `{/cache}` | [almacena en caché una sección de plantilla|caching:#caching-in-latte] .[table-latte-tags language-latte] diff --git a/latte/fr/tags.texy b/latte/fr/tags.texy index 26c0d42606..6014948985 100644 --- a/latte/fr/tags.texy +++ b/latte/fr/tags.texy @@ -97,8 +97,8 @@ Résumé et description de toutes les balises intégrées de Latte. | `{link}` | [imprime un lien |application:creating-links#In the Presenter Template] | `{plink}` | [imprime un lien vers un présentateur |application:creating-links#In the Presenter Template] | `{control}` | [imprime un composant |application:components#Rendering] -| `{snippet}`... `{/snippet}` | [un snippet de modèle qui peut être envoyé par AJAX |application:ajax#tag-snippet] -| `{snippetArea}` | enveloppe des snippets +| `{snippet}`... `{/snippet}` | [un snippet de modèle qui peut être envoyé par AJAX |application:ajax#snippets-in-latte] +| `{snippetArea}` | [enveloppe des snippets |application:ajax#snippet-areas] | `{cache}`... `{/cache}` | [met en cache une section de modèle |caching:#caching-in-latte] .[table-latte-tags language-latte] diff --git a/latte/hu/tags.texy b/latte/hu/tags.texy index 515ef7aa3c..8067ced3a4 100644 --- a/latte/hu/tags.texy +++ b/latte/hu/tags.texy @@ -97,8 +97,8 @@ Az összes beépített Latte-címke összefoglalása és leírása. | `{link}` | [linket nyomtat |application:creating-links#In the Presenter Template] | `{plink}` | [bemutatóra mutató link nyomtatása |application:creating-links#In the Presenter Template] | `{control}` | [komponens nyomtatása |application:components#Rendering] -| `{snippet}`... `{/snippet}` | [AJAX-szel küldhető sablonrészlet |application:ajax#tag-snippet] -| `{snippetArea}` | snippet borítékolás +| `{snippet}`... `{/snippet}` | [AJAX-szel küldhető sablonrészlet |application:ajax#snippets-in-latte] +| `{snippetArea}` | [snippet borítékolás |application:ajax#snippet-areas] | `{cache}`... `{/cache}` | [egy sablonrészlet gyorsítótárba helyezése |caching:#caching-in-latte] .[table-latte-tags language-latte] diff --git a/latte/it/tags.texy b/latte/it/tags.texy index e41b39e7e0..8f913e302e 100644 --- a/latte/it/tags.texy +++ b/latte/it/tags.texy @@ -97,8 +97,8 @@ Riepilogo e descrizione di tutti i tag incorporati di Latte. | `{link}` | [stampa un link |application:creating-links#In the Presenter Template] | `{plink}` | [stampa un link a un presentatore |application:creating-links#In the Presenter Template] | `{control}` | [stampa un componente |application:components#Rendering] -| `{snippet}`... `{/snippet}` | [uno snippet di modello che può essere inviato tramite AJAX |application:ajax#tag-snippet] -| `{snippetArea}` | snippet busta +| `{snippet}`... `{/snippet}` | [uno snippet di modello che può essere inviato tramite AJAX |application:ajax#snippets-in-latte] +| `{snippetArea}` | [snippet busta |application:ajax#snippet-areas] | `{cache}`... `{/cache}` | [memorizza nella cache una sezione del template |caching:#caching-in-latte] .[table-latte-tags language-latte] diff --git a/latte/ja/tags.texy b/latte/ja/tags.texy index 58f2fcab6f..d0ddf3e1d1 100644 --- a/latte/ja/tags.texy +++ b/latte/ja/tags.texy @@ -97,8 +97,8 @@ Latte内蔵の全タグの概要と説明。 |`{link}` |[リンクを表示する|application:en:creating-links#In the Presenter Template] |`{plink}` |[プレゼンターへのリンクを表示する|application:en:creating-links#In the Presenter Template] |`{control}` |[コンポーネントを表示します|application:en:components#Rendering] -|`{snippet}`...`{/snippet}` |[AJAXで送信可能なテンプレートスニペット |application:en:ajax#tag-snippet] -|`{snippetArea}` | スニペットの封筒 +|`{snippet}`...`{/snippet}` |[AJAXで送信可能なテンプレートスニペット |application:en:ajax#snippets-in-latte] +|`{snippetArea}` | [スニペットの封筒 |application:en:ajax#snippet-areas] |`{cache}`...`{/cache}` |[テンプレートセクションをキャッシュする|caching:en#caching-in-latte] .[table-latte-tags language-latte] diff --git a/latte/pl/tags.texy b/latte/pl/tags.texy index 427b023b0d..01361a52f5 100644 --- a/latte/pl/tags.texy +++ b/latte/pl/tags.texy @@ -97,8 +97,8 @@ Przegląd i opis wszystkich znaczników systemu templatek Latte, które są domy | `{link}` | [drukuje link |application:creating-links#In-the-Presenter-Template] | `{plink}` | [drukuje link do prezentera |application:creating-links#In-the-Presenter-Template] | `{control}` | [renderuje komponent |application:components#Rendering] -| `{snippet}`... `{/snippet}` | [snippet, który może być wysłany przez AJAX |application:ajax#Tag-snippet] -| `{snippetArea}` | clipping cover +| `{snippet}`... `{/snippet}` | [snippet, który może być wysłany przez AJAX |application:ajax#snippets-in-latte] +| `{snippetArea}` | [clipping cover |application:ajax#snippet-areas] | `{cache}`... `{/cache}` | [buforuje część szablonu |caching:#Caching-in-Latte] .[table-latte-tags language-latte] diff --git a/latte/pt/tags.texy b/latte/pt/tags.texy index e75d75442c..49c3599b74 100644 --- a/latte/pt/tags.texy +++ b/latte/pt/tags.texy @@ -97,8 +97,8 @@ Resumo e descrição de todas as etiquetas incorporadas no Latte. | `{link}` | [imprime um link |application:creating-links#In the Presenter Template] | `{plink}` | [imprime um link para um apresentador |application:creating-links#In the Presenter Template] | `{control}` | [imprime um componente |application:components#Rendering] -| `{snippet}`... `{/snippet}` | [um trecho de modelo que pode ser enviado pela AJAX |application:ajax#tag-snippet] -| `{snippetArea}` | envelope de snippets +| `{snippet}`... `{/snippet}` | [um trecho de modelo que pode ser enviado pela AJAX |application:ajax#snippets-in-latte] +| `{snippetArea}` | [envelope de snippets |application:ajax#snippet-areas] | `{cache}`... `{/cache}` | [caches uma seção modelo |caching:#caching-in-latte] .[table-latte-tags language-latte] diff --git a/latte/ro/tags.texy b/latte/ro/tags.texy index 418f96706b..c2950bc2ad 100644 --- a/latte/ro/tags.texy +++ b/latte/ro/tags.texy @@ -97,8 +97,8 @@ Rezumat și descriere a tuturor etichetelor Latte încorporate. | `{link}` | [tipărește un link |application:creating-links#In the Presenter Template] | `{plink}` | [tipărește un link către un prezentator |application:creating-links#In the Presenter Template] | `{control}` | [tipărește o componentă |application:components#Rendering] -| `{snippet}`... `{/snippet}` | [un fragment de șablon care poate fi trimis prin AJAX |application:ajax#tag-snippet] -| `{snippetArea}` | plic de fragmente +| `{snippet}`... `{/snippet}` | [un fragment de șablon care poate fi trimis prin AJAX |application:ajax#snippets-in-latte] +| `{snippetArea}` | [plic de fragmente |application:ajax#snippet-areas] | `{cache}`... `{/cache}` | [pune în cache o secțiune de șablon |caching:en#caching-in-latte] .[table-latte-tags language-latte] diff --git a/latte/ru/tags.texy b/latte/ru/tags.texy index bda6db644b..d47d8f30cc 100644 --- a/latte/ru/tags.texy +++ b/latte/ru/tags.texy @@ -97,8 +97,8 @@ | `{link}` | [печатает ссылку |application:creating-links#In-the-Presenter-Template] | `{plink}` | [печатает ссылку на ведущего |application:creating-links#In-the-Presenter-Template] | `{control}` | [печатает компонент |application:components#Rendering] -| `{snippet}`... `{/snippet}` | [фрагмент шаблона, который может быть отправлен с помощью AJAX |application:ajax#Tag-snippet] -| `{snippetArea}` | конверт сниппетов +| `{snippet}`... `{/snippet}` | [фрагмент шаблона, который может быть отправлен с помощью AJAX |application:ajax#snippets-in-latte] +| `{snippetArea}` | [конверт сниппетов |application:ajax#snippet-areas] | `{cache}`... `{/cache}` | [кэширует раздел шаблона |caching:#Caching-in-Latte] .[table-latte-tags language-latte] diff --git a/latte/sl/tags.texy b/latte/sl/tags.texy index a28be54aa9..b218a53ccc 100644 --- a/latte/sl/tags.texy +++ b/latte/sl/tags.texy @@ -97,8 +97,8 @@ Povzetek in opis vseh vgrajenih oznak Latte. | `{link}` | [izpiše povezavo |application:creating-links#In the Presenter Template] | `{plink}` | [natisne povezavo do predvajalnika |application:creating-links#In the Presenter Template] | `{control}` | [natisne komponento |application:components#Rendering] -| `{snippet}`... `{/snippet}` | [odlomek predloge, ki se lahko pošlje z AJAXom |application:ajax#tag-snippet] -| `{snippetArea}` | ovojnica snippets +| `{snippet}`... `{/snippet}` | [odlomek predloge, ki se lahko pošlje z AJAXom |application:ajax#snippets-in-latte] +| `{snippetArea}` | [ovojnica snippets |application:ajax#snippet-areas] | `{cache}`... `{/cache}` | [predpomnilnik oddelka predloge |caching:en#caching-in-latte] .[table-latte-tags language-latte] diff --git a/latte/tr/tags.texy b/latte/tr/tags.texy index d7154073d0..889b0d3aba 100644 --- a/latte/tr/tags.texy +++ b/latte/tr/tags.texy @@ -97,8 +97,8 @@ Tüm Latte yerleşik etiketlerinin özeti ve açıklaması. | `{link}` | [bir bağlantı yazdırır |application:creating-links#In the Presenter Template] | `{plink}` | [sunum yapan kişiye bir bağlantı yazdırır |application:creating-links#In the Presenter Template] | `{control}` | [bir bileşen yazdırır |application:components#Rendering] -| `{snippet}`... `{/snippet}` | [AJAX ile gönderilebilecek bir şablon parçacığı |application:ajax#tag-snippet] -| `{snippetArea}` | snippets zarfı +| `{snippet}`... `{/snippet}` | [AJAX ile gönderilebilecek bir şablon parçacığı |application:ajax#snippets-in-latte] +| `{snippetArea}` | [snippets zarfı |application:ajax#snippet-areas] | `{cache}`... `{/cache}` | [bir şablon bölümünü önbelleğe alır|caching:#caching-in-latte] .[table-latte-tags language-latte] diff --git a/latte/uk/tags.texy b/latte/uk/tags.texy index fdf8ed737c..40bc5c4964 100644 --- a/latte/uk/tags.texy +++ b/latte/uk/tags.texy @@ -97,8 +97,8 @@ | `{link}` | [друкує посилання |application:creating-links#In-the-Presenter-Template] | `{plink}` | [друкує посилання на ведучого |application:creating-links#In-the-Presenter-Template] | `{control}` | [друкує компонент |application:components#Rendering] -| `{snippet}`... `{/snippet}` | [фрагмент шаблону, який може бути відправлений за допомогою AJAX |application:ajax#Tag-snippet] -| `{snippetArea}` | конверт сніпетів +| `{snippet}`... `{/snippet}` | [фрагмент шаблону, який може бути відправлений за допомогою AJAX |application:ajax#snippets-in-latte] +| `{snippetArea}` | [конверт сніпетів |application:ajax#snippet-areas] | `{cache}`... `{/cache}` | [кешує розділ шаблону |caching:#Caching-in-Latte] .[table-latte-tags language-latte] From 8427ee1a282ddf9808bc8ce49d7afd040d63428e Mon Sep 17 00:00:00 2001 From: David Grudl Date: Fri, 20 Oct 2023 18:08:50 +0200 Subject: [PATCH 026/137] forms: improved in about disabled fields --- forms/bg/controls.texy | 4 ++-- forms/cs/controls.texy | 4 ++-- forms/de/controls.texy | 4 ++-- forms/el/controls.texy | 4 ++-- forms/en/controls.texy | 4 ++-- forms/es/controls.texy | 4 ++-- forms/fr/controls.texy | 4 ++-- forms/hu/controls.texy | 4 ++-- forms/it/controls.texy | 4 ++-- forms/pl/controls.texy | 4 ++-- forms/pt/controls.texy | 4 ++-- forms/ro/controls.texy | 4 ++-- forms/ru/controls.texy | 4 ++-- forms/sl/controls.texy | 4 ++-- forms/tr/controls.texy | 4 ++-- forms/uk/controls.texy | 4 ++-- 16 files changed, 32 insertions(+), 32 deletions(-) diff --git a/forms/bg/controls.texy b/forms/bg/controls.texy index ef9f30e62f..c3983e946b 100644 --- a/forms/bg/controls.texy +++ b/forms/bg/controls.texy @@ -412,9 +412,9 @@ $form->addText('username', 'Имя пользователя:') ->setDisabled(); ``` -Обърнете внимание, че браузърът изобщо не изпраща забранените полета към сървъра, така че те дори няма да бъдат открити в данните, върнати от функцията `$form->getValues()`. +Деактивираните полета изобщо не се изпращат от браузъра към сървъра, така че няма да ги намерите в данните, върнати от функцията `$form->getValues()`. Въпреки това, ако зададете `setOmitted(false)`, Nette ще включи тяхната стойност в тези данни. -Ако задавате стойност по подразбиране за дадено поле, трябва да го направите само след като сте го деактивирали: +Когато извикате `setDisabled()`, стойността на полето се изтрива. Ако задавате стойност по подразбиране, трябва да го направите, след като я деактивирате: ```php $form->addText('username', 'Имя пользователя:') diff --git a/forms/cs/controls.texy b/forms/cs/controls.texy index 237ef0547f..46b5ccf4ed 100644 --- a/forms/cs/controls.texy +++ b/forms/cs/controls.texy @@ -412,9 +412,9 @@ $form->addText('username', 'Uživatelské jméno:') ->setDisabled(); ``` -Upozorňujeme, že disablované prvky prohlížeč vůbec neodesílá na server, tedy je ani nenajdete v datech vrácených funkcí `$form->getValues()`. +Disablované prvky prohlížeč vůbec neodesílá na server, tedy je ani nenajdete v datech vrácených funkcí `$form->getValues()`. Pokud však nastavíte `setOmitted(false)`, Nette jejich hodnotu do těchto dat zahrne. -Pokud prvku nastavujete výchozí hodnotu, je tak nutné učinit až po jeho deaktivaci: +Při volání `setDisabled()` se smaže hodnota prvku. Pokud nastavujete výchozí hodnotu, je tak nutné učinit až po jeho deaktivaci: ```php $form->addText('username', 'Uživatelské jméno:') diff --git a/forms/de/controls.texy b/forms/de/controls.texy index 33f09429bf..8f6891b8a0 100644 --- a/forms/de/controls.texy +++ b/forms/de/controls.texy @@ -412,9 +412,9 @@ $form->addText('username', 'User name:') ->setDisabled(); ``` -Beachten Sie, dass der Browser die deaktivierten Felder gar nicht an den Server sendet, so dass Sie sie nicht einmal in den von der Funktion `$form->getValues()` zurückgegebenen Daten finden werden. +Deaktivierte Felder werden vom Browser nicht an den Server gesendet, so dass sie nicht in den von der Funktion `$form->getValues()` zurückgegebenen Daten zu finden sind. Wenn Sie jedoch `setOmitted(false)` einstellen, wird Nette ihren Wert in diese Daten aufnehmen. -Wenn Sie einen Standardwert für ein Feld festlegen, dürfen Sie dies erst tun, nachdem Sie das Feld deaktiviert haben: +Wenn Sie `setDisabled()` aufrufen, wird der Wert des Feldes gelöscht. Wenn Sie einen Standardwert setzen, müssen Sie dies nach der Deaktivierung tun: ```php $form->addText('username', 'User name:') diff --git a/forms/el/controls.texy b/forms/el/controls.texy index 9da47861ef..a138d0e62d 100644 --- a/forms/el/controls.texy +++ b/forms/el/controls.texy @@ -412,9 +412,9 @@ $form->addText('username', 'User name:') ->setDisabled(); ``` -Σημειώστε ότι το πρόγραμμα περιήγησης δεν στέλνει καθόλου τα απενεργοποιημένα πεδία στο διακομιστή, οπότε δεν θα τα βρείτε καν στα δεδομένα που επιστρέφει η συνάρτηση `$form->getValues()`. +Τα απενεργοποιημένα πεδία δεν αποστέλλονται καθόλου από το πρόγραμμα περιήγησης στον διακομιστή, οπότε δεν θα τα βρείτε στα δεδομένα που επιστρέφονται από τη λειτουργία `$form->getValues()`. Ωστόσο, αν ορίσετε το `setOmitted(false)`, η Nette θα συμπεριλάβει την τιμή τους σε αυτά τα δεδομένα. -Εάν ορίζετε μια προεπιλεγμένη τιμή για ένα πεδίο, πρέπει να το κάνετε μόνο αφού το απενεργοποιήσετε: +Όταν καλέσετε τη λειτουργία `setDisabled()`, η τιμή του πεδίου διαγράφεται. Εάν ορίζετε μια προεπιλεγμένη τιμή, πρέπει να το κάνετε αφού την απενεργοποιήσετε: ```php $form->addText('username', 'User name:') diff --git a/forms/en/controls.texy b/forms/en/controls.texy index dd1a9db0c9..59b9206619 100644 --- a/forms/en/controls.texy +++ b/forms/en/controls.texy @@ -412,9 +412,9 @@ $form->addText('username', 'User name:') ->setDisabled(); ``` -Note that the browser does not send the disabled fields to the server at all, so you won't even find them in the data returned by the `$form->getValues()` function. +Disabled fields are not sent by the browser to the server at all, so you will not find them in the data returned by the `$form->getValues()` function. However, if you set `setOmitted(false)`, Nette will include their value in this data. -If you are setting a default value for a field, you must do so only after disabling it: +When you call `setDisabled()`, the value of the field is deleted. If you are setting a default value, you must do so after deactivating it: ```php $form->addText('username', 'User name:') diff --git a/forms/es/controls.texy b/forms/es/controls.texy index 9ea4d7241b..2e48bd6cfe 100644 --- a/forms/es/controls.texy +++ b/forms/es/controls.texy @@ -412,9 +412,9 @@ $form->addText('username', 'User name:') ->setDisabled(); ``` -Tenga en cuenta que el navegador no envía los campos deshabilitados al servidor en absoluto, por lo que ni siquiera los encontrará en los datos devueltos por la función `$form->getValues()`. +Los campos deshabilitados no son enviados por el navegador al servidor en absoluto, por lo que no los encontrará en los datos devueltos por la función `$form->getValues()`. Sin embargo, si configura `setOmitted(false)`, Nette incluirá su valor en estos datos. -Si establece un valor predeterminado para un campo, debe hacerlo sólo después de desactivarlo: +Cuando llame a `setDisabled()`, se borrará el valor del campo. Si establece un valor por defecto, deberá hacerlo después de desactivarlo: ```php $form->addText('username', 'User name:') diff --git a/forms/fr/controls.texy b/forms/fr/controls.texy index 81e0fba99d..7909477786 100644 --- a/forms/fr/controls.texy +++ b/forms/fr/controls.texy @@ -412,9 +412,9 @@ $form->addText('username', 'User name:') ->setDisabled(); ``` -Notez que le navigateur n'envoie pas du tout les champs désactivés au serveur, de sorte que vous ne les trouverez même pas dans les données renvoyées par la fonction `$form->getValues()`. +Les champs désactivés ne sont pas du tout envoyés par le navigateur au serveur, de sorte qu'ils ne figurent pas dans les données renvoyées par la fonction `$form->getValues()`. Toutefois, si vous définissez `setOmitted(false)`, Nette inclura leur valeur dans ces données. -Si vous définissez une valeur par défaut pour un champ, vous devez le faire uniquement après l'avoir désactivé : +Lorsque vous appelez `setDisabled()`, la valeur du champ est supprimée. Si vous définissez une valeur par défaut, vous devez le faire après l'avoir désactivée : ```php $form->addText('username', 'User name:') diff --git a/forms/hu/controls.texy b/forms/hu/controls.texy index 624c32fdac..48ab6d0292 100644 --- a/forms/hu/controls.texy +++ b/forms/hu/controls.texy @@ -412,9 +412,9 @@ $form->addText('username', 'User name:') ->setDisabled(); ``` -Vegye figyelembe, hogy a böngésző egyáltalán nem küldi el a letiltott mezőket a szerverre, így a `$form->getValues()` függvény által visszaküldött adatokban sem fogja megtalálni őket. +A letiltott mezőket a böngésző egyáltalán nem küldi el a kiszolgálónak, így a `$form->getValues()` funkció által visszaküldött adatokban sem találja meg őket. Ha azonban beállítja a `setOmitted(false)` értéket, a Nette tartalmazza az értéküket ezekben az adatokban. -Ha alapértelmezett értéket állít be egy mezőhöz, akkor ezt csak a mező letiltása után szabad megtennie: +A `setDisabled()` meghívásakor a mező értéke törlődik. Ha alapértelmezett értéket állít be, akkor azt a deaktiválás után kell megtennie: ```php $form->addText('username', 'User name:') diff --git a/forms/it/controls.texy b/forms/it/controls.texy index 8664dfb24a..1155aaa398 100644 --- a/forms/it/controls.texy +++ b/forms/it/controls.texy @@ -412,9 +412,9 @@ $form->addText('username', 'User name:') ->setDisabled(); ``` -Si noti che il browser non invia affatto i campi disabilitati al server, quindi non li si troverà nemmeno nei dati restituiti dalla funzione `$form->getValues()`. +I campi disabilitati non vengono inviati dal browser al server, quindi non sono presenti nei dati restituiti dalla funzione `$form->getValues()`. Tuttavia, se si imposta `setOmitted(false)`, Nette includerà il loro valore in questi dati. -Se si imposta un valore predefinito per un campo, è necessario farlo solo dopo averlo disabilitato: +Quando si chiama `setDisabled()`, il valore del campo viene cancellato. Se si imposta un valore predefinito, è necessario farlo dopo averlo disattivato: ```php $form->addText('username', 'User name:') diff --git a/forms/pl/controls.texy b/forms/pl/controls.texy index 4122784d06..c81b9eb35e 100644 --- a/forms/pl/controls.texy +++ b/forms/pl/controls.texy @@ -412,9 +412,9 @@ $form->addText('username', 'Uživatelské jméno:') ->setDisabled(); ``` -Należy pamiętać, że elementy wyłączone nie są w ogóle wysyłane przez przeglądarkę do serwera, więc nie znajdziemy ich w danych zwracanych przez funkcję `$form->getValues()`. +Wyłączone pola nie są w ogóle wysyłane przez przeglądarkę do serwera, więc nie znajdziesz ich w danych zwracanych przez funkcję `$form->getValues()`. Jeśli jednak ustawisz `setOmitted(false)`, Nette uwzględni ich wartość w tych danych. -Jeśli ustawisz wartość domyślną dla elementu, musisz to zrobić dopiero po jego dezaktywacji: +Po wywołaniu funkcji `setDisabled()`, wartość pola zostanie usunięta. Jeśli ustawiasz wartość domyślną, musisz to zrobić po jej dezaktywacji: ```php $form->addText('username', 'Uživatelské jméno:') diff --git a/forms/pt/controls.texy b/forms/pt/controls.texy index 5f26051d84..7436750031 100644 --- a/forms/pt/controls.texy +++ b/forms/pt/controls.texy @@ -412,9 +412,9 @@ $form->addText('username', 'User name:') ->setDisabled(); ``` -Note que o navegador não envia os campos desativados para o servidor, portanto você não os encontrará nem mesmo nos dados devolvidos pela função `$form->getValues()`. +Os campos desabilitados não são enviados pelo navegador ao servidor, portanto, você não os encontrará nos dados retornados pela função `$form->getValues()`. Entretanto, se você definir `setOmitted(false)`, a Nette incluirá o valor deles nesses dados. -Se você estiver definindo um valor padrão para um campo, você deve fazê-lo somente após desativá-lo: +Quando você chamar `setDisabled()`, o valor do campo será excluído. Se você estiver definindo um valor padrão, deverá fazê-lo depois de desativá-lo: ```php $form->addText('username', 'User name:') diff --git a/forms/ro/controls.texy b/forms/ro/controls.texy index 9c3dca2fe9..41ec7f51b8 100644 --- a/forms/ro/controls.texy +++ b/forms/ro/controls.texy @@ -412,9 +412,9 @@ $form->addText('username', 'User name:') ->setDisabled(); ``` -Rețineți că browserul nu trimite deloc câmpurile dezactivate către server, astfel încât nici măcar nu le veți găsi în datele returnate de funcția `$form->getValues()`. +Câmpurile dezactivate nu sunt trimise de către browser către server, deci nu le veți găsi în datele returnate de funcția `$form->getValues()`. Cu toate acestea, dacă setați `setOmitted(false)`, Nette va include valoarea lor în aceste date. -Dacă setați o valoare implicită pentru un câmp, trebuie să faceți acest lucru numai după ce l-ați dezactivat: +Atunci când apelați `setDisabled()`, valoarea câmpului este ștearsă. Dacă setați o valoare implicită, trebuie să faceți acest lucru după dezactivarea acesteia: ```php $form->addText('username', 'User name:') diff --git a/forms/ru/controls.texy b/forms/ru/controls.texy index d2efd260ae..b5b1721d51 100644 --- a/forms/ru/controls.texy +++ b/forms/ru/controls.texy @@ -412,9 +412,9 @@ $form->addText('username', 'Имя пользователя:') ->setDisabled(); ``` -Обратите внимание, что браузер вообще не отправляет отключенные поля на сервер, поэтому вы даже не найдете их в данных, возвращаемых функцией `$form->getValues()`. +Отключенные поля вообще не посылаются браузером на сервер, поэтому в данных, возвращаемых функцией `$form->getValues()`, их не найти. Однако если задать `setOmitted(false)`, то Nette включит их значение в эти данные. -Если вы устанавливаете значение по умолчанию для поля, вы должны сделать это только после его отключения: +При вызове функции `setDisabled()` значение поля удаляется. Если вы задаете значение по умолчанию, то делать это нужно после его отключения: ```php $form->addText('username', 'Имя пользователя:') diff --git a/forms/sl/controls.texy b/forms/sl/controls.texy index 8edc2d797a..dbc503a563 100644 --- a/forms/sl/controls.texy +++ b/forms/sl/controls.texy @@ -412,9 +412,9 @@ $form->addText('username', 'User name:') ->setDisabled(); ``` -Upoštevajte, da brskalnik onemogočenih polj sploh ne pošlje strežniku, zato jih ne boste našli niti v podatkih, ki jih vrne funkcija `$form->getValues()`. +Brskalnik onemogočenih polj sploh ne pošlje strežniku, zato jih v podatkih, ki jih vrne funkcija `$form->getValues()`, ne boste našli. Če pa nastavite `setOmitted(false)`, bo Nette njihovo vrednost vključil v te podatke. -Če polju določate privzeto vrednost, morate to storiti šele potem, ko ste ga onemogočili: +Ko pokličete `setDisabled()`, se vrednost polja izbriše. Če nastavljate privzeto vrednost, morate to storiti po tem, ko ste jo deaktivirali: ```php $form->addText('username', 'User name:') diff --git a/forms/tr/controls.texy b/forms/tr/controls.texy index 0db003ff2e..c2a5215541 100644 --- a/forms/tr/controls.texy +++ b/forms/tr/controls.texy @@ -412,9 +412,9 @@ $form->addText('username', 'User name:') ->setDisabled(); ``` -Tarayıcının devre dışı bırakılan alanları sunucuya göndermediğini unutmayın, bu nedenle bunları `$form->getValues()` işlevi tarafından döndürülen verilerde bile bulamazsınız. +Devre dışı bırakılan alanlar tarayıcı tarafından sunucuya gönderilmez, bu nedenle `$form->getValues()` işlevi tarafından döndürülen verilerde bunları bulamazsınız. Ancak, `setOmitted(false)` adresini ayarlarsanız, Nette bunların değerini bu veriye dahil edecektir. -Bir alan için varsayılan bir değer ayarlıyorsanız, bunu yalnızca devre dışı bıraktıktan sonra yapmalısınız: + `setDisabled()` adresini çağırdığınızda, alanın değeri silinir. Varsayılan bir değer ayarlıyorsanız, bunu devre dışı bıraktıktan sonra yapmalısınız: ```php $form->addText('username', 'User name:') diff --git a/forms/uk/controls.texy b/forms/uk/controls.texy index 5c8e9804c0..c32e802012 100644 --- a/forms/uk/controls.texy +++ b/forms/uk/controls.texy @@ -412,9 +412,9 @@ $form->addText('username', 'Имя пользователя:') ->setDisabled(); ``` -Зверніть увагу, що браузер узагалі не надсилає відключені поля на сервер, тому ви навіть не знайдете їх у даних, які повертає функція `$form->getValues()`. +Вимкнені поля взагалі не надсилаються браузером на сервер, тому ви не знайдете їх у даних, що повертаються функцією `$form->getValues()`. Однак, якщо ви задасте `setOmitted(false)`, Nette включить їх значення в ці дані. -Якщо ви встановлюєте значення за замовчуванням для поля, ви повинні зробити це тільки після його вимкнення: +При виклику `setDisabled()` значення поля видаляється. Якщо ви встановлюєте значення за замовчуванням, ви повинні зробити це після його деактивації: ```php $form->addText('username', 'Имя пользователя:') From 2b7b21af2f52a1513a59a65f68f67398ece4a370 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 24 Oct 2023 23:24:19 +0200 Subject: [PATCH 027/137] intro to oop --- ...uction-to-object-oriented-programming.texy | 719 +++++++++++++++++ ...uction-to-object-oriented-programming.texy | 719 +++++++++++++++++ ...uction-to-object-oriented-programming.texy | 719 +++++++++++++++++ ...uction-to-object-oriented-programming.texy | 719 +++++++++++++++++ ...uction-to-object-oriented-programming.texy | 719 +++++++++++++++++ ...uction-to-object-oriented-programming.texy | 719 +++++++++++++++++ ...uction-to-object-oriented-programming.texy | 719 +++++++++++++++++ ...uction-to-object-oriented-programming.texy | 719 +++++++++++++++++ ...uction-to-object-oriented-programming.texy | 719 +++++++++++++++++ ...uction-to-object-oriented-programming.texy | 719 +++++++++++++++++ ...uction-to-object-oriented-programming.texy | 719 +++++++++++++++++ ...uction-to-object-oriented-programming.texy | 719 +++++++++++++++++ ...uction-to-object-oriented-programming.texy | 719 +++++++++++++++++ ...uction-to-object-oriented-programming.texy | 719 +++++++++++++++++ ...uction-to-object-oriented-programming.texy | 725 ++++++++++++++++++ ...uction-to-object-oriented-programming.texy | 719 +++++++++++++++++ 16 files changed, 11510 insertions(+) create mode 100644 nette/bg/introduction-to-object-oriented-programming.texy create mode 100644 nette/cs/introduction-to-object-oriented-programming.texy create mode 100644 nette/de/introduction-to-object-oriented-programming.texy create mode 100644 nette/el/introduction-to-object-oriented-programming.texy create mode 100644 nette/en/introduction-to-object-oriented-programming.texy create mode 100644 nette/es/introduction-to-object-oriented-programming.texy create mode 100644 nette/fr/introduction-to-object-oriented-programming.texy create mode 100644 nette/hu/introduction-to-object-oriented-programming.texy create mode 100644 nette/it/introduction-to-object-oriented-programming.texy create mode 100644 nette/pl/introduction-to-object-oriented-programming.texy create mode 100644 nette/pt/introduction-to-object-oriented-programming.texy create mode 100644 nette/ro/introduction-to-object-oriented-programming.texy create mode 100644 nette/ru/introduction-to-object-oriented-programming.texy create mode 100644 nette/sl/introduction-to-object-oriented-programming.texy create mode 100644 nette/tr/introduction-to-object-oriented-programming.texy create mode 100644 nette/uk/introduction-to-object-oriented-programming.texy diff --git a/nette/bg/introduction-to-object-oriented-programming.texy b/nette/bg/introduction-to-object-oriented-programming.texy new file mode 100644 index 0000000000..12388a51fc --- /dev/null +++ b/nette/bg/introduction-to-object-oriented-programming.texy @@ -0,0 +1,719 @@ +Въведение в обектно-ориентираното програмиране +********************************************** + +.[perex] +Терминът "ООП" означава обектно-ориентирано програмиране, което е начин за организиране и структуриране на кода. ООП ни позволява да разглеждаме една програма като колекция от обекти, които комуникират помежду си, а не като последователност от команди и функции. + +В ООП "обект" е единица, която съдържа данни и функции, които работят с тези данни. Обектите се създават въз основа на "класове", които могат да се разбират като проекти или шаблони за обекти. След като разполагаме с клас, можем да създадем негов "екземпляр", който е конкретен обект, създаден от този клас. + +Нека разгледаме как можем да създадем прост клас в PHP. Когато дефинираме клас, използваме ключовата дума "class", последвана от името на класа, и след това къдрави скоби, които ограждат функциите на класа (наречени "методи") и променливите на класа (наречени "свойства" или "атрибути"): + +```php +class Car +{ + function honk() + { + echo 'Beep beep!'; + } +} +``` + +В този пример създадохме клас на име `Car` с една функция (или "метод"), наречена `honk`. + +Всеки клас трябва да реши само една основна задача. Ако един клас решава твърде много задачи, може да е подходящо да го разделите на по-малки, специализирани класове. + +Обикновено класовете се съхраняват в отделни файлове, за да се запази организацията на кода и да се улесни навигацията в него. Името на файла трябва да съвпада с името на класа, така че за класа `Car` името на файла ще бъде `Car.php`. + +При именуването на класовете е добре да се следва конвенцията "PascalCase", което означава, че всяка дума в името започва с главна буква и няма подчертавания или други разделители. Методите и свойствата следват конвенцията "camelCase", което означава, че започват с малка буква. + +Някои методи в PHP имат специални роли и се предхождат от `__` (две подчертавания). Един от най-важните специални методи е "конструкторът", обозначен като `__construct`. Конструкторът е метод, който се извиква автоматично при създаването на нова инстанция на даден клас. + +Често използваме конструктора, за да зададем първоначалното състояние на даден обект. Например, когато създавате обект, представляващ човек, може да използвате конструктора, за да зададете неговата възраст, име или други атрибути. + +Нека видим как да използваме конструктор в PHP: + +```php +class Person +{ + private $age; + + function __construct($age) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +$person = new Person(25); +echo $person->howOldAreYou(); // Outputs: 25 +``` + +В този пример класът `Person` има свойство `$age` и конструктор, който задава това свойство. След това методът `howOldAreYou()` осигурява достъп до възрастта на лицето. + +Ключовата дума `new` се използва за създаване на нов екземпляр на даден клас. В горния пример създадохме ново лице на възраст 25 години. + +Можете също така да зададете стойности по подразбиране за параметрите на конструктора, ако те не са зададени при създаването на обект. Например: + +```php +class Person +{ + private $age; + + function __construct($age = 20) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +$person = new Person; // if no argument is passed, parentheses can be omitted +echo $person->howOldAreYou(); // Outputs: 20 +``` + +В този пример, ако не посочите възраст при създаването на обект `Person`, ще бъде използвана стойността по подразбиране 20. + +И накрая, дефинирането на свойството с неговата инициализация чрез конструктора може да бъде съкратено и опростено по следния начин: + +```php +class Person +{ + function __construct( + private $age = 20, + ) { + } +} +``` + + +Пространства от имена .[#toc-namespaces] +---------------------------------------- + +Пространствата от имена ни позволяват да организираме и групираме свързани класове, функции и константи, като избягваме конфликти в наименованията. Можете да си ги представите като папки на компютъра, където всяка папка съдържа файлове, свързани с конкретен проект или тема. + +Пространствата от имена са особено полезни в по-големи проекти или при използване на библиотеки на трети страни, където могат да възникнат конфликти в наименованията на класовете. + +Представете си, че в проекта ви има клас с име `Car` и искате да го поставите в пространство от имена, наречено `Transport`. Ще го направите по следния начин: + +```php +namespace Transport; + +class Car +{ + function honk() + { + echo 'Beep beep!'; + } +} +``` + +Ако искате да използвате класа `Car` в друг файл, трябва да посочите от кое пространство от имена произхожда класът: + +```php +$car = new Transport\Car; +``` + +За улеснение можете да посочите в началото на файла кой клас от определено пространство от имена искате да използвате, което ви позволява да създавате екземпляри, без да посочвате пълния път: + +```php +use Transport\Car; + +$car = new Car; +``` + + +Наследяване .[#toc-inheritance] +------------------------------- + +Наследяването е инструмент на обектно-ориентираното програмиране, който позволява създаването на нови класове на базата на съществуващи, като се наследяват техните свойства и методи и се разширяват или предефинират при необходимост. Наследяването осигурява повторна използваемост на кода и йерархичност на класовете. + +Казано по-просто, ако имаме един клас и искаме да създадем друг, производен от него, но с някои модификации, можем да "наследим" новия клас от оригиналния. + +В PHP наследяването се реализира с помощта на ключовата дума `extends`. + +Нашият клас `Person` съхранява информация за възрастта. Можем да имаме друг клас, `Student`, който разширява `Person` и добавя информация за областта на обучение. + +Нека разгледаме един пример: + +```php +class Person +{ + private $age; + + function __construct($age) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +class Student extends Person +{ + private $fieldOfStudy; + + function __construct($age, $fieldOfStudy) + { + parent::__construct($age); + $this->fieldOfStudy = $fieldOfStudy; + } + + function printInformation() + { + echo 'Age of student: ', $this->howOldAreYou(); + echo 'Field of study: ', $this->fieldOfStudy; + } +} + +$student = new Student(20, 'Computer Science'); +$student->printInformation(); +``` + +Как работи този код? + +- Използвахме ключовата дума `extends`, за да разширим класа `Person`, което означава, че класът `Student` наследява всички методи и свойства от `Person`. + +- Ключовата дума `parent::` ни позволява да извикваме методи от родителския клас. В този случай извикахме конструктора от класа `Person`, преди да добавим наша собствена функционалност към класа `Student`. + +Наследяването е предназначено за ситуации, в които между класовете има връзка "е а". Например, клас `Student` е клас `Person`. Котката е животно. То ни позволява в случаите, когато в кода очакваме един обект (например "Човек"), да използваме вместо него производен обект (например "Ученик"). + +От съществено значение е да осъзнаем, че основната цел на наследяването **не е** да предотврати дублирането на кода. Напротив, неправилното използване на наследяването може да доведе до сложен и труден за поддържане код. Ако между класовете няма връзка "е а", трябва да помислим за композиция вместо за наследяване. + + +Композиция .[#toc-composition] +------------------------------ + +Композицията е техника, при която вместо да наследяваме свойства и методи от друг клас, просто използваме негова инстанция в нашия клас. Това ни позволява да комбинираме функционалностите и свойствата на няколко класа, без да създаваме сложни структури на наследяване. + +Например, имаме клас `Engine` и клас `Car`. Вместо да кажем "Колата е двигател", казваме "Колата има двигател", което е типична композиционна връзка. + +```php +class Engine +{ + function start() + { + echo "Engine is running."; + } +} + +class Car +{ + private $engine; + + function __construct() + { + $this->engine = new Engine; + } + + function start() + { + $this->engine->start(); + echo "The car is ready to drive!"; + } +} + +$car = new Car; +$car->start(); +``` + +Тук `Car` не притежава всички свойства и методи на `Engine`, но има достъп до тях чрез свойството `$engine`. + +Предимството на композицията е по-голямата гъвкавост на дизайна и по-добрата адаптивност към бъдещи промени. + + +Видимост .[#toc-visibility] +--------------------------- + +В PHP можете да дефинирате "видимост" за свойствата, методите и константите на класа. Видимостта определя къде можете да получите достъп до тези елементи. + +1. **Публично:** Ако даден елемент е отбелязан като `public`, това означава, че имате достъп до него отвсякъде, дори извън класа. + +2. **Защитен:** Елемент, маркиран като `protected`, е достъпен само в рамките на класа и всички негови наследници (класове, които наследяват от него). + +3. **Приватно:** Ако даден елемент е обозначен като `private`, можете да имате достъп до него само в рамките на класа, в който е дефиниран. + +Ако не посочите видимост, PHP автоматично ще я зададе на `public`. + +Нека разгледаме примерен код: + +```php +class VisibilityExample +{ + public $publicProperty = 'Public'; + protected $protectedProperty = 'Protected'; + private $privateProperty = 'Private'; + + public function printProperties() + { + echo $this->publicProperty; // Works + echo $this->protectedProperty; // Works + echo $this->privateProperty; // Works + } +} + +$object = new VisibilityExample; +$object->printProperties(); +echo $object->publicProperty; // Works +// echo $object->protectedProperty; // Throws an error +// echo $object->privateProperty; // Throws an error +``` + +Продължаваме с наследяването на класове: + +```php +class ChildClass extends VisibilityExample +{ + public function printProperties() + { + echo $this->publicProperty; // Works + echo $this->protectedProperty; // Works + // echo $this->privateProperty; // Throws an error + } +} +``` + +В този случай методът `printProperties()` в `ChildClass` има достъп до публичните и защитените свойства, но няма достъп до частните свойства на родителския клас. + +Данните и методите трябва да са възможно най-скрити и достъпни само чрез определен интерфейс. Това ви позволява да променяте вътрешната имплементация на класа, без да засягате останалата част от кода. + + +Финална ключова дума .[#toc-final-keyword] +------------------------------------------ + +В PHP можем да използваме ключовата дума `final`, ако искаме да предотвратим наследяването или пренаписването на даден клас, метод или константа. Когато даден клас е маркиран като `final`, той не може да бъде разширяван. Когато даден метод е маркиран като `final`, той не може да бъде презаписван в подклас. + +Знанието, че даден клас или метод вече няма да бъде променян, ни позволява да правим промени по-лесно, без да се притесняваме за потенциални конфликти. Например можем да добавим нов метод, без да се страхуваме, че някой потомък вече има метод със същото име, което ще доведе до колизия. Или пък можем да променим параметрите на метод, отново без риск да предизвикаме несъответствие с надграден метод в наследник. + +```php +final class FinalClass +{ +} + +// The following code will throw an error because we cannot inherit from a final class. +class ChildOfFinalClass extends FinalClass +{ +} +``` + +В този пример опитът за наследяване от крайния клас `FinalClass` ще доведе до грешка. + + +Статични свойства и методи .[#toc-static-properties-and-methods] +---------------------------------------------------------------- + +Когато говорим за "статични" елементи на даден клас в PHP, имаме предвид методи и свойства, които принадлежат на самия клас, а не на конкретна инстанция на класа. Това означава, че не е необходимо да създавате инстанция на класа, за да имате достъп до тях. Вместо това ги извиквате или получавате достъп до тях директно чрез името на класа. + +Имайте предвид, че тъй като статичните елементи принадлежат на класа, а не на неговите инстанции, не можете да използвате псевдопроменливата `$this` вътре в статичните методи. + +Използването на статични свойства води до [затрупан код, пълен с капани |dependency-injection:global-state], затова никога не трябва да ги използвате и тук няма да показваме пример. От друга страна, статичните методи са полезни. Ето един пример: + +```php +class Calculator +{ + public static function add($a, $b) + { + return $a + $b; + } + + public static function subtract($a, $b) + { + return $a - $b; + } +} + +// Using the static method without creating an instance of the class +echo Calculator::add(5, 3); // Output: 8 +echo Calculator::subtract(5, 3); // Output: 2 +``` + +В този пример създадохме клас `Calculator` с два статични метода. Можем да извикаме тези методи директно, без да създаваме инстанция на класа, като използваме оператора `::`. Статичните методи са особено полезни за операции, които не зависят от състоянието на конкретна инстанция на класа. + + +Константи на класа .[#toc-class-constants] +------------------------------------------ + +В рамките на класовете имаме възможност да дефинираме константи. Константите са стойности, които никога не се променят по време на изпълнението на програмата. За разлика от променливите, стойността на една константа остава непроменена. + +```php +class Car +{ + public const NumberOfWheels = 4; + + public function displayNumberOfWheels(): int + { + echo self::NumberOfWheels; + } +} + +echo Car::NumberOfWheels; // Output: 4 +``` + +В този пример имаме клас `Car` с константата `NumberOfWheels`. Когато получаваме достъп до константата вътре в класа, можем да използваме ключовата дума `self` вместо името на класа. + + +Интерфейси на обекти .[#toc-object-interfaces] +---------------------------------------------- + +Интерфейсите на обектите действат като "договори" за класовете. Ако един клас трябва да имплементира обектния интерфейс, той трябва да съдържа всички методи, които интерфейсът дефинира. Това е чудесен начин да се гарантира, че определени класове се придържат към един и същ "договор" или структура. + +В PHP интерфейсите се дефинират с помощта на ключовата дума `interface`. Всички методи, дефинирани в даден интерфейс, са публични (`public`). Когато даден клас имплементира интерфейс, той използва ключовата дума `implements`. + +```php +interface Animal +{ + function makeSound(); +} + +class Cat implements Animal +{ + public function makeSound() + { + echo 'Meow'; + } +} + +$cat = new Cat; +$cat->makeSound(); +``` + +Ако даден клас имплементира интерфейс, но не са дефинирани всички очаквани методи, PHP ще хвърли грешка. Един клас може да имплементира няколко интерфейса едновременно, което е различно от наследяването, при което класът може да наследява само от един клас. + + +Абстрактни класове .[#toc-abstract-classes] +------------------------------------------- + +Абстрактните класове служат като базови шаблони за други класове, но не можете да създавате техни екземпляри директно. Те съдържат комбинация от пълни методи и абстрактни методи, които нямат определено съдържание. Класовете, които наследяват от абстрактни класове, трябва да предоставят дефиниции за всички абстрактни методи от родителя. + +Използваме ключовата дума `abstract`, за да дефинираме абстрактен клас. + +```php +abstract class AbstractClass +{ + public function regularMethod() + { + echo 'This is a regular method'; + } + + abstract public function abstractMethod(); +} + +class Child extends AbstractClass +{ + public function abstractMethod() + { + echo 'This is the implementation of the abstract method'; + } +} + +$instance = new Child; +$instance->regularMethod(); +$instance->abstractMethod(); +``` + +В този пример имаме абстрактен клас с един обикновен и един абстрактен метод. След това имаме клас `Child`, който наследява от `AbstractClass` и предоставя имплементация за абстрактния метод. + + +Проверка на типа .[#toc-type-checking] +-------------------------------------- + +В програмирането е изключително важно да се уверим, че данните, с които работим, са от правилния тип. В PHP разполагаме с инструменти, които осигуряват тази сигурност. Проверката на това дали данните са от правилния тип се нарича "проверка на типа". + +Типове, които можем да срещнем в PHP: + +1. **Основни типове**: Те включват `int` (цели числа), `float` (числа с плаваща запетая), `bool` (булеви стойности), `string` (низове), `array` (масиви) и `null`. +2. **Класове**: Когато искаме дадена стойност да бъде инстанция на определен клас. +3. **Интерфейси**: Определя набор от методи, които даден клас трябва да имплементира. Стойност, която отговаря на даден интерфейс, трябва да има тези методи. +4. **Смесени типове**: Можем да укажем, че дадена променлива може да има няколко разрешени типа. +5. **Void**: Този специален тип указва, че функцията или методът не връщат никаква стойност. + +Нека да видим как да модифицираме кода, за да включим типовете: + +```php +class Person +{ + private int $age; + + public function __construct(int $age) + { + $this->age = $age; + } + + public function printAge(): void + { + echo "This person is " . $this->age . " years old."; + } +} + +/** + * A function that accepts a Person object and prints the person's age. + */ +function printPersonAge(Person $person): void +{ + $person->printAge(); +} +``` + +По този начин гарантираме, че нашият код очаква и работи с данни от правилния тип, което ни помага да предотвратим потенциални грешки. + + +Сравнение и идентичност .[#toc-comparison-and-identity] +------------------------------------------------------- + +В PHP можете да сравнявате обекти по два начина: + +1. Сравняване на стойности `==`: Проверява се дали обектите са от един и същи клас и имат еднакви стойности в свойствата си. +2. Сравнение на идентичността `===`: Проверява се дали става въпрос за една и съща инстанция на обекта. + +```php +class Car +{ + public string $brand; + + public function __construct(string $brand) + { + $this->brand = $brand; + } +} + +$car1 = new Car('Skoda'); +$car2 = new Car('Skoda'); +$car3 = $car1; + +var_dump($car1 == $car2); // true, because they have the same value +var_dump($car1 === $car2); // false, because they are not the same instance +var_dump($car1 === $car3); // true, because $car3 is the same instance as $car1 +``` + + +Операторът на `instanceof` .[#toc-the-instanceof-operator] +---------------------------------------------------------- + +Операторът `instanceof` ви позволява да определите дали даден обект е инстанция на определен клас, потомък на този клас или дали реализира определен интерфейс. + +Представете си, че имаме клас `Person` и друг клас `Student`, който е потомък на `Person`: + +```php +class Person +{ + private int $age; + + public function __construct(int $age) + { + $this->age = $age; + } +} + +class Student extends Person +{ + private string $major; + + public function __construct(int $age, string $major) + { + parent::__construct($age); + $this->major = $major; + } +} + +$student = new Student(20, 'Computer Science'); + +// Check if $student is an instance of the Student class +var_dump($student instanceof Student); // Output: bool(true) + +// Check if $student is an instance of the Person class (because Student is a descendant of Person) +var_dump($student instanceof Person); // Output: bool(true) +``` + +От изводите е видно, че обектът `$student` се счита за инстанция на двата класа `Student` и `Person`. + + +Флуентни интерфейси .[#toc-fluent-interfaces] +--------------------------------------------- + +"Флуентен интерфейс" е техника в ООП, която позволява верижно свързване на методи с едно извикване. Това често опростява и изяснява кода. + +Ключовият елемент на плавния интерфейс е, че всеки метод във веригата връща референция към текущия обект. Това се постига чрез използване на `return $this;` в края на метода. Този стил на програмиране често се свързва с методите, наречени "setters", които задават стойностите на свойствата на даден обект. + +Нека да видим как може да изглежда един плавен интерфейс за изпращане на имейли: + +```php +public function sendMessage() +{ + $email = new Email; + $email->setFrom('sender@example.com') + ->setRecipient('admin@example.com') + ->setMessage('Hello, this is a message.') + ->send(); +} +``` + +В този пример методите `setFrom()`, `setRecipient()` и `setMessage()` се използват за задаване на съответните стойности (изпращач, получател, съдържание на съобщението). След задаването на всяка от тези стойности методите връщат текущия обект (`$email`), което ни позволява да верижно да използваме друг метод след него. Накрая извикваме метода `send()`, който всъщност изпраща електронното писмо. + +Благодарение на плавните интерфейси можем да пишем код, който е интуитивен и лесно четим. + + +Копиране с `clone` .[#toc-copying-with-clone] +--------------------------------------------- + +В PHP можем да създадем копие на даден обект, като използваме оператора `clone`. По този начин получаваме нов екземпляр с идентично съдържание. + +Ако при копирането на обект трябва да променим някои от неговите свойства, можем да дефинираме специален метод `__clone()` в класа. Този метод се извиква автоматично, когато обектът се клонира. + +```php +class Sheep +{ + public string $name; + + public function __construct(string $name) + { + $this->name = $name; + } + + public function __clone() + { + $this->name = 'Clone of ' . $this->name; + } +} + +$original = new Sheep('Dolly'); +echo $original->name . "\n"; // Outputs: Dolly + +$clone = clone $original; +echo $clone->name . "\n"; // Outputs: Clone of Dolly +``` + +В този пример имаме клас `Sheep` с едно свойство `$name`. Когато клонираме екземпляр на този клас, методът `__clone()` гарантира, че името на клонираната овца ще получи префикс "Clone of". + + +Признаци .[#toc-traits] +----------------------- + +Чертите в PHP са инструмент, който позволява споделянето на методи, свойства и константи между класовете и предотвратява дублирането на код. Можете да си ги представите като механизъм за "копиране и поставяне" (Ctrl-C и Ctrl-V), при който съдържанието на дадена черта се "вмъква" в класовете. Това ви позволява да използвате повторно кода, без да се налага да създавате сложни йерархии от класове. + +Нека разгледаме прост пример за използване на черти в PHP: + +```php +trait Honking +{ + public function honk() + { + echo 'Beep beep!'; + } +} + +class Car +{ + use Honking; +} + +class Truck +{ + use Honking; +} + +$car = new Car; +$car->honk(); // Outputs 'Beep beep!' + +$truck = new Truck; +$truck->honk(); // Also outputs 'Beep beep!' +``` + +В този пример имаме черта, наречена `Honking`, която съдържа един метод `honk()`. След това имаме два класа: `Car` и `Truck`, като и двата използват чертата `Honking`. В резултат на това и двата класа "притежават" метода `honk()` и можем да го извикаме върху обекти и от двата класа. + +Характеристиките позволяват лесно и ефективно споделяне на код между класовете. Те не влизат в йерархията на наследяване, т.е. `$car instanceof Honking` ще върне `false`. + + +Изключения +---------- + +Изключенията в ООП ни позволяват да обработваме и управляваме грешки, които могат да възникнат по време на изпълнението на нашия код. По същество те са обекти, предназначени да регистрират грешки или неочаквани ситуации във вашата програма. + +В PHP имаме вградения клас `Exception` за тези обекти. Той има няколко метода, които ни позволяват да получим повече информация за изключението, като например съобщение за грешка, файла и реда, където е възникнала грешката, и т.н. + +Когато възникне проблем, можем да "хвърлим" изключение (с помощта на `throw`). Ако искаме да "хванем" и обработим това изключение, използваме блоковете `try` и `catch`. + +Нека видим как работи това: + +```php +try { + throw new Exception('Message explaining the reason for the exception'); + + // This code won't execute + echo 'I am a message that nobody will read'; + +} catch (Exception $e) { + echo 'Exception caught: '. $e->getMessage(); +} +``` + +Важно е да се отбележи, че изключението може да бъде хвърлено по-надълбоко, по време на извикването на други методи. + +За един блок `try` могат да бъдат зададени няколко блока `catch`, ако очаквате различни видове изключения. + +Можем също така да създадем йерархия на изключенията, при която всеки клас на изключението наследява от предишния. Като пример, разгледайте едно просто банково приложение, което позволява депозити и тегления: + +```php +class BankingException extends Exception {} +class InsufficientFundsException extends BankingException {} +class ExceededLimitException extends BankingException {} + +class BankAccount +{ + private int $balance = 0; + private int $dailyLimit = 1000; + + public function deposit(int $amount): int + { + $this->balance += $amount; + return $this->balance; + } + + public function withdraw(int $amount): int + { + if ($amount > $this->balance) { + throw new InsufficientFundsException('Not enough funds in the account.'); + } + + if ($amount > $this->dailyLimit) { + throw new ExceededLimitException('Daily withdrawal limit exceeded.'); + } + + $this->balance -= $amount; + return $this->balance; + } +} + +$account = new BankAccount; +$account->deposit(500); + +try { + $account->withdraw(1500); +} catch (ExceededLimitException $e) { + echo $e->getMessage(); +} catch (InsufficientFundsException $e) { + echo $e->getMessage(); +} catch (BankingException $e) { + echo 'An error occurred during the operation.'; +} +``` + +В този пример е важно да се отбележи редът на блоковете `catch`. Тъй като всички изключения се наследяват от `BankingException`, ако имахме този блок първи, всички изключения щяха да бъдат уловени в него, без кодът да достига до следващите блокове `catch`. Затова е важно по-специфичните изключения (т.е. тези, които се наследяват от други) да бъдат по-нагоре в реда на блоковете `catch` от родителските си изключения. + + +Най-добри практики .[#toc-best-practices] +----------------------------------------- + +След като вече сте усвоили основните принципи на обектно-ориентираното програмиране, е изключително важно да се съсредоточите върху най-добрите практики в ООП. Те ще ви помогнат да пишете код, който е не само функционален, но и четим, разбираем и лесен за поддържане. + +1) **Отделяне на проблемите**: Всеки клас трябва да има ясно определена отговорност и да се занимава само с една основна задача. Ако даден клас върши твърде много неща, може да е подходящо да го разделите на по-малки, специализирани класове. +2) **Екапсулиране**: Данните и методите трябва да са възможно най-скрити и достъпни само чрез определен интерфейс. Това ви позволява да променяте вътрешната имплементация на даден клас, без да засягате останалата част от кода. +3) **Вкачване на зависимостта**: Вместо да създавате зависимости директно в класа, трябва да ги "инжектирате" отвън. За по-задълбочено разбиране на този принцип препоръчваме [главите, посветени на "Инжектиране на зависимости" (Dependency Injection) |dependency-injection:introduction]. diff --git a/nette/cs/introduction-to-object-oriented-programming.texy b/nette/cs/introduction-to-object-oriented-programming.texy new file mode 100644 index 0000000000..3d86fd5405 --- /dev/null +++ b/nette/cs/introduction-to-object-oriented-programming.texy @@ -0,0 +1,719 @@ +Úvod do objektově orientovaného programování +******************************************** + +.[perex] +Termín "OOP" označuje objektově orientované programování, což je způsob, jak organizovat a strukturovat kód. OOP nám umožňuje vidět program jako soubor objektů, které komunikují mezi sebou, místo sledu příkazů a funkcí. + +V OOP je "objekt" jednotka, která obsahuje data a funkce, které s těmito daty pracují. Objekty jsou vytvořeny podle "tříd", které můžeme chápat jako návrhy nebo šablony pro objekty. Když máme třídu, můžeme vytvořit její "instanci", což je konkrétní objekt vytvořený podle této třídy. + +Pojďme si ukázat, jak můžeme vytvořit jednoduchou třídu v PHP. Při definování třídy použijeme klíčové slovo "class", následované názvem třídy a pak složenými závorkami, které obklopují funkce (říká se jim "metody") a proměnné třídy (říká se jim "vlastnosti" nebo anglicky "property"): + +```php +class Auto +{ + function zatrub() + { + echo 'Bip bip!'; + } +} +``` + +V tomto příkladě jsme vytvořili třídu s názvem `Auto` s jednou funkcí (nebo "metodou") nazvanou `zatrub`. + +Každá třída by měla řešit pouze jeden hlavní úkol. Pokud třída dělá příliš mnoho věcí, může být vhodné ji rozdělit na menší, specializované třídy. + +Třídy obvykle ukládáme do samostatných souborů, aby byl kód organizovaný a snadno se v něm orientovalo. Název souboru by měl odpovídat názvu třídy, takže pro třídu `Auto` by název souboru byl `Auto.php`. + +Při pojmenování tříd je dobré držet se konvence "PascalCase", což znamená, že každé slovo v názvu začíná velkým písmenem a nejsou mezi nimi žádné podtržítka nebo jiné oddělovače. Metody a vlastnosti používají konvenci "camelCase", to znamená, že začínají malým písmenem. + +Některé metody v PHP mají speciální úlohy a jsou označené předponou `__` (dvě podtržítka). Jednou z nejdůležitějších speciálních metod je "konstruktor", který je označen jako `__construct`. Konstruktor je metoda, která se automaticky zavolá, když vytváříte novou instanci třídy. + +Konstruktor často používáme k nastavení počátečního stavu objektu. Například, když vytváříte objekt reprezentující osobu, můžete využit konstruktor k nastavení jejího věku, jména nebo jiných vlastností. + +Pojďme si ukázat, jak použít konstruktor v PHP: + +```php +class Osoba +{ + private $vek; + + function __construct($vek) + { + $this->vek = $vek; + } + + function kolikJeTiLet() + { + return $this->vek; + } +} + +$osoba = new Osoba(25); +echo $osoba->kolikJeTiLet(); // Vypíše: 25 +``` + +V tomto příkladě třída `Osoba` má vlastnost `$vek` a dále konstruktor, který nastavuje tuto vlastnost. Metoda `kolikJeTiLet()` pak umožňuje přístup k věku osoby. + +Klíčové slovo `new` se používá k vytvoření nové instance třídy. Ve výše uvedeném příkladu jsme vytvořili novou osobu s věkem 25. + +Můžete také nastavit výchozí hodnoty pro parametry konstruktoru, pokud nejsou při vytváření objektu specifikovány. Například: + +```php +class Osoba +{ + private $vek; + + function __construct($vek = 20) + { + $this->vek = $vek; + } + + function kolikJeTiLet() + { + return $this->vek; + } +} + +$osoba = new Osoba; // pokud nepředáváme žádný argument, lze závorky vynechat +echo $osoba->kolikJeTiLet(); // Vypíše: 20 +``` + +V tomto příkladě, pokud nezadáte věk při vytváření objektu `Osoba`, bude použita výchozí hodnota 20. + +A nakonec, definice vlastnosti s její inicializací přes konstruktor se dá takto zkrátit a zjednodušit: + +```php +class Osoba +{ + function __construct( + private $vek = 20, + ) { + } +} +``` + + +Jmenné prostory +--------------- + +Jmenné prostory (neboli "namespaces" v angličtině) nám umožňují organizovat a seskupovat související třídy, funkce a konstanty, a zároveň se vyhýbat konfliktům v názvech. Můžete si je představit jako složky v počítači, kde každá složka obsahuje soubory, které patří k určitému projektu nebo tématu. + +Jmenné prostory jsou obzvlášť užitečné ve větších projektech nebo když používáte knihovny od třetích stran, kde by mohly vzniknout konflikty v názvech tříd. + +Představte si, že máte třídu s názvem `Auto` ve vašem projektu a chcete ji umístit do jmenného prostoru nazvaného `Doprava`. Uděláte to takto: + +```php +namespace Doprava; + +class Auto +{ + function zatrub() + { + echo 'Bip bip!'; + } +} +``` + +Pokud chcete použít třídu `Auto` v jiném souboru, musíte specifikovat, z jakého jmenného prostoru třída pochází: + +```php +$auto = new Doprava\Auto; +``` + +Pro zjednodušení můžete na začátku souboru uvést, kterou třídu z daného jmenného prostoru chcete používat, což umožňuje vytvářet instance bez nutnosti uvádět celou cestu: + +```php +use Doprava\Auto; + +$auto = new Auto; +``` + + +Dědičnost +--------- + +Dědičnost je nástrojem objektově orientovaného programování, který umožňuje vytvářet nové třídy na základě již existujících tříd, přebírat jejich vlastnosti a metody a rozšiřovat nebo předefinovat je podle potřeby. Dědičnost umožňuje zajistit kódovou znovupoužitelnost a hierarchii tříd. + +Zjednodušeně řečeno, pokud máme jednu třídu a chtěli bychom vytvořit další, od ní odvozenou, ale s několika změnami, můžeme novou třídu "zdědit" z původní třídy. + +V PHP dědičnost realizujeme pomocí klíčového slova `extends`. + +Naše třída `Osoba` uchovává informaci o věku. Můžeme mít další třídu `Student`, která rozšiřuje `Osobu` a přidává informaci o oboru studia. + +Podívejme se na příklad: + +```php +class Osoba +{ + private $vek; + + function __construct($vek) + { + $this->vek = $vek; + } + + function kolikJeTiLet() + { + return $this->vek; + } +} + +class Student extends Osoba +{ + private $obor; + + function __construct($vek, $obor) + { + parent::__construct($vek); + $this->obor = $obor; + } + + function vypisInformace() + { + echo 'Věk studenta: ', $this->kolikJeTiLet(); + echo 'Obor studia: ', $this->obor; + } +} + +$student = new Student(20, 'Informatika'); +$student->vypisInformace(); +``` + +Jak tento kód funguje? + +- Použili jsme klíčové slovo `extends` k rozšíření třídy `Osoba`, což znamená, že třída `Student` zdědí všechny metody a vlastnosti z `Osoby`. + +- Klíčové slovo `parent::` nám umožňuje volat metody z nadřazené třídy. V tomto případě jsme volali konstruktor z třídy `Osoba` před přidáním vlastní funkcionality do třídy `Student`. + +Dědičnost je určená pro situace, kdy existuje vztah "je" mezi třídami. Například `Student` je `Osoba`. Kočka je zvíře. Dává nám možnost v případech, kdy v kódu očekáváme jeden objekt (např. "Osoba"), použít místo něj objekt zděděný (např. "Student"). + +Je důležité si uvědomit, že hlavním účelem dědičnosti **není** zabránit duplikaci kódu. Naopak, nesprávné využití dědičnosti může vést k složitému a těžko udržitelnému kódu. Pokud vztah "je" mezi třídami neexistuje, měli bychom místo dědičnosti uvažovat o kompozici. + + +Kompozice +--------- + +Kompozice je technika, kdy místo toho, abychom zdědili vlastnosti a metody jiné třídy, jednoduše využijeme její instanci v naší třídě. Toto nám umožňuje kombinovat funkcionality a vlastnosti více tříd bez nutnosti vytvářet složité dědičné struktury. + +Podívejme se na příklad. Máme třídu `Motor` a třídu `Auto`. Místo toho, abychom říkali "Auto je Motor", říkáme "Auto má Motor", což je typický vztah kompozice. + +```php +class Motor +{ + function zapni() + { + echo "Motor běží."; + } +} + +class Auto +{ + private $motor; + + function __construct() + { + $this->motor = new Motor; + } + + function start() + { + $this->motor->zapni(); + echo "Auto je připraveno k jízdě!"; + } +} + +$auto = new Auto; +$auto->start(); +``` + +Zde `Auto` nemá všechny vlastnosti a metody `Motoru`, ale má k němu přístup prostřednictvím vlastnosti `$motor`. + +Výhodou kompozice je větší flexibilita v designu a lepší možnost úprav v budoucnosti. + + +Viditelnost +----------- + +V PHP můžete definovat "viditelnost" pro vlastnosti, metody a konstanty třídy. Viditelnost určuje, odkud můžete přistupovat k těmto prvkům. + +1. **Public:** Pokud je prvek označen jako `public`, znamená to, že k němu můžete přistupovat odkudkoli, i mimo třídu. + +2. **Protected:** Prvek s označením `protected` je přístupný pouze v rámci dané třídy a všech jejích potomků (tříd, které dědí od této třídy). + +3. **Private:** Pokud je prvek `private`, můžete k němu přistupovat pouze zevnitř třídy, ve které byl definována. + +Pokud nespecifikujete viditelnost, PHP ji automaticky nastaví na `public`. + +Podívejme se na ukázkový kód: + +```php +class UkazkaViditelnosti +{ + public $verejnaVlastnost = 'Veřejná'; + protected $chranenaVlastnost = 'Chráněná'; + private $soukromaVlastnost = 'Soukromá'; + + public function vypisVlastnosti() + { + echo $this->verejnaVlastnost; // Funguje + echo $this->chranenaVlastnost; // Funguje + echo $this->soukromaVlastnost; // Funguje + } +} + +$objekt = new UkazkaViditelnosti; +$objekt->vypisVlastnosti(); +echo $objekt->verejnaVlastnost; // Funguje +// echo $objekt->chranenaVlastnost; // Vyhodí chybu +// echo $objekt->soukromaVlastnost; // Vyhodí chybu +``` + +Pokračujeme s děděním třídy: + +```php +class PotomekTridy extends UkazkaViditelnosti +{ + public function vypisVlastnosti() + { + echo $this->verejnaVlastnost; // Funguje + echo $this->chranenaVlastnost; // Funguje + // echo $this->soukromaVlastnost; // Vyhodí chybu + } +} +``` + +V tomto případě metoda `vypisVlastnosti()` v třídě `PotomekTřídy` může přistupovat k veřejným a chráněným vlastnostem, ale nemůže přistupovat k privátním vlastnostem rodičovské třídy. + +Data a metody by měly být co nejvíce skryté a přístupné pouze prostřednictvím definovaného rozhraní. To vám umožní měnit interní implementaci třídy bez ovlivnění zbytku kódu. + + +Klíčové slovo `final` +--------------------- + +V PHP můžeme použít klíčové slovo `final`, pokud chceme zabránit třídě, metodě nebo konstantě být zděděna nebo přepsána. Když označíme třídu jako `final`, nemůže být rozšířena. Když označíme metodu jako `final`, nemůže být v potomkovské třídě přepsána. + +Vědomí, že určitá třída nebo metoda nebude dále upravována, nám umožňuje snáze provádět úpravy, aniž bychom se museli obávat možných konfliktů. Například můžeme přidat novou metodu bez obav, že by některý její potomek už stejně pojmenovanou metodu měl a došlo by ke kolizi. Nebo metodě můžeme pozměnit jejich parametry, neboť opět nehrozí, že způsobíme nesoulad s přepsanou metodou v potomkovi. + +```php +final class FinalniTrida +{ +} + +// Následující kód vyvolá chybu, protože nemůžeme zdědit od finalní třídy. +class PotomekFinalniTridy extends FinalniTrida +{ +} +``` + +V tomto příkladu pokus o zdědění od finalní třídy `FinalniTrida` vyvolá chybu. + + +Statické vlastnosti a metody +---------------------------- + +Když v PHP mluvíme o "statických" prvcích třídy, myslíme tím metody a vlastnosti, které náleží samotné třídě, a ne konkrétní instanci této třídy. To znamená, že nemusíte vytvářet instanci třídy, abyste k nim měli přístup. Místo toho je voláte nebo přistupujete k nim přímo přes název třídy. + +Mějte na paměti, že jelikož statické prvky patří k třídě, a ne k jejím instancím, nemůžete uvnitř statických metod používat pseudoproměnnou `$this`. + +Používání statických vlastností vede k [nepřehlednému kódu plnému záludností|dependency-injection:global-state], proto byste je neměli nikdy použít a ani tu nebudeme ukazovat příklad použití. Naproti tomu statické metody jsou užitečné. Příklad použití: + +```php +class Kalkulator +{ + public static function scitani($a, $b) + { + return $a + $b; + } + + public static function odecitani($a, $b) + { + return $a - $b; + } +} + +// Použití statické metody bez vytvoření instance třídy +echo Kalkulator::scitani(5, 3); // Výsledek: 8 +echo Kalkulator::odecitani(5, 3); // Výsledek: 2 +``` + +V tomto příkladu jsme vytvořili třídu `Kalkulator` s dvěma statickými metodami. Tyto metody můžeme volat přímo bez vytvoření instance třídy pomocí `::` operátoru. Statické metody jsou obzvláště užitečné pro operace, které nezávisí na stavu konkrétní instance třídy. + + +Třídní konstanty +---------------- + +V rámci tříd máme možnost definovat konstanty. Konstanty jsou hodnoty, které se nikdy nezmění během běhu programu. Na rozdíl od proměnných, hodnota konstanty zůstává stále stejná. + +```php +class Auto +{ + public const PocetKol = 4; + + public function zobrazPocetKol(): int + { + echo self::PocetKol; + } +} + +echo Auto::PocetKol; // Výstup: 4 +``` + +V tomto příkladu máme třídu `Auto` s konstantou `PocetKol`. Když chceme přistupovat ke konstantě uvnitř třídy, můžeme použít klíčové slovo `self` místo názvu třídy. + + +Objektová rozhraní +------------------ + +Objektová rozhraní fungují jako "smlouvy" pro třídy. Pokud má třída implementovat objektové rozhraní, musí obsahovat všechny metody, které toto rozhraní definuje. Je to skvělý způsob, jak zajistit, že určité třídy dodržují stejnou "smlouvu" nebo strukturu. + +V PHP se rozhraní definuje klíčovým slovem `interface`. Všechny metody definované v rozhraní jsou veřejné (`public`). Když třída implementuje rozhraní, používá klíčové slovo `implements`. + +```php +interface Zvire +{ + function vydejZvuk(); +} + +class Kocka implements Zvire +{ + public function vydejZvuk() + { + echo 'Mňau'; + } +} + +$kocka = new Kocka; +$kocka->vydejZvuk(); +``` + +Pokud třída implementuje rozhraní, ale nejsou v ní definované všechny očekávané metody, PHP vyhodí chybu. Třída může implementovat více rozhraní najednou, což je rozdíl oproti dědičnosti, kde může třída dědit pouze od jedné třídy. + + +Abstraktní třídy +---------------- + +Abstraktní třídy slouží jako základní šablony pro jiné třídy, ale nemůžete vytvářet jejich instance přímo. Obsahují kombinaci kompletních metod a abstraktních metod, které nemají definovaný obsah. Třídy, které dědí z abstraktních tříd, musí poskytnout definice pro všechny abstraktní metody z předka. + +K definování abstraktní třídy používáme klíčové slovo `abstract`. + +```php +abstract class AbstraktniTrida +{ + public function obycejnaMetoda() + { + echo 'Toto je obyčejná metoda'; + } + + abstract public function abstraktniMetoda(); +} + +class Potomek extends AbstraktniTrida +{ + public function abstraktniMetoda() + { + echo 'Toto je implementace abstraktní metody'; + } +} + +$instance = new Potomek; +$instance->obycejnaMetoda(); +$instance->abstraktniMetoda(); +``` + +V tomto příkladu máme abstraktní třídu s jednou obyčejnou a jednou abstraktní metodou. Poté máme třídu `Potomek`, která dědí z `AbstraktniTrida` a poskytuje implementaci pro abstraktní metodu. + + +Typová kontrola +--------------- + +V programování je velmi důležité mít jistotu, že data, se kterými pracujeme, jsou správného typu. V PHP máme nástroje, které nám toto zajišťují. Ověřování, zda data mají správný typ, se nazývá "typová kontrola". + +Typy, na které můžeme v PHP narazit: + +1. **Základní typy**: Zahrnují `int` (celá čísla), `float` (desetinná čísla), `bool` (pravdivostní hodnoty), `string` (řetězce), `array` (pole) a `null`. +2. **Třídy**: Pokud chceme, aby hodnota byla instancí specifické třídy. +3. **Rozhraní**: Definuje soubor metod, které třída musí implementovat. Hodnota, která splňuje rozhraní, musí mít tyto metody. +4. **Smíšené typy**: Můžeme určit, že proměnná může mít více povolených typů. +5. **Void**: Tento speciální typ označuje, že funkce či metoda nevrací žádnou hodnotu. + +Pojďme si ukázat, jak upravit kód, aby zahrnoval typy: + +```php +class Osoba +{ + private int $vek; + + public function __construct(int $vek) + { + $this->vek = $vek; + } + + public function vypisVek(): void + { + echo "Této osobě je " . $this->vek . " let."; + } +} + +/** + * Funkce, která přijímá objekt třídy Osoba a vypíše věk osoby. + */ +function vypisVekOsoby(Osoba $osoba): void +{ + $osoba->vypisVek(); +} +``` + +Tímto způsobem jsme zajistili, že náš kód očekává a pracuje s daty správného typu, což nám pomáhá předcházet potenciálním chybám. + + +Porovnávání a identita +---------------------- + +V PHP můžete porovnávat objekty dvěma způsoby: + +1. Porovnání hodnot `==`: Zkontroluje, zda mají objekty jsou stejné třídy a mají stejné hodnoty ve svých vlastnostech. +2. Identita `===`: Zkontroluje, zda jde o stejnou instanci objektu. + +```php +class Auto +{ + public string $znacka; + + public function __construct(string $znacka) + { + $this->znacka = $znacka; + } +} + +$auto1 = new Auto('Skoda'); +$auto2 = new Auto('Skoda'); +$auto3 = $auto1; + +var_dump($auto1 == $auto2); // true, protože mají stejnou hodnotu +var_dump($auto1 === $auto2); // false, protože nejsou stejná instance +var_dump($auto1 === $auto3); // true, protože $auto3 je stejná instance jako $auto1 +``` + + +Operátor `instanceof` +--------------------- + +Operátor `instanceof` umožňuje zjistit, zda je daný objekt instancí určité třídy, potomka této třídy, nebo zda implementuje určité rozhraní. + +Představme si, že máme třídu `Osoba` a další třídu `Student`, která je potomkem třídy `Osoba`: + +```php +class Osoba +{ + private int $vek; + + public function __construct(int $vek) + { + $this->vek = $vek; + } +} + +class Student extends Osoba +{ + private string $obor; + + public function __construct(int $vek, string $obor) + { + parent::__construct($vek); + $this->obor = $obor; + } +} + +$student = new Student(20, 'Informatika'); + +// Ověření, zda je $student instancí třídy Student +var_dump($student instanceof Student); // Výstup: bool(true) + +// Ověření, zda je $student instancí třídy Osoba (protože Student je potomek Osoba) +var_dump($student instanceof Osoba); // Výstup: bool(true) +``` + +Z výstupů je patrné, že objekt `$student` je současně považován za instanci obou tříd - `Student` i `Osoba`. + + +Fluent Interfaces +----------------- + +"Plynulé rozhraní" (anglicky "Fluent Interface") je technika v OOP, která umožňuje řetězit metody dohromady v jednom volání. Tím se často zjednoduší a zpřehlední kód. + +Klíčovým prvkem plynulého rozhraní je, že každá metoda v řetězu vrací odkaz na aktuální objekt. Toho dosáhneme tak, že na konci metody použijeme `return $this;`. Tento styl programování je často spojován s metodami zvanými "setters", které nastavují hodnoty vlastností objektu. + +Ukážeme si, jak může vypadat plynulé rozhraní na příkladu odesílání emailů: + +```php +public function sendMessage() +{ + $email = new Email; + $email->setFrom('sender@example.com') + ->setRecipient('admin@example.com') + ->setMessage('Hello, this is a message.') + ->send(); +} +``` + +V tomto příkladě metody `setFrom()`, `setRecipient()` a `setMessage()` slouží k nastavení odpovídajících hodnot (odesílatele, příjemce, obsahu zprávy). Po nastavení každé z těchto hodnot nám metody vrací aktuální objekt (`$email`), což nám umožňuje řetězit další metodu za ní. Nakonec voláme metodu `send()`, která email skutečně odesílá. + +Díky plynulým rozhraním můžeme psát kód, který je intuitivní a snadno čitelný. + + +Kopírování pomocí `clone` +------------------------- + +V PHP můžeme vytvořit kopii objektu pomocí operátoru `clone`. Tímto způsobem dostaneme novou instanci s totožným obsahem. + +Pokud potřebujeme při kopírování objektu upravit některé jeho vlastnosti, můžeme ve třídě definovat speciální metodu `__clone()`. Tato metoda se automaticky zavolá, když je objekt klonován. + +```php +class Ovce +{ + public string $jmeno; + + public function __construct(string $jmeno) + { + $this->jmeno = $jmeno; + } + + public function __clone() + { + $this->jmeno = 'Klon ' . $this->jmeno; + } +} + +$original = new Ovce('Dolly'); +echo $original->jmeno . "\n"; // Vypíše: Dolly + +$klon = clone $original; +echo $klon->jmeno . "\n"; // Vypíše: Klon Dolly +``` + +V tomto příkladu máme třídu `Ovce` s jednou vlastností `$jmeno`. Když klonujeme instanci této třídy, metoda `__clone()` se postará o to, aby název klonované ovce získal předponu "Klon". + + +Traity +------ + +Traity v PHP jsou nástrojem, který umožňuje sdílet metody, vlastnosti a konstanty mezi třídami a zabránit duplicitě kódu. Můžete si je představit jako mechanismus "kopírovat a vložit" (Ctrl-C a Ctrl-V), kdy se obsah trait "vkládá" do tříd. To vám umožní znovupoužívat kód bez nutnosti vytvářet komplikované hierarchie tříd. + +Pojďme si ukázat jednoduchý příklad, jak používat traity v PHP: + +```php +trait Troubeni +{ + public function zatrub() + { + echo 'Bip bip!'; + } +} + +class Auto +{ + use Troubeni; +} + +class Nakladak +{ + use Troubeni; +} + +$auto = new Auto; +$auto->zatrub(); // Vypíše 'Bip bip!' + +$nakladak = new Nakladak; +$nakladak->zatrub(); // Také vypíše 'Bip bip!' +``` + +V tomto příkladu máme traitu nazvanou `Troubeni`, která obsahuje jednu metodu `zatrub()`. Poté máme dvě třídy: `Auto` a `Nakladak`, které obě používají traitu `Troubeni`. Díky tomu obě třídy "mají" metodu `zatrub()`, a můžeme ji volat na objektech obou tříd. + +Traity vám umožní snadno a efektivně sdílet kód mezi třídami. Přitom nevstupují do dědičné hierarchie, tj. `$auto instanceof Troubeni` vrátí `false`. + + +Výjimky +------- + +Výjimky v OOP nám umožňují řídit a ošetřovat chyby, které mohou vzniknout během provádění našeho kódu. Jsou to vlastně objekty určené k zaznamenání chyb nebo nečekaných situací ve vašem programu. + +V PHP máme pro tyto objekty k dispozici vestavěnou třídu `Exception`. Ta má několik metod, které nám umožňují získat více informací o výjimce, jako je zpráva o chybě, soubor a řádek, kde k chybě došlo, atd. + +Když se objeví problém, můžeme "vyhodit" výjimku (použitím `throw`). Chceme-li tuto výjimku "chytit" a nějak zpracovat, použijeme bloky `try` a `catch`. + +Ukážeme si, jak to funguje: + +```php +try { + throw new Exception('Zpráva vysvětlující důvod výjimky'); + + // Tento kód se neprovede + echo 'Jsem zpráva, kterou nikdo nepřečte'; + +} catch (Exception $e) { + echo 'Výjimka zachycena: '. $e->getMessage(); +} +``` + +Důležité je, že výjimka může být vyhozena hlouběji, při volání jiných metod. + +Pro jeden blok `try` lze uvést více bloků `catch`, pokud očekáváte různé typy výjimek. + +Zároveň můžeme vytvořit hierarchii výjimek, kde každá třída výjimky dědí od té předchozí. Jako příklad si představme jednoduchou bankovní aplikaci, která umožňuje provádět vklady a výběry: + +```php +class BankovniVyjimka extends Exception {} +class NedostatekProstredkuVyjimka extends BankovniVyjimka {} +class PrekroceniLimituVyjimka extends BankovniVyjimka {} + +class BankovniUcet +{ + private int $zustatek = 0; + private int $denniLimit = 1000; + + public function vlozit(int $castka): int + { + $this->zustatek += $castka; + return $this->zustatek; + } + + public function vybrat(int $castka): int + { + if ($castka > $this->zustatek) { + throw new NedostatekProstredkuVyjimka('Na účtu není dostatek prostředků.'); + } + + if ($castka > $this->denniLimit) { + throw new PrekroceniLimituVyjimka('Byl překročen denní limit pro výběry.'); + } + + $this->zustatek -= $castka; + return $this->zustatek; + } +} + +$ucet = new BankovniUcet; +$ucet->vlozit(500); + +try { + $ucet->vybrat(1500); +} catch (PrekroceniLimituVyjimka $e) { + echo $e->getMessage(); +} catch (NedostatekProstredkuVyjimka $e) { + echo $e->getMessage(); +} catch (BankovniVyjimka $e) { + echo 'Vyskytla se chyba při provádění operace.'; +} +``` + +V tomto příkladu je důležité si všimnout pořadí bloků `catch`. Protože všechny výjimky dědí od `BankovniVyjimka`, pokud bychom tento blok měli první, zachytily by se v něm všechny výjimky, aniž by se kód dostal k následujícím `catch` blokům. Proto je důležité mít specifičtější výjimky (tj. ty, které dědí od jiných) v bloku `catch` výše v pořadí než jejich rodičovské výjimky. + + +Správné postupy +--------------- + +Když máte za sebou základní principy objektově orientovaného programování, je důležité se zaměřit na správné postupy v OOP. Ty vám pomohou psat kód, který je nejen funkční, ale také čitelný, srozumitelný a snadno udržovatelný. + +1) **Oddělení zájmů (Separation of Concerns)**: Každá třída by měla mít jasně definovanou odpovědnost a měla by řešit pouze jeden hlavní úkol. Pokud třída dělá příliš mnoho věcí, může být vhodné ji rozdělit na menší, specializované třídy. +2) **Zapouzdření (Encapsulation)**: Data a metody by měly být co nejvíce skryté a přístupné pouze prostřednictvím definovaného rozhraní. To vám umožní měnit interní implementaci třídy bez ovlivnění zbytku kódu. +3) **Předávání závislostí (Dependency Injection)**: Místo toho, abyste vytvořili závislosti přímo v třídě, měli byste je "injektovat" z vnějšku. Pro hlubší porozumění tomuto principu doporučujeme [kapitoly o Dependency Injection|dependency-injection:introduction]. diff --git a/nette/de/introduction-to-object-oriented-programming.texy b/nette/de/introduction-to-object-oriented-programming.texy new file mode 100644 index 0000000000..88a1f0cdff --- /dev/null +++ b/nette/de/introduction-to-object-oriented-programming.texy @@ -0,0 +1,719 @@ +Einführung in die objektorientierte Programmierung +************************************************** + +.[perex] +Der Begriff "OOP" steht für Object-Oriented Programming (objektorientierte Programmierung), eine Methode zur Organisation und Strukturierung von Code. OOP ermöglicht es uns, ein Programm als eine Sammlung von Objekten zu betrachten, die miteinander kommunizieren, und nicht als eine Abfolge von Befehlen und Funktionen. + +In OOP ist ein "Objekt" eine Einheit, die Daten und Funktionen enthält, die mit diesen Daten arbeiten. Objekte werden auf der Grundlage von "Klassen" erstellt, die als Entwürfe oder Vorlagen für Objekte verstanden werden können. Sobald wir eine Klasse haben, können wir ihre "Instanz" erstellen, d. h. ein spezifisches Objekt, das aus dieser Klasse besteht. + +Schauen wir uns an, wie wir eine einfache Klasse in PHP erstellen können. Bei der Definition einer Klasse verwenden wir das Schlüsselwort "class", gefolgt vom Klassennamen und geschweiften Klammern, die die Funktionen der Klasse (genannt "Methoden") und die Variablen der Klasse (genannt "Eigenschaften" oder "Attribute") einschließen: + +```php +class Car +{ + function honk() + { + echo 'Beep beep!'; + } +} +``` + +In diesem Beispiel haben wir eine Klasse namens `Car` mit einer Funktion (oder "Methode") namens `honk` erstellt. + +Jede Klasse sollte nur eine Hauptaufgabe lösen. Wenn eine Klasse zu viele Aufgaben hat, kann es sinnvoll sein, sie in kleinere, spezialisierte Klassen aufzuteilen. + +Klassen werden in der Regel in separaten Dateien gespeichert, damit der Code übersichtlich bleibt und leicht zu navigieren ist. Der Dateiname sollte mit dem Klassennamen übereinstimmen, für die Klasse `Car` wäre der Dateiname also `Car.php`. + +Bei der Benennung von Klassen sollte man sich an die "PascalCase"-Konvention halten, d. h. jedes Wort im Namen beginnt mit einem Großbuchstaben, und es gibt keine Unterstriche oder andere Trennzeichen. Methoden und Eigenschaften folgen der "camelCase"-Konvention, das heißt, sie beginnen mit einem Kleinbuchstaben. + +Einige Methoden in PHP haben besondere Funktionen und werden mit `__` (zwei Unterstrichen) eingeleitet. Eine der wichtigsten Spezialmethoden ist der "Konstruktor", der mit `__construct` gekennzeichnet ist. Der Konstruktor ist eine Methode, die automatisch aufgerufen wird, wenn eine neue Instanz einer Klasse erstellt wird. + +Wir verwenden den Konstruktor häufig, um den Anfangszustand eines Objekts festzulegen. Wenn Sie beispielsweise ein Objekt erstellen, das eine Person darstellt, können Sie den Konstruktor verwenden, um deren Alter, Namen oder andere Attribute festzulegen. + +Schauen wir uns an, wie man einen Konstruktor in PHP verwendet: + +```php +class Person +{ + private $age; + + function __construct($age) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +$person = new Person(25); +echo $person->howOldAreYou(); // Outputs: 25 +``` + +In diesem Beispiel hat die Klasse `Person` eine Eigenschaft `$age` und einen Konstruktor, der diese Eigenschaft festlegt. Die Methode `howOldAreYou()` ermöglicht dann den Zugriff auf das Alter der Person. + +Das Schlüsselwort `new` wird verwendet, um eine neue Instanz einer Klasse zu erstellen. Im obigen Beispiel haben wir eine neue Person im Alter von 25 Jahren erstellt. + +Sie können auch Standardwerte für Konstruktorparameter festlegen, wenn diese bei der Erstellung eines Objekts nicht angegeben werden. Zum Beispiel: + +```php +class Person +{ + private $age; + + function __construct($age = 20) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +$person = new Person; // if no argument is passed, parentheses can be omitted +echo $person->howOldAreYou(); // Outputs: 20 +``` + +Wenn Sie in diesem Beispiel bei der Erstellung eines `Person` Objekts kein Alter angeben, wird der Standardwert von 20 verwendet. + +Schließlich kann die Definition von Eigenschaften mit ihrer Initialisierung über den Konstruktor wie folgt verkürzt und vereinfacht werden: + +```php +class Person +{ + function __construct( + private $age = 20, + ) { + } +} +``` + + +Namespaces .[#toc-namespaces] +----------------------------- + +Namensräume ermöglichen es uns, verwandte Klassen, Funktionen und Konstanten zu organisieren und zu gruppieren und gleichzeitig Benennungskonflikte zu vermeiden. Man kann sie sich wie Ordner auf einem Computer vorstellen, wobei jeder Ordner Dateien enthält, die sich auf ein bestimmtes Projekt oder Thema beziehen. + +Namensräume sind besonders nützlich in größeren Projekten oder bei der Verwendung von Bibliotheken von Drittanbietern, wo es zu Konflikten bei der Benennung von Klassen kommen kann. + +Stellen Sie sich vor, Sie haben in Ihrem Projekt eine Klasse mit dem Namen `Car`, die Sie in einen Namensraum mit dem Namen `Transport` einfügen möchten. Sie würden folgendermaßen vorgehen: + +```php +namespace Transport; + +class Car +{ + function honk() + { + echo 'Beep beep!'; + } +} +``` + +Wenn Sie die Klasse `Car` in einer anderen Datei verwenden wollen, müssen Sie angeben, aus welchem Namespace die Klasse stammt: + +```php +$car = new Transport\Car; +``` + +Zur Vereinfachung können Sie am Anfang der Datei angeben, welche Klasse aus einem bestimmten Namespace Sie verwenden wollen, so dass Sie Instanzen erstellen können, ohne den vollständigen Pfad angeben zu müssen: + +```php +use Transport\Car; + +$car = new Car; +``` + + +Vererbung .[#toc-inheritance] +----------------------------- + +Die Vererbung ist ein Werkzeug der objektorientierten Programmierung, das es ermöglicht, neue Klassen auf der Grundlage bestehender Klassen zu erstellen, deren Eigenschaften und Methoden zu erben und sie bei Bedarf zu erweitern oder neu zu definieren. Die Vererbung gewährleistet die Wiederverwendbarkeit des Codes und die Klassenhierarchie. + +Einfach ausgedrückt: Wenn wir eine Klasse haben und eine andere davon abgeleitete Klasse mit einigen Änderungen erstellen möchten, können wir die neue Klasse von der ursprünglichen Klasse "erben". + +In PHP wird die Vererbung mit dem Schlüsselwort `extends` realisiert. + +Unsere Klasse `Person` speichert Altersinformationen. Wir können eine weitere Klasse, `Student`, erstellen, die `Person` erweitert und Informationen über das Studienfach hinzufügt. + +Schauen wir uns ein Beispiel an: + +```php +class Person +{ + private $age; + + function __construct($age) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +class Student extends Person +{ + private $fieldOfStudy; + + function __construct($age, $fieldOfStudy) + { + parent::__construct($age); + $this->fieldOfStudy = $fieldOfStudy; + } + + function printInformation() + { + echo 'Age of student: ', $this->howOldAreYou(); + echo 'Field of study: ', $this->fieldOfStudy; + } +} + +$student = new Student(20, 'Computer Science'); +$student->printInformation(); +``` + +Wie funktioniert dieser Code? + +- Wir haben das Schlüsselwort `extends` verwendet, um die Klasse `Person` zu erweitern, d.h. die Klasse `Student` erbt alle Methoden und Eigenschaften von `Person`. + +- Mit dem Schlüsselwort `parent::` können wir Methoden der übergeordneten Klasse aufrufen. In diesem Fall haben wir den Konstruktor der Klasse `Person` aufgerufen, bevor wir der Klasse `Student` unsere eigenen Funktionen hinzugefügt haben. + +Vererbung ist für Situationen gedacht, in denen es eine "ist ein"-Beziehung zwischen Klassen gibt. Zum Beispiel ist eine `Student` eine `Person`. Eine Katze ist ein Tier. Sie ermöglicht es uns, in Fällen, in denen wir ein Objekt (z. B. "Person") im Code erwarten, stattdessen ein abgeleitetes Objekt zu verwenden (z. B. "Student"). + +Es ist wichtig zu erkennen, dass der Hauptzweck der Vererbung **nicht** darin besteht, doppelten Code zu verhindern. Im Gegenteil, der Missbrauch von Vererbung kann zu komplexem und schwer zu wartendem Code führen. Wenn es keine "ist ein"-Beziehung zwischen Klassen gibt, sollten wir Komposition anstelle von Vererbung in Betracht ziehen. + + +Komposition .[#toc-composition] +------------------------------- + +Komposition ist eine Technik, bei der wir, anstatt Eigenschaften und Methoden einer anderen Klasse zu erben, einfach deren Instanz in unserer Klasse verwenden. Auf diese Weise können wir Funktionalitäten und Eigenschaften mehrerer Klassen kombinieren, ohne komplexe Vererbungsstrukturen zu schaffen. + +Ein Beispiel: Wir haben eine Klasse `Engine` und eine Klasse `Car`. Anstatt zu sagen "Ein Auto ist ein Motor", sagen wir "Ein Auto hat einen Motor", was eine typische Kompositionsbeziehung ist. + +```php +class Engine +{ + function start() + { + echo "Engine is running."; + } +} + +class Car +{ + private $engine; + + function __construct() + { + $this->engine = new Engine; + } + + function start() + { + $this->engine->start(); + echo "The car is ready to drive!"; + } +} + +$car = new Car; +$car->start(); +``` + +In diesem Fall verfügt die Klasse `Car` nicht über alle Eigenschaften und Methoden der Klasse `Engine`, aber sie hat über die Eigenschaft `$engine` Zugang zu ihnen. + +Der Vorteil der Komposition ist eine größere Flexibilität bei der Gestaltung und eine bessere Anpassungsfähigkeit an künftige Änderungen. + + +Sichtbarkeit .[#toc-visibility] +------------------------------- + +In PHP können Sie "Sichtbarkeit" für Klasseneigenschaften, Methoden und Konstanten definieren. Die Sichtbarkeit bestimmt, wo Sie auf diese Elemente zugreifen können. + +1. **Öffentlich:** Wenn ein Element als `public` gekennzeichnet ist, bedeutet dies, dass Sie von überall darauf zugreifen können, auch außerhalb der Klasse. + +2. **Geschützt:** Ein als `protected` gekennzeichnetes Element ist nur innerhalb der Klasse und aller ihrer Nachkommen (Klassen, die von ihr erben) zugänglich. + +3. **Privat:** Wenn ein Element als `private` gekennzeichnet ist, kann man nur innerhalb der Klasse, in der es definiert wurde, darauf zugreifen. + +Wenn Sie die Sichtbarkeit nicht angeben, setzt PHP sie automatisch auf `public`. + +Schauen wir uns einen Beispielcode an: + +```php +class VisibilityExample +{ + public $publicProperty = 'Public'; + protected $protectedProperty = 'Protected'; + private $privateProperty = 'Private'; + + public function printProperties() + { + echo $this->publicProperty; // Works + echo $this->protectedProperty; // Works + echo $this->privateProperty; // Works + } +} + +$object = new VisibilityExample; +$object->printProperties(); +echo $object->publicProperty; // Works +// echo $object->protectedProperty; // Throws an error +// echo $object->privateProperty; // Throws an error +``` + +Fortsetzung der Klassenvererbung: + +```php +class ChildClass extends VisibilityExample +{ + public function printProperties() + { + echo $this->publicProperty; // Works + echo $this->protectedProperty; // Works + // echo $this->privateProperty; // Throws an error + } +} +``` + +In diesem Fall kann die Methode `printProperties()` in der `ChildClass` auf die öffentlichen und geschützten Eigenschaften zugreifen, aber nicht auf die privaten Eigenschaften der übergeordneten Klasse. + +Daten und Methoden sollten so versteckt wie möglich sein und nur über eine definierte Schnittstelle zugänglich sein. Auf diese Weise können Sie die interne Implementierung der Klasse ändern, ohne dass sich dies auf den restlichen Code auswirkt. + + +Final-Schlüsselwort .[#toc-final-keyword] +----------------------------------------- + +In PHP können wir das Schlüsselwort `final` verwenden, wenn wir verhindern wollen, dass eine Klasse, Methode oder Konstante geerbt oder überschrieben wird. Wenn eine Klasse als `final` markiert ist, kann sie nicht erweitert werden. Wenn eine Methode als `final` markiert ist, kann sie in einer Unterklasse nicht überschrieben werden. + +Wenn wir wissen, dass eine bestimmte Klasse oder Methode nicht mehr geändert wird, können wir leichter Änderungen vornehmen, ohne uns Gedanken über mögliche Konflikte zu machen. Wir können zum Beispiel eine neue Methode hinzufügen, ohne befürchten zu müssen, dass ein Nachkomme bereits eine Methode mit demselben Namen hat, was zu einer Kollision führen würde. Oder wir können die Parameter einer Methode ändern, ohne das Risiko einer Inkonsistenz mit einer überschriebenen Methode in einem Nachfahren einzugehen. + +```php +final class FinalClass +{ +} + +// The following code will throw an error because we cannot inherit from a final class. +class ChildOfFinalClass extends FinalClass +{ +} +``` + +In diesem Beispiel führt der Versuch, von der endgültigen Klasse `FinalClass` zu erben, zu einem Fehler. + + +Statische Eigenschaften und Methoden .[#toc-static-properties-and-methods] +-------------------------------------------------------------------------- + +Wenn wir in PHP von "statischen" Elementen einer Klasse sprechen, meinen wir Methoden und Eigenschaften, die zur Klasse selbst gehören, nicht zu einer bestimmten Instanz der Klasse. Das bedeutet, dass Sie keine Instanz der Klasse erstellen müssen, um auf sie zuzugreifen. Stattdessen können Sie sie direkt über den Klassennamen aufrufen oder auf sie zugreifen. + +Da statische Elemente zur Klasse und nicht zu ihren Instanzen gehören, können Sie die Pseudovariable `$this` nicht in statischen Methoden verwenden. + +Die Verwendung von statischen Eigenschaften führt zu [verschleiertem Code voller Fallstricke |dependency-injection:global-state], so dass Sie sie niemals verwenden sollten, und wir werden hier auch kein Beispiel zeigen. Andererseits sind statische Methoden nützlich. Hier ist ein Beispiel: + +```php +class Calculator +{ + public static function add($a, $b) + { + return $a + $b; + } + + public static function subtract($a, $b) + { + return $a - $b; + } +} + +// Using the static method without creating an instance of the class +echo Calculator::add(5, 3); // Output: 8 +echo Calculator::subtract(5, 3); // Output: 2 +``` + +In diesem Beispiel haben wir eine Klasse `Calculator` mit zwei statischen Methoden erstellt. Wir können diese Methoden direkt aufrufen, ohne eine Instanz der Klasse mit dem `::` Operator zu erstellen. Statische Methoden sind besonders nützlich für Operationen, die nicht vom Zustand einer bestimmten Klasseninstanz abhängen. + + +Klassenkonstanten .[#toc-class-constants] +----------------------------------------- + +Innerhalb von Klassen haben wir die Möglichkeit, Konstanten zu definieren. Konstanten sind Werte, die sich während der Ausführung des Programms nicht ändern. Im Gegensatz zu Variablen bleibt der Wert einer Konstante gleich. + +```php +class Car +{ + public const NumberOfWheels = 4; + + public function displayNumberOfWheels(): int + { + echo self::NumberOfWheels; + } +} + +echo Car::NumberOfWheels; // Output: 4 +``` + +In diesem Beispiel haben wir eine Klasse `Car` mit der Konstante `NumberOfWheels`. Beim Zugriff auf die Konstante innerhalb der Klasse können wir das Schlüsselwort `self` anstelle des Klassennamens verwenden. + + +Objektschnittstellen .[#toc-object-interfaces] +---------------------------------------------- + +Objektschnittstellen fungieren als "Verträge" für Klassen. Wenn eine Klasse eine Objektschnittstelle implementieren soll, muss sie alle Methoden enthalten, die die Schnittstelle definiert. Auf diese Weise kann man sicherstellen, dass sich bestimmte Klassen an denselben "Vertrag" oder dieselbe Struktur halten. + +In PHP werden Schnittstellen mit dem Schlüsselwort `interface` definiert. Alle Methoden, die in einer Schnittstelle definiert sind, sind öffentlich (`public`). Wenn eine Klasse eine Schnittstelle implementiert, verwendet sie das Schlüsselwort `implements`. + +```php +interface Animal +{ + function makeSound(); +} + +class Cat implements Animal +{ + public function makeSound() + { + echo 'Meow'; + } +} + +$cat = new Cat; +$cat->makeSound(); +``` + +Wenn eine Klasse eine Schnittstelle implementiert, aber nicht alle erwarteten Methoden definiert sind, wird PHP einen Fehler ausgeben. Eine Klasse kann mehrere Schnittstellen auf einmal implementieren, was sich von der Vererbung unterscheidet, bei der eine Klasse nur von einer Klasse erben kann. + + +Abstrakte Klassen .[#toc-abstract-classes] +------------------------------------------ + +Abstrakte Klassen dienen als Basisvorlagen für andere Klassen, aber Sie können ihre Instanzen nicht direkt erstellen. Sie enthalten eine Mischung aus vollständigen Methoden und abstrakten Methoden, die keinen definierten Inhalt haben. Klassen, die von abstrakten Klassen erben, müssen Definitionen für alle abstrakten Methoden der Elternklasse bereitstellen. + +Wir verwenden das Schlüsselwort `abstract`, um eine abstrakte Klasse zu definieren. + +```php +abstract class AbstractClass +{ + public function regularMethod() + { + echo 'This is a regular method'; + } + + abstract public function abstractMethod(); +} + +class Child extends AbstractClass +{ + public function abstractMethod() + { + echo 'This is the implementation of the abstract method'; + } +} + +$instance = new Child; +$instance->regularMethod(); +$instance->abstractMethod(); +``` + +In diesem Beispiel haben wir eine abstrakte Klasse mit einer regulären und einer abstrakten Methode. Dann haben wir eine Klasse `Child`, die von `AbstractClass` erbt und eine Implementierung für die abstrakte Methode bereitstellt. + + +Typ-Prüfung .[#toc-type-checking] +--------------------------------- + +Beim Programmieren ist es wichtig, sicherzustellen, dass die Daten, mit denen wir arbeiten, vom richtigen Typ sind. In PHP gibt es Werkzeuge, die diese Sicherheit bieten. Die Überprüfung, ob die Daten vom richtigen Typ sind, nennt man "Typüberprüfung". + +Typen, denen wir in PHP begegnen können: + +1. **Basistypen**: Dazu gehören `int` (Ganzzahlen), `float` (Gleitkommazahlen), `bool` (boolesche Werte), `string` (Strings), `array` (Arrays) und `null`. +2. **Klassen**: Wenn ein Wert eine Instanz einer bestimmten Klasse sein soll. +3. **Schnittstellen**: Definiert eine Reihe von Methoden, die eine Klasse implementieren muss. Ein Wert, der eine Schnittstelle erfüllt, muss über diese Methoden verfügen. +4. **Mischtypen**: Wir können festlegen, dass eine Variable mehrere zulässige Typen haben kann. +5. **Void**: Dieser spezielle Typ gibt an, dass eine Funktion oder Methode keinen Wert zurückgibt. + +Schauen wir uns an, wie wir den Code ändern können, um Typen einzubeziehen: + +```php +class Person +{ + private int $age; + + public function __construct(int $age) + { + $this->age = $age; + } + + public function printAge(): void + { + echo "This person is " . $this->age . " years old."; + } +} + +/** + * A function that accepts a Person object and prints the person's age. + */ +function printPersonAge(Person $person): void +{ + $person->printAge(); +} +``` + +Auf diese Weise stellen wir sicher, dass unser Code Daten des richtigen Typs erwartet und mit ihnen arbeitet, was uns hilft, mögliche Fehler zu vermeiden. + + +Vergleich und Identität .[#toc-comparison-and-identity] +------------------------------------------------------- + +In PHP können Sie Objekte auf zwei Arten vergleichen: + +1. Wertevergleich `==`: Es wird geprüft, ob die Objekte der gleichen Klasse angehören und die gleichen Werte in ihren Eigenschaften haben. +2. Identität `===`: Prüft, ob es sich um die gleiche Instanz des Objekts handelt. + +```php +class Car +{ + public string $brand; + + public function __construct(string $brand) + { + $this->brand = $brand; + } +} + +$car1 = new Car('Skoda'); +$car2 = new Car('Skoda'); +$car3 = $car1; + +var_dump($car1 == $car2); // true, because they have the same value +var_dump($car1 === $car2); // false, because they are not the same instance +var_dump($car1 === $car3); // true, because $car3 is the same instance as $car1 +``` + + +Der `instanceof` Operator .[#toc-the-instanceof-operator] +--------------------------------------------------------- + +Mit dem Operator `instanceof` können Sie feststellen, ob ein bestimmtes Objekt eine Instanz einer bestimmten Klasse ist, ein Nachkomme dieser Klasse oder ob es eine bestimmte Schnittstelle implementiert. + +Stellen Sie sich vor, wir haben eine Klasse `Person` und eine weitere Klasse `Student`, die ein Nachkomme von `Person` ist: + +```php +class Person +{ + private int $age; + + public function __construct(int $age) + { + $this->age = $age; + } +} + +class Student extends Person +{ + private string $major; + + public function __construct(int $age, string $major) + { + parent::__construct($age); + $this->major = $major; + } +} + +$student = new Student(20, 'Computer Science'); + +// Check if $student is an instance of the Student class +var_dump($student instanceof Student); // Output: bool(true) + +// Check if $student is an instance of the Person class (because Student is a descendant of Person) +var_dump($student instanceof Person); // Output: bool(true) +``` + +Aus den Ausgaben ist ersichtlich, dass das Objekt `$student` als Instanz der Klassen `Student` und `Person` betrachtet wird. + + +Fließende Schnittstellen .[#toc-fluent-interfaces] +-------------------------------------------------- + +Eine "Fluent Interface" ist eine Technik in der OOP, die es ermöglicht, Methoden in einem einzigen Aufruf zu verketten. Dies vereinfacht und verdeutlicht oft den Code. + +Das Schlüsselelement einer fließenden Schnittstelle ist, dass jede Methode in der Kette einen Verweis auf das aktuelle Objekt zurückgibt. Dies wird durch die Verwendung von `return $this;` am Ende der Methode erreicht. Dieser Programmierstil wird häufig mit Methoden in Verbindung gebracht, die "Setter" genannt werden und die Werte der Eigenschaften eines Objekts festlegen. + +Schauen wir uns an, wie eine fließende Schnittstelle für das Senden von E-Mails aussehen könnte: + +```php +public function sendMessage() +{ + $email = new Email; + $email->setFrom('sender@example.com') + ->setRecipient('admin@example.com') + ->setMessage('Hello, this is a message.') + ->send(); +} +``` + +In diesem Beispiel werden die Methoden `setFrom()`, `setRecipient()` und `setMessage()` verwendet, um die entsprechenden Werte (Absender, Empfänger, Nachrichteninhalt) zu setzen. Nach dem Setzen jedes dieser Werte geben die Methoden das aktuelle Objekt (`$email`) zurück, so dass wir eine weitere Methode dahinter verketten können. Schließlich rufen wir die Methode `send()` auf, die die E-Mail tatsächlich versendet. + +Dank der fließenden Schnittstellen können wir Code schreiben, der intuitiv und leicht lesbar ist. + + +Kopieren mit `clone` .[#toc-copying-with-clone] +----------------------------------------------- + +In PHP können wir eine Kopie eines Objekts mit dem Operator `clone` erstellen. Auf diese Weise erhalten wir eine neue Instanz mit identischem Inhalt. + +Wenn wir beim Kopieren eines Objekts einige seiner Eigenschaften ändern müssen, können wir eine spezielle Methode `__clone()` in der Klasse definieren. Diese Methode wird automatisch aufgerufen, wenn das Objekt geklont wird. + +```php +class Sheep +{ + public string $name; + + public function __construct(string $name) + { + $this->name = $name; + } + + public function __clone() + { + $this->name = 'Clone of ' . $this->name; + } +} + +$original = new Sheep('Dolly'); +echo $original->name . "\n"; // Outputs: Dolly + +$clone = clone $original; +echo $clone->name . "\n"; // Outputs: Clone of Dolly +``` + +In diesem Beispiel haben wir eine Klasse `Sheep` mit einer Eigenschaft `$name`. Wenn wir eine Instanz dieser Klasse klonen, sorgt die Methode `__clone()` dafür, dass der Name des geklonten Schafs das Präfix "Clone of" erhält. + + +Eigenschaften .[#toc-traits] +---------------------------- + +Traits in PHP sind ein Werkzeug, das die gemeinsame Nutzung von Methoden, Eigenschaften und Konstanten zwischen Klassen ermöglicht und die Duplizierung von Code verhindert. Man kann sie sich wie einen "Kopieren und Einfügen"-Mechanismus vorstellen (Strg-C und Strg-V), bei dem der Inhalt eines Traits in Klassen "eingefügt" wird. So können Sie Code wiederverwenden, ohne komplizierte Klassenhierarchien erstellen zu müssen. + +Werfen wir einen Blick auf ein einfaches Beispiel für die Verwendung von Traits in PHP: + +```php +trait Honking +{ + public function honk() + { + echo 'Beep beep!'; + } +} + +class Car +{ + use Honking; +} + +class Truck +{ + use Honking; +} + +$car = new Car; +$car->honk(); // Outputs 'Beep beep!' + +$truck = new Truck; +$truck->honk(); // Also outputs 'Beep beep!' +``` + +In diesem Beispiel haben wir einen Trait namens `Honking`, der eine Methode `honk()` enthält. Dann haben wir zwei Klassen: `Car` und `Truck`, die beide den Trait `Honking` verwenden. Infolgedessen "besitzen" beide Klassen die Methode `honk()`, und wir können sie für Objekte beider Klassen aufrufen. + +Traits ermöglichen eine einfache und effiziente gemeinsame Nutzung von Code zwischen Klassen. Sie greifen nicht in die Vererbungshierarchie ein, d. h. `$car instanceof Honking` gibt `false` zurück. + + +Ausnahmen +--------- + +Ausnahmen in OOP ermöglichen es uns, Fehler zu behandeln und zu verwalten, die während der Ausführung unseres Codes auftreten können. Sie sind im Wesentlichen Objekte, die dazu dienen, Fehler oder unerwartete Situationen in Ihrem Programm aufzuzeichnen. + +In PHP gibt es für diese Objekte die eingebaute Klasse `Exception`. Sie verfügt über mehrere Methoden, mit denen wir weitere Informationen über die Ausnahme erhalten können, z. B. die Fehlermeldung, die Datei und die Zeile, in der der Fehler aufgetreten ist, usw. + +Wenn ein Problem auftritt, können wir eine Ausnahme "werfen" (mit `throw`). Wenn wir diese Ausnahme "abfangen" und verarbeiten wollen, verwenden wir die Blöcke `try` und `catch`. + +Schauen wir uns an, wie das funktioniert: + +```php +try { + throw new Exception('Message explaining the reason for the exception'); + + // This code won't execute + echo 'I am a message that nobody will read'; + +} catch (Exception $e) { + echo 'Exception caught: '. $e->getMessage(); +} +``` + +Es ist wichtig zu wissen, dass eine Ausnahme auch tiefer, während des Aufrufs anderer Methoden, ausgelöst werden kann. + +Für einen `try` Block können mehrere `catch` Blöcke angegeben werden, wenn Sie verschiedene Arten von Ausnahmen erwarten. + +Wir können auch eine Ausnahmehierarchie erstellen, bei der jede Ausnahmeklasse von der vorhergehenden erbt. Nehmen wir als Beispiel eine einfache Bankanwendung, die Einzahlungen und Abhebungen zulässt: + +```php +class BankingException extends Exception {} +class InsufficientFundsException extends BankingException {} +class ExceededLimitException extends BankingException {} + +class BankAccount +{ + private int $balance = 0; + private int $dailyLimit = 1000; + + public function deposit(int $amount): int + { + $this->balance += $amount; + return $this->balance; + } + + public function withdraw(int $amount): int + { + if ($amount > $this->balance) { + throw new InsufficientFundsException('Not enough funds in the account.'); + } + + if ($amount > $this->dailyLimit) { + throw new ExceededLimitException('Daily withdrawal limit exceeded.'); + } + + $this->balance -= $amount; + return $this->balance; + } +} + +$account = new BankAccount; +$account->deposit(500); + +try { + $account->withdraw(1500); +} catch (ExceededLimitException $e) { + echo $e->getMessage(); +} catch (InsufficientFundsException $e) { + echo $e->getMessage(); +} catch (BankingException $e) { + echo 'An error occurred during the operation.'; +} +``` + +In diesem Beispiel ist es wichtig, die Reihenfolge der `catch` Blöcke zu beachten. Da alle Ausnahmen von `BankingException` erben, würden alle Ausnahmen in diesem Block abgefangen werden, ohne dass der Code die nachfolgenden Blöcke von `catch` erreicht. Daher ist es wichtig, spezifischere Ausnahmen (d. h. solche, die von anderen erben) in der Reihenfolge der `catch` -Blöcke höher anzusiedeln als ihre übergeordneten Ausnahmen. + + +Bewährte Praktiken .[#toc-best-practices] +----------------------------------------- + +Sobald Sie die Grundprinzipien der objektorientierten Programmierung beherrschen, ist es wichtig, sich auf die besten Praktiken der OOP zu konzentrieren. Diese helfen Ihnen, Code zu schreiben, der nicht nur funktional, sondern auch lesbar, verständlich und leicht zu warten ist. + +1) **Trennung von Belangen**: Jede Klasse sollte eine klar definierte Verantwortung haben und sich nur mit einer Hauptaufgabe befassen. Wenn eine Klasse zu viele Aufgaben hat, kann es sinnvoll sein, sie in kleinere, spezialisierte Klassen aufzuteilen. +2) **Kapselung**: Daten und Methoden sollten so versteckt wie möglich sein und nur über eine definierte Schnittstelle zugänglich sein. Auf diese Weise können Sie die interne Implementierung einer Klasse ändern, ohne dass sich dies auf den restlichen Code auswirkt. +3) **Dependency Injection**: Anstatt Abhängigkeiten direkt innerhalb einer Klasse zu schaffen, sollten Sie sie von außen "injizieren". Für ein tieferes Verständnis dieses Prinzips empfehlen wir die [Kapitel über Dependency Injection |dependency-injection:introduction]. diff --git a/nette/el/introduction-to-object-oriented-programming.texy b/nette/el/introduction-to-object-oriented-programming.texy new file mode 100644 index 0000000000..92d7a8cf58 --- /dev/null +++ b/nette/el/introduction-to-object-oriented-programming.texy @@ -0,0 +1,719 @@ +Εισαγωγή στον αντικειμενοστραφή προγραμματισμό +********************************************** + +.[perex] +Ο όρος "OOP" σημαίνει αντικειμενοστραφής προγραμματισμός, ο οποίος είναι ένας τρόπος οργάνωσης και δόμησης του κώδικα. Ο OOP μας επιτρέπει να βλέπουμε ένα πρόγραμμα ως μια συλλογή αντικειμένων που επικοινωνούν μεταξύ τους, αντί για μια ακολουθία εντολών και συναρτήσεων. + +Στο OOP, ένα "αντικείμενο" είναι μια μονάδα που περιέχει δεδομένα και συναρτήσεις που λειτουργούν με αυτά τα δεδομένα. Τα αντικείμενα δημιουργούνται με βάση "κλάσεις", οι οποίες μπορούν να εκληφθούν ως σχέδια ή πρότυπα για αντικείμενα. Αφού έχουμε μια κλάση, μπορούμε να δημιουργήσουμε την "παρουσία" της, η οποία είναι ένα συγκεκριμένο αντικείμενο κατασκευασμένο από αυτή την κλάση. + +Ας δούμε πώς μπορούμε να δημιουργήσουμε μια απλή κλάση στην PHP. Όταν ορίζουμε μια κλάση, χρησιμοποιούμε τη λέξη-κλειδί "class", ακολουθούμενη από το όνομα της κλάσης και στη συνέχεια από τις τεθλασμένες αγκύλες που περικλείουν τις συναρτήσεις της κλάσης (που ονομάζονται "μέθοδοι") και τις μεταβλητές της κλάσης (που ονομάζονται "ιδιότητες" ή "χαρακτηριστικά"): + +```php +class Car +{ + function honk() + { + echo 'Beep beep!'; + } +} +``` + +Σε αυτό το παράδειγμα, δημιουργήσαμε μια κλάση με όνομα `Car` με μια συνάρτηση (ή "μέθοδο") που ονομάζεται `honk`. + +Κάθε τάξη θα πρέπει να επιλύει μόνο μία κύρια εργασία. Εάν μια τάξη κάνει πάρα πολλά πράγματα, μπορεί να είναι σκόπιμο να χωριστεί σε μικρότερες, εξειδικευμένες τάξεις. + +Οι κλάσεις συνήθως αποθηκεύονται σε ξεχωριστά αρχεία για να διατηρείται ο κώδικας οργανωμένος και εύκολος στην πλοήγηση. Το όνομα του αρχείου πρέπει να ταιριάζει με το όνομα της κλάσης, οπότε για την κλάση `Car`, το όνομα του αρχείου θα είναι `Car.php`. + +Όταν ονομάζετε κλάσεις, είναι καλό να ακολουθείτε τη σύμβαση "PascalCase", δηλαδή κάθε λέξη στο όνομα αρχίζει με κεφαλαίο γράμμα και δεν υπάρχουν υπογραμμίσεις ή άλλα διαχωριστικά. Οι μέθοδοι και οι ιδιότητες ακολουθούν τη σύμβαση "camelCase", δηλαδή ξεκινούν με πεζά γράμματα. + +Ορισμένες μέθοδοι στην PHP έχουν ειδικούς ρόλους και προτάσσονται με `__` (δύο υπογράμμιση). Μία από τις πιο σημαντικές ειδικές μεθόδους είναι ο "κατασκευαστής", με την ένδειξη `__construct`. Ο κατασκευαστής είναι μια μέθοδος που καλείται αυτόματα κατά τη δημιουργία μιας νέας περίπτωσης μιας κλάσης. + +Συχνά χρησιμοποιούμε τον κατασκευαστή για να ορίσουμε την αρχική κατάσταση ενός αντικειμένου. Για παράδειγμα, κατά τη δημιουργία ενός αντικειμένου που αναπαριστά ένα άτομο, μπορεί να χρησιμοποιήσετε τον κατασκευαστή για να ορίσετε την ηλικία, το όνομα ή άλλα χαρακτηριστικά του. + +Ας δούμε πώς μπορείτε να χρησιμοποιήσετε έναν κατασκευαστή στην PHP: + +```php +class Person +{ + private $age; + + function __construct($age) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +$person = new Person(25); +echo $person->howOldAreYou(); // Outputs: 25 +``` + +Σε αυτό το παράδειγμα, η κλάση `Person` έχει μια ιδιότητα `$age` και έναν κατασκευαστή που ορίζει αυτή την ιδιότητα. Η μέθοδος `howOldAreYou()` παρέχει στη συνέχεια πρόσβαση στην ηλικία του ατόμου. + +Η λέξη-κλειδί `new` χρησιμοποιείται για τη δημιουργία μιας νέας περίπτωσης μιας κλάσης. Στο παραπάνω παράδειγμα, δημιουργήσαμε ένα νέο άτομο ηλικίας 25 ετών. + +Μπορείτε επίσης να ορίσετε προεπιλεγμένες τιμές για τις παραμέτρους του κατασκευαστή, εάν δεν έχουν καθοριστεί κατά τη δημιουργία ενός αντικειμένου. Για παράδειγμα: + +```php +class Person +{ + private $age; + + function __construct($age = 20) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +$person = new Person; // if no argument is passed, parentheses can be omitted +echo $person->howOldAreYou(); // Outputs: 20 +``` + +Σε αυτό το παράδειγμα, αν δεν καθορίσετε μια ηλικία κατά τη δημιουργία ενός αντικειμένου `Person`, θα χρησιμοποιηθεί η προεπιλεγμένη τιμή 20. + +Τέλος, ο ορισμός της ιδιότητας με την αρχικοποίησή της μέσω του κατασκευαστή μπορεί να συντομευτεί και να απλοποιηθεί ως εξής: + +```php +class Person +{ + function __construct( + private $age = 20, + ) { + } +} +``` + + +Χώροι ονομάτων .[#toc-namespaces] +--------------------------------- + +Οι χώροι ονομάτων μας επιτρέπουν να οργανώνουμε και να ομαδοποιούμε συναφείς κλάσεις, συναρτήσεις και σταθερές αποφεύγοντας συγκρούσεις ονομάτων. Μπορείτε να τα φανταστείτε όπως τους φακέλους σε έναν υπολογιστή, όπου κάθε φάκελος περιέχει αρχεία που σχετίζονται με ένα συγκεκριμένο έργο ή θέμα. + +Οι χώροι ονομάτων είναι ιδιαίτερα χρήσιμοι σε μεγαλύτερα έργα ή όταν χρησιμοποιείτε βιβλιοθήκες τρίτων, όπου μπορεί να προκύψουν συγκρούσεις ονοματοδοσίας κλάσεων. + +Φανταστείτε ότι έχετε μια κλάση με όνομα `Car` στο έργο σας και θέλετε να την τοποθετήσετε σε ένα χώρο ονομάτων με όνομα `Transport`. Θα το κάνατε ως εξής: + +```php +namespace Transport; + +class Car +{ + function honk() + { + echo 'Beep beep!'; + } +} +``` + +Αν θέλετε να χρησιμοποιήσετε την κλάση `Car` σε ένα άλλο αρχείο, πρέπει να καθορίσετε από ποιο χώρο ονομάτων προέρχεται η κλάση: + +```php +$car = new Transport\Car; +``` + +Για λόγους απλούστευσης, μπορείτε να καθορίσετε στην αρχή του αρχείου ποια κλάση από ένα συγκεκριμένο χώρο ονομάτων θέλετε να χρησιμοποιήσετε, επιτρέποντάς σας να δημιουργήσετε περιπτώσεις χωρίς να αναφέρετε την πλήρη διαδρομή: + +```php +use Transport\Car; + +$car = new Car; +``` + + +Κληρονομικότητα .[#toc-inheritance] +----------------------------------- + +Η κληρονομικότητα είναι ένα εργαλείο του αντικειμενοστρεφούς προγραμματισμού που επιτρέπει τη δημιουργία νέων κλάσεων με βάση τις υπάρχουσες, κληρονομώντας τις ιδιότητες και τις μεθόδους τους και επεκτείνοντας ή επαναπροσδιορίζοντας τες ανάλογα με τις ανάγκες. Η κληρονομικότητα εξασφαλίζει την επαναχρησιμοποίηση του κώδικα και την ιεραρχία των κλάσεων. + +Με απλά λόγια, αν έχουμε μια κλάση και θέλουμε να δημιουργήσουμε μια άλλη που να προέρχεται από αυτήν αλλά με κάποιες τροποποιήσεις, μπορούμε να "κληρονομήσουμε" τη νέα κλάση από την αρχική. + +Στην PHP, η κληρονομικότητα υλοποιείται με τη χρήση της λέξης-κλειδί `extends`. + +Η κλάση μας `Person` αποθηκεύει πληροφορίες για την ηλικία. Μπορούμε να έχουμε μια άλλη κλάση, την `Student`, η οποία επεκτείνει την `Person` και προσθέτει πληροφορίες σχετικά με τον τομέα σπουδών. + +Ας δούμε ένα παράδειγμα: + +```php +class Person +{ + private $age; + + function __construct($age) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +class Student extends Person +{ + private $fieldOfStudy; + + function __construct($age, $fieldOfStudy) + { + parent::__construct($age); + $this->fieldOfStudy = $fieldOfStudy; + } + + function printInformation() + { + echo 'Age of student: ', $this->howOldAreYou(); + echo 'Field of study: ', $this->fieldOfStudy; + } +} + +$student = new Student(20, 'Computer Science'); +$student->printInformation(); +``` + +Πώς λειτουργεί αυτός ο κώδικας; + +- Χρησιμοποιήσαμε τη λέξη-κλειδί `extends` για να επεκτείνουμε την κλάση `Person`, δηλαδή η κλάση `Student` κληρονομεί όλες τις μεθόδους και τις ιδιότητες από την `Person`. + +- Η λέξη-κλειδί `parent::` μας επιτρέπει να καλούμε μεθόδους από τη γονική κλάση. Σε αυτή την περίπτωση, καλέσαμε τον κατασκευαστή από την κλάση `Person` πριν προσθέσουμε τη δική μας λειτουργικότητα στην κλάση `Student`. + +Η κληρονομικότητα προορίζεται για καταστάσεις όπου υπάρχει μια σχέση "είναι ένα" μεταξύ κλάσεων. Για παράδειγμα, μια `Student` είναι μια `Person`. Μια γάτα είναι ένα ζώο. Μας επιτρέπει σε περιπτώσεις όπου περιμένουμε ένα αντικείμενο (π.χ. "Person") στον κώδικα να χρησιμοποιήσουμε αντί αυτού ένα παράγωγο αντικείμενο (π.χ. "Student"). + +Είναι σημαντικό να συνειδητοποιήσουμε ότι ο πρωταρχικός σκοπός της κληρονομικότητας **δεν** είναι να αποτρέψει την επανάληψη του κώδικα. Αντιθέτως, η κακή χρήση της κληρονομικότητας μπορεί να οδηγήσει σε πολύπλοκο και δύσκολα συντηρήσιμο κώδικα. Εάν δεν υπάρχει σχέση "είναι ένα" μεταξύ των κλάσεων, θα πρέπει να εξετάσουμε τη σύνθεση αντί της κληρονομικότητας. + + +Σύνθεση .[#toc-composition] +--------------------------- + +Η σύνθεση είναι μια τεχνική κατά την οποία, αντί να κληρονομούμε ιδιότητες και μεθόδους από μια άλλη κλάση, απλά χρησιμοποιούμε την εμφάνισή της στην κλάση μας. Αυτό μας επιτρέπει να συνδυάζουμε λειτουργίες και ιδιότητες πολλών κλάσεων χωρίς να δημιουργούμε πολύπλοκες δομές κληρονομικότητας. + +Για παράδειγμα, έχουμε μια κλάση `Engine` και μια κλάση `Car`. Αντί να πούμε "Ένα αυτοκίνητο είναι ένας κινητήρας", λέμε "Ένα αυτοκίνητο έχει έναν κινητήρα", που είναι μια τυπική σχέση σύνθεσης. + +```php +class Engine +{ + function start() + { + echo "Engine is running."; + } +} + +class Car +{ + private $engine; + + function __construct() + { + $this->engine = new Engine; + } + + function start() + { + $this->engine->start(); + echo "The car is ready to drive!"; + } +} + +$car = new Car; +$car->start(); +``` + +Εδώ, η `Car` δεν έχει όλες τις ιδιότητες και τις μεθόδους της `Engine`, αλλά έχει πρόσβαση σε αυτές μέσω της ιδιότητας `$engine`. + +Το πλεονέκτημα της σύνθεσης είναι η μεγαλύτερη ευελιξία σχεδιασμού και η καλύτερη προσαρμοστικότητα για μελλοντικές αλλαγές. + + +Ορατότητα .[#toc-visibility] +---------------------------- + +Στην PHP, μπορείτε να ορίσετε "ορατότητα" για ιδιότητες, μεθόδους και σταθερές κλάσεων. Η ορατότητα καθορίζει πού μπορείτε να έχετε πρόσβαση σε αυτά τα στοιχεία. + +1. **Δημόσιο:** Εάν ένα στοιχείο χαρακτηρίζεται ως `public`, σημαίνει ότι μπορείτε να έχετε πρόσβαση σε αυτό από οπουδήποτε, ακόμη και εκτός της κλάσης. + +2. **Προστατευμένο:** Ένα στοιχείο που επισημαίνεται ως `protected` είναι προσβάσιμο μόνο μέσα στην κλάση και σε όλους τους απογόνους της (κλάσεις που κληρονομούν από αυτήν). + +3. **Ιδιωτικό:** Εάν ένα στοιχείο είναι `private`, μπορείτε να έχετε πρόσβαση σε αυτό μόνο μέσα από την κλάση στην οποία ορίστηκε. + +Αν δεν καθορίσετε ορατότητα, η PHP θα την ορίσει αυτόματα σε `public`. + +Ας δούμε ένα παράδειγμα κώδικα: + +```php +class VisibilityExample +{ + public $publicProperty = 'Public'; + protected $protectedProperty = 'Protected'; + private $privateProperty = 'Private'; + + public function printProperties() + { + echo $this->publicProperty; // Works + echo $this->protectedProperty; // Works + echo $this->privateProperty; // Works + } +} + +$object = new VisibilityExample; +$object->printProperties(); +echo $object->publicProperty; // Works +// echo $object->protectedProperty; // Throws an error +// echo $object->privateProperty; // Throws an error +``` + +Συνεχίζοντας με την κληρονομικότητα των κλάσεων: + +```php +class ChildClass extends VisibilityExample +{ + public function printProperties() + { + echo $this->publicProperty; // Works + echo $this->protectedProperty; // Works + // echo $this->privateProperty; // Throws an error + } +} +``` + +Σε αυτή την περίπτωση, η μέθοδος `printProperties()` στην `ChildClass` μπορεί να έχει πρόσβαση στις δημόσιες και προστατευόμενες ιδιότητες, αλλά δεν μπορεί να έχει πρόσβαση στις ιδιωτικές ιδιότητες της γονικής κλάσης. + +Τα δεδομένα και οι μέθοδοι θα πρέπει να είναι όσο το δυνατόν πιο κρυφά και προσβάσιμα μόνο μέσω μιας καθορισμένης διεπαφής. Αυτό σας επιτρέπει να αλλάξετε την εσωτερική υλοποίηση της κλάσης χωρίς να επηρεάζεται ο υπόλοιπος κώδικας. + + +Λέξη-κλειδί Final .[#toc-final-keyword] +--------------------------------------- + +Στην PHP, μπορούμε να χρησιμοποιήσουμε τη λέξη-κλειδί `final` αν θέλουμε να αποτρέψουμε μια κλάση, μέθοδο ή σταθερά από το να κληρονομηθεί ή να αντικατασταθεί. Όταν μια κλάση χαρακτηρίζεται ως `final`, δεν μπορεί να επεκταθεί. Όταν μια μέθοδος χαρακτηρίζεται ως `final`, δεν μπορεί να αντικατασταθεί σε μια υποκλάση. + +Γνωρίζοντας ότι μια συγκεκριμένη κλάση ή μέθοδος δεν θα τροποποιείται πλέον, μπορούμε να κάνουμε αλλαγές πιο εύκολα χωρίς να ανησυχούμε για πιθανές συγκρούσεις. Για παράδειγμα, μπορούμε να προσθέσουμε μια νέα μέθοδο χωρίς να φοβόμαστε ότι ένας απόγονος μπορεί να έχει ήδη μια μέθοδο με το ίδιο όνομα, οδηγώντας σε σύγκρουση. Ή μπορούμε να αλλάξουμε τις παραμέτρους μιας μεθόδου, και πάλι χωρίς τον κίνδυνο να προκαλέσουμε ασυνέπεια με μια μέθοδο που έχει παρακαμφθεί σε έναν απόγονο. + +```php +final class FinalClass +{ +} + +// The following code will throw an error because we cannot inherit from a final class. +class ChildOfFinalClass extends FinalClass +{ +} +``` + +Σε αυτό το παράδειγμα, η απόπειρα κληρονόμησης από την τελική κλάση `FinalClass` θα οδηγήσει σε σφάλμα. + + +Στατικές ιδιότητες και μέθοδοι .[#toc-static-properties-and-methods] +-------------------------------------------------------------------- + +Όταν μιλάμε για "στατικά" στοιχεία μιας κλάσης στην PHP, εννοούμε μεθόδους και ιδιότητες που ανήκουν στην ίδια την κλάση και όχι σε μια συγκεκριμένη περίπτωση της κλάσης. Αυτό σημαίνει ότι δεν χρειάζεται να δημιουργήσετε μια παρουσία της κλάσης για να αποκτήσετε πρόσβαση σε αυτά. Αντ' αυτού, τις καλείτε ή τις προσπελαύνετε απευθείας μέσω του ονόματος της κλάσης. + +Λάβετε υπόψη ότι, εφόσον τα στατικά στοιχεία ανήκουν στην κλάση και όχι στις περιπτώσεις της, δεν μπορείτε να χρησιμοποιήσετε την ψευδομεταβλητή `$this` μέσα σε στατικές μεθόδους. + +Η χρήση στατικών ιδιοτήτων οδηγεί σε [συγκεχυμένο κώδικα γεμάτο παγίδες |dependency-injection:global-state], γι' αυτό δεν πρέπει ποτέ να τις χρησιμοποιείτε και δεν θα δείξουμε ένα παράδειγμα εδώ. Από την άλλη πλευρά, οι στατικές μέθοδοι είναι χρήσιμες. Ακολουθεί ένα παράδειγμα: + +```php +class Calculator +{ + public static function add($a, $b) + { + return $a + $b; + } + + public static function subtract($a, $b) + { + return $a - $b; + } +} + +// Using the static method without creating an instance of the class +echo Calculator::add(5, 3); // Output: 8 +echo Calculator::subtract(5, 3); // Output: 2 +``` + +Σε αυτό το παράδειγμα, δημιουργήσαμε μια κλάση `Calculator` με δύο στατικές μεθόδους. Μπορούμε να καλέσουμε αυτές τις μεθόδους απευθείας χωρίς να δημιουργήσουμε μια περίπτωση της κλάσης χρησιμοποιώντας τον τελεστή `::`. Οι στατικές μέθοδοι είναι ιδιαίτερα χρήσιμες για λειτουργίες που δεν εξαρτώνται από την κατάσταση μιας συγκεκριμένης περίπτωσης της κλάσης. + + +Σταθερές κλάσης .[#toc-class-constants] +--------------------------------------- + +Μέσα στις κλάσεις, έχουμε τη δυνατότητα να ορίσουμε σταθερές. Οι σταθερές είναι τιμές που δεν αλλάζουν ποτέ κατά τη διάρκεια της εκτέλεσης του προγράμματος. Σε αντίθεση με τις μεταβλητές, η τιμή μιας σταθεράς παραμένει η ίδια. + +```php +class Car +{ + public const NumberOfWheels = 4; + + public function displayNumberOfWheels(): int + { + echo self::NumberOfWheels; + } +} + +echo Car::NumberOfWheels; // Output: 4 +``` + +Σε αυτό το παράδειγμα, έχουμε μια κλάση `Car` με τη σταθερά `NumberOfWheels`. Όταν έχουμε πρόσβαση στη σταθερά μέσα στην κλάση, μπορούμε να χρησιμοποιήσουμε τη λέξη-κλειδί `self` αντί για το όνομα της κλάσης. + + +Διεπαφές αντικειμένων .[#toc-object-interfaces] +----------------------------------------------- + +Οι διεπαφές αντικειμένων λειτουργούν ως "συμβόλαια" για τις κλάσεις. Εάν μια κλάση πρόκειται να υλοποιήσει μια διεπαφή αντικειμένου, πρέπει να περιέχει όλες τις μεθόδους που ορίζει η διεπαφή. Είναι ένας πολύ καλός τρόπος για να διασφαλιστεί ότι ορισμένες κλάσεις τηρούν το ίδιο "συμβόλαιο" ή την ίδια δομή. + +Στην PHP, οι διεπαφές ορίζονται χρησιμοποιώντας τη λέξη-κλειδί `interface`. Όλες οι μέθοδοι που ορίζονται σε μια διεπαφή είναι δημόσιες (`public`). Όταν μια κλάση υλοποιεί μια διεπαφή, χρησιμοποιεί τη λέξη-κλειδί `implements`. + +```php +interface Animal +{ + function makeSound(); +} + +class Cat implements Animal +{ + public function makeSound() + { + echo 'Meow'; + } +} + +$cat = new Cat; +$cat->makeSound(); +``` + +Εάν μια κλάση υλοποιεί μια διασύνδεση, αλλά δεν έχουν οριστεί όλες οι αναμενόμενες μέθοδοι, η PHP θα εκπέμψει ένα σφάλμα. Μια κλάση μπορεί να υλοποιήσει πολλές διεπαφές ταυτόχρονα, κάτι που διαφέρει από την κληρονομικότητα, όπου μια κλάση μπορεί να κληρονομήσει μόνο από μια κλάση. + + +Αφηρημένες κλάσεις .[#toc-abstract-classes] +------------------------------------------- + +Οι αφηρημένες κλάσεις χρησιμεύουν ως πρότυπα βάσης για άλλες κλάσεις, αλλά δεν μπορείτε να δημιουργήσετε άμεσα τις περιπτώσεις τους. Περιέχουν ένα μείγμα από πλήρεις μεθόδους και αφηρημένες μεθόδους που δεν έχουν καθορισμένο περιεχόμενο. Οι κλάσεις που κληρονομούν από αφηρημένες κλάσεις πρέπει να παρέχουν ορισμούς για όλες τις αφηρημένες μεθόδους του γονέα. + +Χρησιμοποιούμε τη λέξη-κλειδί `abstract` για να ορίσουμε μια αφηρημένη κλάση. + +```php +abstract class AbstractClass +{ + public function regularMethod() + { + echo 'This is a regular method'; + } + + abstract public function abstractMethod(); +} + +class Child extends AbstractClass +{ + public function abstractMethod() + { + echo 'This is the implementation of the abstract method'; + } +} + +$instance = new Child; +$instance->regularMethod(); +$instance->abstractMethod(); +``` + +Σε αυτό το παράδειγμα, έχουμε μια αφηρημένη κλάση με μια κανονική και μια αφηρημένη μέθοδο. Στη συνέχεια έχουμε μια κλάση `Child` που κληρονομεί από την `AbstractClass` και παρέχει μια υλοποίηση για την αφηρημένη μέθοδο. + + +Έλεγχος τύπου .[#toc-type-checking] +----------------------------------- + +Στον προγραμματισμό, είναι ζωτικής σημασίας να διασφαλίζουμε ότι τα δεδομένα με τα οποία εργαζόμαστε έχουν τον σωστό τύπο. Στην PHP, διαθέτουμε εργαλεία που παρέχουν αυτή τη διασφάλιση. Η επαλήθευση ότι τα δεδομένα είναι σωστού τύπου ονομάζεται "έλεγχος τύπου". + +Τύποι που μπορεί να συναντήσουμε στην PHP: + +1. **Βασικοί τύποι**: Αυτοί περιλαμβάνουν `int` (ακέραιοι αριθμοί), `float` (αριθμοί κινητής υποδιαστολής), `bool` (τιμές boolean), `string` (συμβολοσειρές), `array` (πίνακες) και `null`. +2. **Κλάσεις**: Όταν θέλουμε μια τιμή να είναι περίπτωση μιας συγκεκριμένης κλάσης. +3. **Διασυνδέσεις**: Ορίζει ένα σύνολο μεθόδων που πρέπει να υλοποιεί μια κλάση. Μια τιμή που ανταποκρίνεται σε μια διεπαφή πρέπει να έχει αυτές τις μεθόδους. +4. **Μεικτοί τύποι**: Μπορούμε να καθορίσουμε ότι μια μεταβλητή μπορεί να έχει πολλούς επιτρεπόμενους τύπους. +5. **Void**: Αυτός ο ειδικός τύπος δηλώνει ότι μια συνάρτηση ή μέθοδος δεν επιστρέφει καμία τιμή. + +Ας δούμε πώς μπορούμε να τροποποιήσουμε τον κώδικα για να συμπεριλάβουμε τύπους: + +```php +class Person +{ + private int $age; + + public function __construct(int $age) + { + $this->age = $age; + } + + public function printAge(): void + { + echo "This person is " . $this->age . " years old."; + } +} + +/** + * A function that accepts a Person object and prints the person's age. + */ +function printPersonAge(Person $person): void +{ + $person->printAge(); +} +``` + +Με αυτόν τον τρόπο εξασφαλίζουμε ότι ο κώδικάς μας αναμένει και λειτουργεί με δεδομένα του σωστού τύπου, βοηθώντας μας να αποφύγουμε πιθανά σφάλματα. + + +Σύγκριση και ταυτότητα .[#toc-comparison-and-identity] +------------------------------------------------------ + +Στην PHP, μπορείτε να συγκρίνετε αντικείμενα με δύο τρόπους: + +1. Σύγκριση τιμών `==`: Ελέγχει αν τα αντικείμενα ανήκουν στην ίδια κλάση και έχουν τις ίδιες τιμές στις ιδιότητές τους. +2. Σύγκριση ταυτότητας `===`: Ελέγχει αν πρόκειται για την ίδια περίπτωση του αντικειμένου. + +```php +class Car +{ + public string $brand; + + public function __construct(string $brand) + { + $this->brand = $brand; + } +} + +$car1 = new Car('Skoda'); +$car2 = new Car('Skoda'); +$car3 = $car1; + +var_dump($car1 == $car2); // true, because they have the same value +var_dump($car1 === $car2); // false, because they are not the same instance +var_dump($car1 === $car3); // true, because $car3 is the same instance as $car1 +``` + + +Ο χειριστής `instanceof` .[#toc-the-instanceof-operator] +-------------------------------------------------------- + +Ο τελεστής `instanceof` σας επιτρέπει να προσδιορίσετε αν ένα δεδομένο αντικείμενο είναι παράδειγμα μιας συγκεκριμένης κλάσης, απόγονος αυτής της κλάσης ή αν υλοποιεί μια συγκεκριμένη διασύνδεση. + +Φανταστείτε ότι έχουμε μια κλάση `Person` και μια άλλη κλάση `Student`, η οποία είναι απόγονος της `Person`: + +```php +class Person +{ + private int $age; + + public function __construct(int $age) + { + $this->age = $age; + } +} + +class Student extends Person +{ + private string $major; + + public function __construct(int $age, string $major) + { + parent::__construct($age); + $this->major = $major; + } +} + +$student = new Student(20, 'Computer Science'); + +// Check if $student is an instance of the Student class +var_dump($student instanceof Student); // Output: bool(true) + +// Check if $student is an instance of the Person class (because Student is a descendant of Person) +var_dump($student instanceof Person); // Output: bool(true) +``` + +Από τις εξόδους, είναι προφανές ότι το αντικείμενο `$student` θεωρείται παράδειγμα και των δύο κλάσεων `Student` και `Person`. + + +Ρευστές διεπαφές .[#toc-fluent-interfaces] +------------------------------------------ + +Μια "ρευστή διεπαφή" είναι μια τεχνική στην OOP που επιτρέπει την αλυσιδωτή σύνδεση μεθόδων με μία μόνο κλήση. Αυτό συχνά απλοποιεί και αποσαφηνίζει τον κώδικα. + +Το βασικό στοιχείο μιας ρευστής διεπαφής είναι ότι κάθε μέθοδος στην αλυσίδα επιστρέφει μια αναφορά στο τρέχον αντικείμενο. Αυτό επιτυγχάνεται με τη χρήση του `return $this;` στο τέλος της μεθόδου. Αυτό το στυλ προγραμματισμού συνδέεται συχνά με μεθόδους που ονομάζονται "setters", οι οποίες ορίζουν τις τιμές των ιδιοτήτων ενός αντικειμένου. + +Ας δούμε πώς θα μπορούσε να μοιάζει μια ρευστή διεπαφή για την αποστολή μηνυμάτων ηλεκτρονικού ταχυδρομείου: + +```php +public function sendMessage() +{ + $email = new Email; + $email->setFrom('sender@example.com') + ->setRecipient('admin@example.com') + ->setMessage('Hello, this is a message.') + ->send(); +} +``` + +Σε αυτό το παράδειγμα, οι μέθοδοι `setFrom()`, `setRecipient()` και `setMessage()` χρησιμοποιούνται για να ορίσουν τις αντίστοιχες τιμές (αποστολέας, παραλήπτης, περιεχόμενο μηνύματος). Μετά τον ορισμό καθεμιάς από αυτές τις τιμές, οι μέθοδοι επιστρέφουν το τρέχον αντικείμενο (`$email`), επιτρέποντάς μας να ακολουθήσουμε αλυσιδωτά μια άλλη μέθοδο. Τέλος, καλούμε τη μέθοδο `send()`, η οποία στην πραγματικότητα στέλνει το μήνυμα ηλεκτρονικού ταχυδρομείου. + +Χάρη στις ρευστές διεπαφές, μπορούμε να γράψουμε κώδικα που είναι διαισθητικός και εύκολα αναγνώσιμος. + + +Αντιγραφή με `clone` .[#toc-copying-with-clone] +----------------------------------------------- + +Στην PHP, μπορούμε να δημιουργήσουμε ένα αντίγραφο ενός αντικειμένου χρησιμοποιώντας τον τελεστή `clone`. Με αυτόν τον τρόπο, λαμβάνουμε μια νέα περίπτωση με πανομοιότυπο περιεχόμενο. + +Αν χρειάζεται να τροποποιήσουμε κάποιες από τις ιδιότητές του κατά την αντιγραφή ενός αντικειμένου, μπορούμε να ορίσουμε μια ειδική μέθοδο `__clone()` στην κλάση. Αυτή η μέθοδος καλείται αυτόματα όταν το αντικείμενο κλωνοποιείται. + +```php +class Sheep +{ + public string $name; + + public function __construct(string $name) + { + $this->name = $name; + } + + public function __clone() + { + $this->name = 'Clone of ' . $this->name; + } +} + +$original = new Sheep('Dolly'); +echo $original->name . "\n"; // Outputs: Dolly + +$clone = clone $original; +echo $clone->name . "\n"; // Outputs: Clone of Dolly +``` + +Σε αυτό το παράδειγμα, έχουμε μια κλάση `Sheep` με μια ιδιότητα `$name`. Όταν κλωνοποιούμε μια περίπτωση αυτής της κλάσης, η μέθοδος `__clone()` εξασφαλίζει ότι το όνομα του κλωνοποιημένου προβάτου παίρνει το πρόθεμα "Clone of". + + +Χαρακτηριστικά .[#toc-traits] +----------------------------- + +Τα γνωρίσματα στην PHP είναι ένα εργαλείο που επιτρέπει την κοινή χρήση μεθόδων, ιδιοτήτων και σταθερών μεταξύ κλάσεων και αποτρέπει την επανάληψη κώδικα. Μπορείτε να τα φανταστείτε ως ένα μηχανισμό "αντιγραφής και επικόλλησης" (Ctrl-C και Ctrl-V), όπου το περιεχόμενο ενός γνωρίσματος "επικολλάται" σε κλάσεις. Αυτό σας επιτρέπει να επαναχρησιμοποιείτε κώδικα χωρίς να χρειάζεται να δημιουργείτε περίπλοκες ιεραρχίες κλάσεων. + +Ας ρίξουμε μια ματιά σε ένα απλό παράδειγμα χρήσης των traits στην PHP: + +```php +trait Honking +{ + public function honk() + { + echo 'Beep beep!'; + } +} + +class Car +{ + use Honking; +} + +class Truck +{ + use Honking; +} + +$car = new Car; +$car->honk(); // Outputs 'Beep beep!' + +$truck = new Truck; +$truck->honk(); // Also outputs 'Beep beep!' +``` + +Σε αυτό το παράδειγμα, έχουμε ένα trait με όνομα `Honking` που περιέχει μία μέθοδο `honk()`. Στη συνέχεια, έχουμε δύο κλάσεις: `Car` και `Truck`, οι οποίες χρησιμοποιούν το χαρακτηριστικό `Honking`. Ως αποτέλεσμα, και οι δύο κλάσεις "έχουν" τη μέθοδο `honk()` και μπορούμε να την καλέσουμε σε αντικείμενα και των δύο κλάσεων. + +Τα γνωρίσματα σας επιτρέπουν να μοιράζεστε εύκολα και αποτελεσματικά κώδικα μεταξύ κλάσεων. Δεν εισέρχονται στην ιεραρχία κληρονομικότητας, δηλαδή το `$car instanceof Honking` θα επιστρέψει το `false`. + + +Εξαιρέσεις +---------- + +Οι εξαιρέσεις στην OOP μας επιτρέπουν να χειριζόμαστε και να διαχειριζόμαστε σφάλματα που μπορεί να προκύψουν κατά την εκτέλεση του κώδικά μας. Πρόκειται ουσιαστικά για αντικείμενα που έχουν σχεδιαστεί για να καταγράφουν σφάλματα ή απροσδόκητες καταστάσεις στο πρόγραμμά σας. + +Στην PHP, έχουμε την ενσωματωμένη κλάση `Exception` για αυτά τα αντικείμενα. Διαθέτει διάφορες μεθόδους που μας επιτρέπουν να λάβουμε περισσότερες πληροφορίες σχετικά με την εξαίρεση, όπως το μήνυμα σφάλματος, το αρχείο και τη γραμμή όπου συνέβη το σφάλμα κ.λπ. + +Όταν προκύπτει ένα πρόβλημα, μπορούμε να "πετάξουμε" μια εξαίρεση (χρησιμοποιώντας την `throw`). Αν θέλουμε να "πιάσουμε" και να επεξεργαστούμε αυτή την εξαίρεση, χρησιμοποιούμε τα μπλοκ `try` και `catch`. + +Ας δούμε πώς λειτουργεί: + +```php +try { + throw new Exception('Message explaining the reason for the exception'); + + // This code won't execute + echo 'I am a message that nobody will read'; + +} catch (Exception $e) { + echo 'Exception caught: '. $e->getMessage(); +} +``` + +Είναι σημαντικό να σημειωθεί ότι μια εξαίρεση μπορεί να δημιουργηθεί βαθύτερα, κατά τη διάρκεια της κλήσης άλλων μεθόδων. + +Για ένα μπλοκ `try`, μπορούν να καθοριστούν πολλαπλά μπλοκ `catch`, αν περιμένετε διαφορετικούς τύπους εξαιρέσεων. + +Μπορούμε επίσης να δημιουργήσουμε μια ιεραρχία εξαιρέσεων, όπου κάθε κλάση εξαιρέσεων κληρονομεί από την προηγούμενη. Ως παράδειγμα, θεωρήστε μια απλή τραπεζική εφαρμογή που επιτρέπει καταθέσεις και αναλήψεις: + +```php +class BankingException extends Exception {} +class InsufficientFundsException extends BankingException {} +class ExceededLimitException extends BankingException {} + +class BankAccount +{ + private int $balance = 0; + private int $dailyLimit = 1000; + + public function deposit(int $amount): int + { + $this->balance += $amount; + return $this->balance; + } + + public function withdraw(int $amount): int + { + if ($amount > $this->balance) { + throw new InsufficientFundsException('Not enough funds in the account.'); + } + + if ($amount > $this->dailyLimit) { + throw new ExceededLimitException('Daily withdrawal limit exceeded.'); + } + + $this->balance -= $amount; + return $this->balance; + } +} + +$account = new BankAccount; +$account->deposit(500); + +try { + $account->withdraw(1500); +} catch (ExceededLimitException $e) { + echo $e->getMessage(); +} catch (InsufficientFundsException $e) { + echo $e->getMessage(); +} catch (BankingException $e) { + echo 'An error occurred during the operation.'; +} +``` + +Σε αυτό το παράδειγμα, είναι σημαντικό να σημειωθεί η σειρά των μπλοκ `catch`. Δεδομένου ότι όλες οι εξαιρέσεις κληρονομούν από το `BankingException`, αν είχαμε αυτό το μπλοκ πρώτο, όλες οι εξαιρέσεις θα συλλαμβάνονταν σε αυτό χωρίς ο κώδικας να φτάσει στα επόμενα μπλοκ `catch`. Επομένως, είναι σημαντικό να έχουμε πιο συγκεκριμένες εξαιρέσεις (δηλαδή αυτές που κληρονομούν από άλλες) πιο ψηλά στη σειρά των μπλοκ `catch` από τις εξαιρέσεις των γονέων τους. + + +Βέλτιστες πρακτικές .[#toc-best-practices] +------------------------------------------ + +Μόλις μάθετε τις βασικές αρχές του αντικειμενοστραφούς προγραμματισμού, είναι ζωτικής σημασίας να εστιάσετε στις βέλτιστες πρακτικές του OOP. Αυτές θα σας βοηθήσουν να γράψετε κώδικα που δεν είναι μόνο λειτουργικός αλλά και ευανάγνωστος, κατανοητός και εύκολα συντηρήσιμος. + +1) **Διαχωρισμός των ανησυχιών**: Κάθε κλάση θα πρέπει να έχει σαφώς καθορισμένη ευθύνη και να ασχολείται μόνο με μία πρωταρχική εργασία. Αν μια κλάση κάνει πάρα πολλά πράγματα, ίσως είναι σκόπιμο να τη χωρίσετε σε μικρότερες, εξειδικευμένες κλάσεις. +2) **Ενθυλάκωση**: Τα δεδομένα και οι μέθοδοι θα πρέπει να είναι όσο το δυνατόν πιο κρυφά και προσβάσιμα μόνο μέσω μιας καθορισμένης διεπαφής. Αυτό σας επιτρέπει να αλλάξετε την εσωτερική υλοποίηση μιας κλάσης χωρίς να επηρεάζεται ο υπόλοιπος κώδικας. +3) **Έγχυση εξάρτησης**: Αντί να δημιουργείτε εξαρτήσεις απευθείας μέσα σε μια κλάση, θα πρέπει να τις "εγχέετε" από έξω. Για μια βαθύτερη κατανόηση αυτής της αρχής, σας συνιστούμε τα [κεφάλαια για το Dependency Injection |dependency-injection:introduction]. diff --git a/nette/en/introduction-to-object-oriented-programming.texy b/nette/en/introduction-to-object-oriented-programming.texy new file mode 100644 index 0000000000..bc21f72802 --- /dev/null +++ b/nette/en/introduction-to-object-oriented-programming.texy @@ -0,0 +1,719 @@ +Introduction to Object-Oriented Programming +******************************************* + +.[perex] +The term "OOP" stands for Object-Oriented Programming, which is a way to organize and structure code. OOP allows us to view a program as a collection of objects that communicate with each other, rather than a sequence of commands and functions. + +In OOP, an "object" is a unit that contains data and functions that operate on that data. Objects are created based on "classes", which can be understood as blueprints or templates for objects. Once we have a class, we can create its "instance", which is a specific object made from that class. + +Let's look at how we can create a simple class in PHP. When defining a class, we use the keyword "class", followed by the class name, and then curly braces that enclose the class's functions (called "methods") and class variables (called "properties" or "attributes"): + +```php +class Car +{ + function honk() + { + echo 'Beep beep!'; + } +} +``` + +In this example, we've created a class named `Car` with one function (or "method") called `honk`. + +Each class should solve only one main task. If a class is doing too many things, it may be appropriate to divide it into smaller, specialized classes. + +Classes are typically stored in separate files to keep the code organized and easy to navigate. The file name should match the class name, so for the `Car` class, the file name would be `Car.php`. + +When naming classes, it's good to follow the "PascalCase" convention, meaning each word in the name starts with a capital letter, and there are no underscores or other separators. Methods and properties follow the "camelCase" convention, meaning they start with a lowercase letter. + +Some methods in PHP have special roles and are prefixed with `__` (two underscores). One of the most important special methods is the "constructor", labeled as `__construct`. The constructor is a method that's automatically called when creating a new instance of a class. + +We often use the constructor to set the initial state of an object. For example, when creating an object representing a person, you might use the constructor to set their age, name, or other attributes. + +Let's see how to use a constructor in PHP: + +```php +class Person +{ + private $age; + + function __construct($age) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +$person = new Person(25); +echo $person->howOldAreYou(); // Outputs: 25 +``` + +In this example, the `Person` class has a property `$age` and a constructor that sets this property. The `howOldAreYou()` method then provides access to the person's age. + +The `new` keyword is used to create a new instance of a class. In the example above, we created a new person aged 25. + +You can also set default values for constructor parameters if they aren't specified when creating an object. For instance: + +```php +class Person +{ + private $age; + + function __construct($age = 20) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +$person = new Person; // if no argument is passed, parentheses can be omitted +echo $person->howOldAreYou(); // Outputs: 20 +``` + +In this example, if you don't specify an age when creating a `Person` object, the default value of 20 will be used. + +Lastly, property definition with its initialization via the constructor can be shortened and simplified like this: + +```php +class Person +{ + function __construct( + private $age = 20, + ) { + } +} +``` + + +Namespaces +---------- + +Namespaces allow us to organize and group related classes, functions, and constants while avoiding naming conflicts. You can think of them like folders on a computer, where each folder contains files related to a specific project or topic. + +Namespaces are especially useful in larger projects or when using third-party libraries where class naming conflicts might arise. + +Imagine you have a class named `Car` in your project, and you want to place it in a namespace called `Transport`. You would do it like this: + +```php +namespace Transport; + +class Car +{ + function honk() + { + echo 'Beep beep!'; + } +} +``` + +If you want to use the `Car` class in another file, you need to specify from which namespace the class originates: + +```php +$car = new Transport\Car; +``` + +For simplification, you can specify at the beginning of the file which class from a particular namespace you want to use, allowing you to create instances without mentioning the full path: + +```php +use Transport\Car; + +$car = new Car; +``` + + +Inheritance +----------- + +Inheritance is a tool of object-oriented programming that allows the creation of new classes based on existing ones, inheriting their properties and methods, and extending or redefining them as needed. Inheritance ensures code reusability and class hierarchy. + +Simply put, if we have one class and want to create another derived from it but with some modifications, we can "inherit" the new class from the original one. + +In PHP, inheritance is implemented using the `extends` keyword. + +Our `Person` class stores age information. We can have another class, `Student`, which extends `Person` and adds information about the field of study. + +Let's look at an example: + +```php +class Person +{ + private $age; + + function __construct($age) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +class Student extends Person +{ + private $fieldOfStudy; + + function __construct($age, $fieldOfStudy) + { + parent::__construct($age); + $this->fieldOfStudy = $fieldOfStudy; + } + + function printInformation() + { + echo 'Age of student: ', $this->howOldAreYou(); + echo 'Field of study: ', $this->fieldOfStudy; + } +} + +$student = new Student(20, 'Computer Science'); +$student->printInformation(); +``` + +How does this code work? + +- We used the `extends` keyword to extend the `Person` class, meaning the `Student` class inherits all methods and properties from `Person`. + +- The `parent::` keyword allows us to call methods from the parent class. In this case, we called the constructor from the `Person` class before adding our own functionality to the `Student` class. + +Inheritance is meant for situations where there's an "is a" relationship between classes. For instance, a `Student` is a `Person`. A cat is an animal. It allows us in cases where we expect one object (e.g., "Person") in the code to use a derived object instead (e.g., "Student"). + +It's essential to realize that the primary purpose of inheritance **is not** to prevent code duplication. On the contrary, misuse of inheritance can lead to complex and hard-to-maintain code. If there's no "is a" relationship between classes, we should consider composition instead of inheritance. + + +Composition +----------- + +Composition is a technique where, instead of inheriting properties and methods from another class, we simply use its instance in our class. This allows us to combine functionalities and properties of multiple classes without creating complex inheritance structures. + +For example, we have a `Engine` class and a `Car` class. Instead of saying "A car is an engine", we say "A car has an engine", which is a typical composition relationship. + +```php +class Engine +{ + function start() + { + echo "Engine is running."; + } +} + +class Car +{ + private $engine; + + function __construct() + { + $this->engine = new Engine; + } + + function start() + { + $this->engine->start(); + echo "The car is ready to drive!"; + } +} + +$car = new Car; +$car->start(); +``` + +Here, the `Car` doesn't have all the properties and methods of the `Engine`, but it has access to it through the `$engine` property. + +The advantage of composition is greater design flexibility and better adaptability for future changes. + + +Visibility +---------- + +In PHP, you can define "visibility" for class properties, methods, and constants. Visibility determines where you can access these elements. + +1. **Public:** If an element is marked as `public`, it means you can access it from anywhere, even outside the class. + +2. **Protected:** An element marked as `protected` is accessible only within the class and all its descendants (classes that inherit from it). + +3. **Private:** If an element is `private`, you can access it only from within the class where it was defined. + +If you don't specify visibility, PHP will automatically set it to `public`. + +Let's look at a sample code: + +```php +class VisibilityExample +{ + public $publicProperty = 'Public'; + protected $protectedProperty = 'Protected'; + private $privateProperty = 'Private'; + + public function printProperties() + { + echo $this->publicProperty; // Works + echo $this->protectedProperty; // Works + echo $this->privateProperty; // Works + } +} + +$object = new VisibilityExample; +$object->printProperties(); +echo $object->publicProperty; // Works +// echo $object->protectedProperty; // Throws an error +// echo $object->privateProperty; // Throws an error +``` + +Continuing with class inheritance: + +```php +class ChildClass extends VisibilityExample +{ + public function printProperties() + { + echo $this->publicProperty; // Works + echo $this->protectedProperty; // Works + // echo $this->privateProperty; // Throws an error + } +} +``` + +In this case, the `printProperties()` method in the `ChildClass` can access the public and protected properties but cannot access the private properties of the parent class. + +Data and methods should be as hidden as possible and only accessible through a defined interface. This allows you to change the internal implementation of the class without affecting the rest of the code. + + +Final Keyword +------------- + +In PHP, we can use the `final` keyword if we want to prevent a class, method, or constant from being inherited or overridden. When a class is marked as `final`, it cannot be extended. When a method is marked as `final`, it cannot be overridden in a subclass. + +Being aware that a certain class or method will no longer be modified allows us to make changes more easily without worrying about potential conflicts. For example, we can add a new method without fear that a descendant might already have a method with the same name, leading to a collision. Or we can change the parameters of a method, again without the risk of causing inconsistency with an overridden method in a descendant. + +```php +final class FinalClass +{ +} + +// The following code will throw an error because we cannot inherit from a final class. +class ChildOfFinalClass extends FinalClass +{ +} +``` + +In this example, attempting to inherit from the final class `FinalClass` will result in an error. + + +Static Properties and Methods +----------------------------- + +When we talk about "static" elements of a class in PHP, we mean methods and properties that belong to the class itself, not to a specific instance of the class. This means that you don't have to create an instance of the class to access them. Instead, you call or access them directly through the class name. + +Keep in mind that since static elements belong to the class and not its instances, you cannot use the `$this` pseudo-variable inside static methods. + +Using static properties leads to [obfuscated code full of pitfalls|dependency-injection:global-state], so you should never use them, and we won't show an example here. On the other hand, static methods are useful. Here's an example: + +```php +class Calculator +{ + public static function add($a, $b) + { + return $a + $b; + } + + public static function subtract($a, $b) + { + return $a - $b; + } +} + +// Using the static method without creating an instance of the class +echo Calculator::add(5, 3); // Output: 8 +echo Calculator::subtract(5, 3); // Output: 2 +``` + +In this example, we created a `Calculator` class with two static methods. We can call these methods directly without creating an instance of the class using the `::` operator. Static methods are especially useful for operations that don't depend on the state of a specific class instance. + + +Class Constants +--------------- + +Within classes, we have the option to define constants. Constants are values that never change during the program's execution. Unlike variables, the value of a constant remains the same. + +```php +class Car +{ + public const NumberOfWheels = 4; + + public function displayNumberOfWheels(): int + { + echo self::NumberOfWheels; + } +} + +echo Car::NumberOfWheels; // Output: 4 +``` + +In this example, we have a `Car` class with the `NumberOfWheels` constant. When accessing the constant inside the class, we can use the `self` keyword instead of the class name. + + +Object Interfaces +----------------- + +Object interfaces act as "contracts" for classes. If a class is to implement an object interface, it must contain all the methods that the interface defines. It's a great way to ensure that certain classes adhere to the same "contract" or structure. + +In PHP, interfaces are defined using the `interface` keyword. All methods defined in an interface are public (`public`). When a class implements an interface, it uses the `implements` keyword. + +```php +interface Animal +{ + function makeSound(); +} + +class Cat implements Animal +{ + public function makeSound() + { + echo 'Meow'; + } +} + +$cat = new Cat; +$cat->makeSound(); +``` + +If a class implements an interface, but not all expected methods are defined, PHP will throw an error. A class can implement multiple interfaces at once, which is different from inheritance, where a class can only inherit from one class. + + +Abstract Classes +---------------- + +Abstract classes serve as base templates for other classes, but you cannot create their instances directly. They contain a mix of complete methods and abstract methods that don't have a defined content. Classes that inherit from abstract classes must provide definitions for all the abstract methods from the parent. + +We use the `abstract` keyword to define an abstract class. + +```php +abstract class AbstractClass +{ + public function regularMethod() + { + echo 'This is a regular method'; + } + + abstract public function abstractMethod(); +} + +class Child extends AbstractClass +{ + public function abstractMethod() + { + echo 'This is the implementation of the abstract method'; + } +} + +$instance = new Child; +$instance->regularMethod(); +$instance->abstractMethod(); +``` + +In this example, we have an abstract class with one regular and one abstract method. Then we have a `Child` class that inherits from `AbstractClass` and provides an implementation for the abstract method. + + +Type Checking +------------- + +In programming, it's crucial to ensure that the data we work with is of the correct type. In PHP, we have tools that provide this assurance. Verifying that data is of the correct type is called "type checking." + +Types we might encounter in PHP: + +1. **Basic types**: These include `int` (integers), `float` (floating-point numbers), `bool` (boolean values), `string` (strings), `array` (arrays), and `null`. +2. **Classes**: When we want a value to be an instance of a specific class. +3. **Interfaces**: Defines a set of methods that a class must implement. A value that meets an interface must have these methods. +4. **Mixed types**: We can specify that a variable can have multiple allowed types. +5. **Void**: This special type indicates that a function or method does not return any value. + +Let's see how to modify the code to include types: + +```php +class Person +{ + private int $age; + + public function __construct(int $age) + { + $this->age = $age; + } + + public function printAge(): void + { + echo "This person is " . $this->age . " years old."; + } +} + +/** + * A function that accepts a Person object and prints the person's age. + */ +function printPersonAge(Person $person): void +{ + $person->printAge(); +} +``` + +In this way, we ensure that our code expects and works with data of the correct type, helping us prevent potential errors. + + +Comparison and Identity +----------------------- + +In PHP, you can compare objects in two ways: + +1. Value comparison `==`: Checks if the objects are of the same class and have the same values in their properties. +2. Identity `===`: Checks if it's the same instance of the object. + +```php +class Car +{ + public string $brand; + + public function __construct(string $brand) + { + $this->brand = $brand; + } +} + +$car1 = new Car('Skoda'); +$car2 = new Car('Skoda'); +$car3 = $car1; + +var_dump($car1 == $car2); // true, because they have the same value +var_dump($car1 === $car2); // false, because they are not the same instance +var_dump($car1 === $car3); // true, because $car3 is the same instance as $car1 +``` + + +The `instanceof` Operator +------------------------- + +The `instanceof` operator allows you to determine if a given object is an instance of a specific class, a descendant of that class, or if it implements a certain interface. + +Imagine we have a class `Person` and another class `Student`, which is a descendant of `Person`: + +```php +class Person +{ + private int $age; + + public function __construct(int $age) + { + $this->age = $age; + } +} + +class Student extends Person +{ + private string $major; + + public function __construct(int $age, string $major) + { + parent::__construct($age); + $this->major = $major; + } +} + +$student = new Student(20, 'Computer Science'); + +// Check if $student is an instance of the Student class +var_dump($student instanceof Student); // Output: bool(true) + +// Check if $student is an instance of the Person class (because Student is a descendant of Person) +var_dump($student instanceof Person); // Output: bool(true) +``` + +From the outputs, it's evident that the `$student` object is considered an instance of both the `Student` and `Person` classes. + + +Fluent Interfaces +----------------- + +A "Fluent Interface" is a technique in OOP that allows chaining methods together in a single call. This often simplifies and clarifies the code. + +The key element of a fluent interface is that each method in the chain returns a reference to the current object. This is achieved by using `return $this;` at the end of the method. This programming style is often associated with methods called "setters", which set the values of an object's properties. + +Let's see what a fluent interface might look like for sending emails: + +```php +public function sendMessage() +{ + $email = new Email; + $email->setFrom('sender@example.com') + ->setRecipient('admin@example.com') + ->setMessage('Hello, this is a message.') + ->send(); +} +``` + +In this example, the methods `setFrom()`, `setRecipient()`, and `setMessage()` are used to set the corresponding values (sender, recipient, message content). After setting each of these values, the methods return the current object (`$email`), allowing us to chain another method after it. Finally, we call the `send()` method, which actually sends the email. + +Thanks to fluent interfaces, we can write code that is intuitive and easily readable. + + +Copying with `clone` +-------------------- + +In PHP, we can create a copy of an object using the `clone` operator. This way, we get a new instance with identical content. + +If we need to modify some of its properties when copying an object, we can define a special `__clone()` method in the class. This method is automatically called when the object is cloned. + +```php +class Sheep +{ + public string $name; + + public function __construct(string $name) + { + $this->name = $name; + } + + public function __clone() + { + $this->name = 'Clone of ' . $this->name; + } +} + +$original = new Sheep('Dolly'); +echo $original->name . "\n"; // Outputs: Dolly + +$clone = clone $original; +echo $clone->name . "\n"; // Outputs: Clone of Dolly +``` + +In this example, we have a `Sheep` class with one property `$name`. When we clone an instance of this class, the `__clone()` method ensures that the name of the cloned sheep gets the prefix "Clone of". + + +Traits +------ + +Traits in PHP are a tool that allows sharing methods, properties and constants between classes and prevents code duplication. You can think of them as a "copy and paste" mechanism (Ctrl-C and Ctrl-V), where the content of a trait is "pasted" into classes. This allows you to reuse code without having to create complicated class hierarchies. + +Let's take a look at a simple example of how to use traits in PHP: + +```php +trait Honking +{ + public function honk() + { + echo 'Beep beep!'; + } +} + +class Car +{ + use Honking; +} + +class Truck +{ + use Honking; +} + +$car = new Car; +$car->honk(); // Outputs 'Beep beep!' + +$truck = new Truck; +$truck->honk(); // Also outputs 'Beep beep!' +``` + +In this example, we have a trait named `Honking` that contains one method `honk()`. Then we have two classes: `Car` and `Truck`, both of which use the `Honking` trait. As a result, both classes "have" the `honk()` method, and we can call it on objects of both classes. + +Traits allow you to easily and efficiently share code between classes. They do not enter the inheritance hierarchy, i.e., `$car instanceof Honking` will return `false`. + + +Exceptions +---------- + +Exceptions in OOP allow us to handle and manage errors that may arise during the execution of our code. They are essentially objects designed to record errors or unexpected situations in your program. + +In PHP, we have the built-in `Exception` class for these objects. It has several methods that allow us to get more information about the exception, such as the error message, the file, and the line where the error occurred, etc. + +When a problem arises, we can "throw" an exception (using `throw`). If we want to "catch" and process this exception, we use `try` and `catch` blocks. + +Let's see how it works: + +```php +try { + throw new Exception('Message explaining the reason for the exception'); + + // This code won't execute + echo 'I am a message that nobody will read'; + +} catch (Exception $e) { + echo 'Exception caught: '. $e->getMessage(); +} +``` + +It's important to note that an exception can be thrown deeper, during the call to other methods. + +For one `try` block, multiple `catch` blocks can be specified if you expect different types of exceptions. + +We can also create an exception hierarchy, where each exception class inherits from the previous one. As an example, consider a simple banking application that allows deposits and withdrawals: + +```php +class BankingException extends Exception {} +class InsufficientFundsException extends BankingException {} +class ExceededLimitException extends BankingException {} + +class BankAccount +{ + private int $balance = 0; + private int $dailyLimit = 1000; + + public function deposit(int $amount): int + { + $this->balance += $amount; + return $this->balance; + } + + public function withdraw(int $amount): int + { + if ($amount > $this->balance) { + throw new InsufficientFundsException('Not enough funds in the account.'); + } + + if ($amount > $this->dailyLimit) { + throw new ExceededLimitException('Daily withdrawal limit exceeded.'); + } + + $this->balance -= $amount; + return $this->balance; + } +} + +$account = new BankAccount; +$account->deposit(500); + +try { + $account->withdraw(1500); +} catch (ExceededLimitException $e) { + echo $e->getMessage(); +} catch (InsufficientFundsException $e) { + echo $e->getMessage(); +} catch (BankingException $e) { + echo 'An error occurred during the operation.'; +} +``` + +In this example, it's important to note the order of the `catch` blocks. Since all exceptions inherit from `BankingException`, if we had this block first, all exceptions would be caught in it without the code reaching the subsequent `catch` blocks. Therefore, it's important to have more specific exceptions (i.e., those that inherit from others) higher in the `catch` block order than their parent exceptions. + + +Best Practices +-------------- + +Once you have the basic principles of object-oriented programming under your belt, it's crucial to focus on best practices in OOP. These will help you write code that is not only functional but also readable, understandable, and easily maintainable. + +1) **Separation of Concerns**: Each class should have a clearly defined responsibility and should address only one primary task. If a class does too many things, it might be appropriate to split it into smaller, specialized classes. +2) **Encapsulation**: Data and methods should be as hidden as possible and accessible only through a defined interface. This allows you to change the internal implementation of a class without affecting the rest of the code. +3) **Dependency Injection**: Instead of creating dependencies directly within a class, you should "inject" them from the outside. For a deeper understanding of this principle, we recommend the [chapters on Dependency Injection|dependency-injection:introduction]. diff --git a/nette/es/introduction-to-object-oriented-programming.texy b/nette/es/introduction-to-object-oriented-programming.texy new file mode 100644 index 0000000000..a4c42a0dcc --- /dev/null +++ b/nette/es/introduction-to-object-oriented-programming.texy @@ -0,0 +1,719 @@ +Introducción a la programación orientada a objetos +************************************************** + +.[perex] +El término "POO" significa Programación Orientada a Objetos, que es una forma de organizar y estructurar el código. La POO nos permite ver un programa como una colección de objetos que se comunican entre sí, en lugar de como una secuencia de comandos y funciones. + +En la programación orientada a objetos, un "objeto" es una unidad que contiene datos y funciones que operan con esos datos. Los objetos se crean a partir de "clases", que pueden entenderse como planos o plantillas de objetos. Una vez que tenemos una clase, podemos crear su "instancia", que es un objeto específico hecho a partir de esa clase. + +Veamos cómo podemos crear una clase simple en PHP. Cuando definimos una clase, usamos la palabra clave "class", seguida del nombre de la clase, y luego llaves que encierran las funciones de la clase (llamadas "métodos") y las variables de la clase (llamadas "propiedades" o "atributos"): + +```php +class Car +{ + function honk() + { + echo 'Beep beep!'; + } +} +``` + +En este ejemplo, hemos creado una clase llamada `Car` con una función (o "método") llamada `honk`. + +Cada clase debe resolver una sola tarea principal. Si una clase hace demasiadas cosas, puede ser conveniente dividirla en clases más pequeñas y especializadas. + +Las clases suelen almacenarse en archivos separados para mantener el código organizado y facilitar la navegación. El nombre del archivo debe coincidir con el nombre de la clase, por lo que para la clase `Car`, el nombre del archivo sería `Car.php`. + +Cuando se nombran las clases, es bueno seguir la convención "PascalCase", lo que significa que cada palabra en el nombre comienza con una letra mayúscula, y no hay guiones bajos u otros separadores. Los métodos y propiedades siguen la convención "camelCase", lo que significa que empiezan con minúscula. + +Algunos métodos en PHP tienen roles especiales y están prefijados con `__` (dos guiones bajos). Uno de los métodos especiales más importantes es el "constructor", etiquetado como `__construct`. El constructor es un método que es llamado automáticamente cuando se crea una nueva instancia de una clase. + +A menudo utilizamos el constructor para establecer el estado inicial de un objeto. Por ejemplo, al crear un objeto que representa a una persona, puedes utilizar el constructor para establecer su edad, nombre u otros atributos. + +Veamos como usar un constructor en PHP: + +```php +class Person +{ + private $age; + + function __construct($age) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +$person = new Person(25); +echo $person->howOldAreYou(); // Outputs: 25 +``` + +En este ejemplo, la clase `Person` tiene una propiedad `$age` y un constructor que establece esta propiedad. El método `howOldAreYou()` proporciona acceso a la edad de la persona. + +La palabra clave `new` se utiliza para crear una nueva instancia de una clase. En el ejemplo anterior, hemos creado una nueva persona de 25 años. + +También puedes establecer valores por defecto para los parámetros del constructor si no se especifican al crear un objeto. Por ejemplo: + +```php +class Person +{ + private $age; + + function __construct($age = 20) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +$person = new Person; // if no argument is passed, parentheses can be omitted +echo $person->howOldAreYou(); // Outputs: 20 +``` + +En este ejemplo, si no se especifica una edad al crear un objeto `Person`, se utilizará el valor por defecto de 20. + +Por último, la definición de propiedades con su inicialización a través del constructor se puede acortar y simplificar así: + +```php +class Person +{ + function __construct( + private $age = 20, + ) { + } +} +``` + + +Espacios de nombres .[#toc-namespaces] +-------------------------------------- + +Los espacios de nombres nos permiten organizar y agrupar clases, funciones y constantes relacionadas evitando conflictos de nombres. Puedes pensar en ellos como carpetas en un ordenador, donde cada carpeta contiene archivos relacionados con un proyecto o tema específico. + +Los espacios de nombres son especialmente útiles en proyectos grandes o cuando se utilizan librerías de terceros donde pueden surgir conflictos de nombres de clases. + +Imagina que tienes una clase llamada `Car` en tu proyecto, y quieres colocarla en un espacio de nombres llamado `Transport`. Lo harías de la siguiente manera + +```php +namespace Transport; + +class Car +{ + function honk() + { + echo 'Beep beep!'; + } +} +``` + +Si quieres utilizar la clase `Car` en otro archivo, tienes que especificar de qué espacio de nombres procede la clase: + +```php +$car = new Transport\Car; +``` + +Para simplificar, puede especificar al principio del archivo qué clase de un espacio de nombres concreto desea utilizar, lo que le permitirá crear instancias sin mencionar la ruta completa: + +```php +use Transport\Car; + +$car = new Car; +``` + + +Herencia .[#toc-inheritance] +---------------------------- + +La herencia es una herramienta de la programación orientada a objetos que permite crear nuevas clases a partir de otras ya existentes, heredando sus propiedades y métodos, y ampliándolas o redefiniéndolas según sea necesario. La herencia garantiza la reutilización del código y la jerarquía de las clases. + +En pocas palabras, si tenemos una clase y queremos crear otra derivada de ella pero con algunas modificaciones, podemos "heredar" la nueva clase de la original. + +En PHP, la herencia se implementa utilizando la palabra clave `extends`. + +Nuestra clase `Person` almacena información sobre la edad. Podemos tener otra clase, `Student`, que extienda `Person` y añada información sobre el campo de estudio. + +Veamos un ejemplo: + +```php +class Person +{ + private $age; + + function __construct($age) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +class Student extends Person +{ + private $fieldOfStudy; + + function __construct($age, $fieldOfStudy) + { + parent::__construct($age); + $this->fieldOfStudy = $fieldOfStudy; + } + + function printInformation() + { + echo 'Age of student: ', $this->howOldAreYou(); + echo 'Field of study: ', $this->fieldOfStudy; + } +} + +$student = new Student(20, 'Computer Science'); +$student->printInformation(); +``` + +¿Cómo funciona este código? + +- Utilizamos la palabra clave `extends` para extender la clase `Person`, lo que significa que la clase `Student` hereda todos los métodos y propiedades de `Person`. + +- La palabra clave `parent::` nos permite llamar a métodos de la clase padre. En este caso, hemos llamado al constructor de la clase `Person` antes de añadir nuestra propia funcionalidad a la clase `Student`. + +La herencia está pensada para situaciones en las que existe una relación "es un" entre clases. Por ejemplo, un `Student` es un `Person`. Un gato es un animal. Nos permite, en casos en los que esperamos un objeto (por ejemplo, "Persona") en el código, utilizar un objeto derivado en su lugar (por ejemplo, "Estudiante"). + +Es esencial darse cuenta de que el propósito principal de la herencia **no es** evitar la duplicación de código. Al contrario, un mal uso de la herencia puede llevar a un código complejo y difícil de mantener. Si no existe una relación "es un" entre clases, deberíamos considerar la composición en lugar de la herencia. + + +Composición .[#toc-composition] +------------------------------- + +La composición es una técnica en la que, en lugar de heredar propiedades y métodos de otra clase, simplemente utilizamos su instancia en nuestra clase. Esto nos permite combinar funcionalidades y propiedades de múltiples clases sin crear complejas estructuras de herencia. + +Por ejemplo, tenemos una clase `Engine` y otra `Car`. En lugar de decir "Un coche es un motor", decimos "Un coche tiene un motor", que es una relación de composición típica. + +```php +class Engine +{ + function start() + { + echo "Engine is running."; + } +} + +class Car +{ + private $engine; + + function __construct() + { + $this->engine = new Engine; + } + + function start() + { + $this->engine->start(); + echo "The car is ready to drive!"; + } +} + +$car = new Car; +$car->start(); +``` + +Aquí, la `Car` no tiene todas las propiedades y métodos de la `Engine`, pero tiene acceso a ella a través de la propiedad `$engine`. + +La ventaja de la composición es una mayor flexibilidad de diseño y una mejor adaptabilidad a futuros cambios. + + +Visibilidad .[#toc-visibility] +------------------------------ + +En PHP, usted puede definir "visibilidad" para propiedades de clases, métodos y constantes. La visibilidad determina dónde se puede acceder a estos elementos. + +1. **Público:** Si un elemento está marcado como `public`, significa que puede acceder a él desde cualquier lugar, incluso fuera de la clase. + +2. **Protegido:** Un elemento marcado como `protected` sólo es accesible dentro de la clase y todos sus descendientes (clases que heredan de ella). + +3. **Privado:** Si un elemento es `private`, sólo se puede acceder a él desde dentro de la clase en la que se definió. + +Si no especifica la visibilidad, PHP la establecerá automáticamente en `public`. + +Veamos un ejemplo de código: + +```php +class VisibilityExample +{ + public $publicProperty = 'Public'; + protected $protectedProperty = 'Protected'; + private $privateProperty = 'Private'; + + public function printProperties() + { + echo $this->publicProperty; // Works + echo $this->protectedProperty; // Works + echo $this->privateProperty; // Works + } +} + +$object = new VisibilityExample; +$object->printProperties(); +echo $object->publicProperty; // Works +// echo $object->protectedProperty; // Throws an error +// echo $object->privateProperty; // Throws an error +``` + +Continuando con la herencia de clases: + +```php +class ChildClass extends VisibilityExample +{ + public function printProperties() + { + echo $this->publicProperty; // Works + echo $this->protectedProperty; // Works + // echo $this->privateProperty; // Throws an error + } +} +``` + +En este caso, el método `printProperties()` de `ChildClass` puede acceder a las propiedades públicas y protegidas pero no puede acceder a las propiedades privadas de la clase padre. + +Los datos y métodos deben estar lo más ocultos posible y sólo se puede acceder a ellos a través de una interfaz definida. Esto permite cambiar la implementación interna de la clase sin afectar al resto del código. + + +Palabra clave final .[#toc-final-keyword] +----------------------------------------- + +En PHP, podemos usar la palabra clave `final` si queremos evitar que una clase, método o constante sea heredada o sobrescrita. Cuando una clase es marcada como `final`, no puede ser extendida. Cuando un método es marcado como `final`, no puede ser sobrescrito en una subclase. + +Ser conscientes de que una determinada clase o método ya no se modificará nos permite realizar cambios más fácilmente sin preocuparnos por posibles conflictos. Por ejemplo, podemos añadir un nuevo método sin temor a que un descendiente pueda tener ya un método con el mismo nombre, provocando una colisión. O podemos cambiar los parámetros de un método, de nuevo sin el riesgo de causar inconsistencia con un método anulado en un descendiente. + +```php +final class FinalClass +{ +} + +// The following code will throw an error because we cannot inherit from a final class. +class ChildOfFinalClass extends FinalClass +{ +} +``` + +En este ejemplo, si se intenta heredar de la clase final `FinalClass` se producirá un error. + + +Propiedades estáticas y métodos .[#toc-static-properties-and-methods] +--------------------------------------------------------------------- + +Cuando hablamos de elementos "estáticos" de una clase en PHP, nos referimos a métodos y propiedades que pertenecen a la clase misma, no a una instancia específica de la clase. Esto significa que no tiene que crear una instancia de la clase para acceder a ellos. En su lugar, se les llama o accede directamente a través del nombre de la clase. + +Ten en cuenta que como los elementos estáticos pertenecen a la clase y no a sus instancias, no puedes utilizar la pseudo-variable `$this` dentro de métodos estáticos. + +El uso de propiedades estáticas conduce a [código ofuscado lleno de trampas |dependency-injection:global-state], por lo que nunca deberías usarlas, y no mostraremos un ejemplo aquí. Por otro lado, los métodos estáticos son útiles. Aquí tienes un ejemplo: + +```php +class Calculator +{ + public static function add($a, $b) + { + return $a + $b; + } + + public static function subtract($a, $b) + { + return $a - $b; + } +} + +// Using the static method without creating an instance of the class +echo Calculator::add(5, 3); // Output: 8 +echo Calculator::subtract(5, 3); // Output: 2 +``` + +En este ejemplo, creamos una clase `Calculator` con dos métodos estáticos. Podemos llamar a estos métodos directamente sin crear una instancia de la clase utilizando el operador `::`. Los métodos estáticos son especialmente útiles para operaciones que no dependen del estado de una instancia específica de la clase. + + +Constantes de clase .[#toc-class-constants] +------------------------------------------- + +Dentro de las clases, tenemos la opción de definir constantes. Las constantes son valores que nunca cambian durante la ejecución del programa. A diferencia de las variables, el valor de una constante permanece igual. + +```php +class Car +{ + public const NumberOfWheels = 4; + + public function displayNumberOfWheels(): int + { + echo self::NumberOfWheels; + } +} + +echo Car::NumberOfWheels; // Output: 4 +``` + +En este ejemplo, tenemos una clase `Car` con la constante `NumberOfWheels`. Al acceder a la constante dentro de la clase, podemos utilizar la palabra clave `self` en lugar del nombre de la clase. + + +Interfaces de objetos .[#toc-object-interfaces] +----------------------------------------------- + +Las interfaces de objetos actúan como "contratos" para las clases. Si una clase va a implementar una interfaz de objetos, debe contener todos los métodos que la interfaz define. Es una gran manera de asegurar que ciertas clases se adhieren al mismo "contrato" o estructura. + +En PHP, las interfaces se definen usando la palabra clave `interface`. Todos los métodos definidos en una interfaz son públicos (`public`). Cuando una clase implementa una interfaz, usa la palabra clave `implements`. + +```php +interface Animal +{ + function makeSound(); +} + +class Cat implements Animal +{ + public function makeSound() + { + echo 'Meow'; + } +} + +$cat = new Cat; +$cat->makeSound(); +``` + +Si una clase implementa una interfaz, pero no todos los métodos esperados están definidos, PHP arrojará un error. Una clase puede implementar múltiples interfaces a la vez, que es diferente de la herencia, donde una clase sólo puede heredar de una clase. + + +Clases Abstractas .[#toc-abstract-classes] +------------------------------------------ + +Las clases abstractas sirven como plantillas base para otras clases, pero no se pueden crear instancias directamente. Contienen una mezcla de métodos completos y métodos abstractos que no tienen un contenido definido. Las clases que heredan de clases abstractas deben proporcionar definiciones para todos los métodos abstractos del padre. + +Utilizamos la palabra clave `abstract` para definir una clase abstracta. + +```php +abstract class AbstractClass +{ + public function regularMethod() + { + echo 'This is a regular method'; + } + + abstract public function abstractMethod(); +} + +class Child extends AbstractClass +{ + public function abstractMethod() + { + echo 'This is the implementation of the abstract method'; + } +} + +$instance = new Child; +$instance->regularMethod(); +$instance->abstractMethod(); +``` + +En este ejemplo, tenemos una clase abstracta con un método normal y otro abstracto. Luego tenemos una clase `Child` que hereda de `AbstractClass` y proporciona una implementación para el método abstracto. + + +Comprobación de tipos .[#toc-type-checking] +------------------------------------------- + +En programación, es crucial asegurarse de que los datos con los que trabajamos son del tipo correcto. En PHP, tenemos herramientas que proporcionan esta seguridad. Verificar que los datos son del tipo correcto se llama "comprobación de tipo". + +Tipos que podemos encontrar en PHP: + +1. **Tipos básicos**: Estos incluyen `int` (enteros), `float` (números de punto flotante), `bool` (valores booleanos), `string` (cadenas), `array` (matrices), y `null`. +2. **Clases**: Cuando queremos que un valor sea una instancia de una clase concreta. +3. **Interfaces**: Define un conjunto de métodos que una clase debe implementar. Un valor que cumpla una interfaz debe tener estos métodos. +4. **Tipos mixtos**: Podemos especificar que una variable puede tener múltiples tipos permitidos. +5. **Void**: Este tipo especial indica que una función o método no devuelve ningún valor. + +Veamos cómo modificar el código para incluir tipos: + +```php +class Person +{ + private int $age; + + public function __construct(int $age) + { + $this->age = $age; + } + + public function printAge(): void + { + echo "This person is " . $this->age . " years old."; + } +} + +/** + * A function that accepts a Person object and prints the person's age. + */ +function printPersonAge(Person $person): void +{ + $person->printAge(); +} +``` + +De esta forma, nos aseguramos de que nuestro código espera y trabaja con datos del tipo correcto, ayudándonos a prevenir posibles errores. + + +Comparación e identidad .[#toc-comparison-and-identity] +------------------------------------------------------- + +En PHP, puede comparar objetos de dos maneras: + +1. Comparación de valores `==`: Comprueba si los objetos son de la misma clase y tienen los mismos valores en sus propiedades. +2. Identidad `===`: Comprueba si se trata de la misma instancia del objeto. + +```php +class Car +{ + public string $brand; + + public function __construct(string $brand) + { + $this->brand = $brand; + } +} + +$car1 = new Car('Skoda'); +$car2 = new Car('Skoda'); +$car3 = $car1; + +var_dump($car1 == $car2); // true, because they have the same value +var_dump($car1 === $car2); // false, because they are not the same instance +var_dump($car1 === $car3); // true, because $car3 is the same instance as $car1 +``` + + +El operador `instanceof` .[#toc-the-instanceof-operator] +-------------------------------------------------------- + +El operador `instanceof` permite determinar si un objeto dado es una instancia de una clase específica, un descendiente de esa clase o si implementa una determinada interfaz. + +Imaginemos que tenemos una clase `Person` y otra clase `Student`, que es descendiente de `Person`: + +```php +class Person +{ + private int $age; + + public function __construct(int $age) + { + $this->age = $age; + } +} + +class Student extends Person +{ + private string $major; + + public function __construct(int $age, string $major) + { + parent::__construct($age); + $this->major = $major; + } +} + +$student = new Student(20, 'Computer Science'); + +// Check if $student is an instance of the Student class +var_dump($student instanceof Student); // Output: bool(true) + +// Check if $student is an instance of the Person class (because Student is a descendant of Person) +var_dump($student instanceof Person); // Output: bool(true) +``` + +A partir de las salidas, es evidente que el objeto `$student` se considera una instancia tanto de la clase `Student` como de la clase `Person`. + + +Interfaces fluidas .[#toc-fluent-interfaces] +-------------------------------------------- + +Una "interfaz fluida" es una técnica de programación orientada a objetos que permite encadenar métodos en una sola llamada. Esto a menudo simplifica y clarifica el código. + +El elemento clave de una interfaz fluida es que cada método de la cadena devuelve una referencia al objeto actual. Esto se consigue utilizando `return $this;` al final del método. Este estilo de programación se asocia a menudo con métodos llamados "setters", que establecen los valores de las propiedades de un objeto. + +Veamos cómo sería una interfaz fluida para enviar correos electrónicos: + +```php +public function sendMessage() +{ + $email = new Email; + $email->setFrom('sender@example.com') + ->setRecipient('admin@example.com') + ->setMessage('Hello, this is a message.') + ->send(); +} +``` + +En este ejemplo, los métodos `setFrom()`, `setRecipient()`, y `setMessage()` se utilizan para establecer los valores correspondientes (remitente, destinatario, contenido del mensaje). Después de establecer cada uno de estos valores, los métodos devuelven el objeto actual (`$email`), lo que nos permite encadenar otro método después de él. Finalmente, llamamos al método `send()`, que realmente envía el correo electrónico. + +Gracias a las interfaces fluidas, podemos escribir código intuitivo y fácilmente legible. + + +Copiar con `clone` .[#toc-copying-with-clone] +--------------------------------------------- + +En PHP, podemos crear una copia de un objeto utilizando el operador `clone`. De esta forma, obtenemos una nueva instancia con idéntico contenido. + +Si necesitamos modificar algunas de sus propiedades al copiar un objeto, podemos definir un método especial `__clone()` en la clase. Este método se llama automáticamente cuando se clona el objeto. + +```php +class Sheep +{ + public string $name; + + public function __construct(string $name) + { + $this->name = $name; + } + + public function __clone() + { + $this->name = 'Clone of ' . $this->name; + } +} + +$original = new Sheep('Dolly'); +echo $original->name . "\n"; // Outputs: Dolly + +$clone = clone $original; +echo $clone->name . "\n"; // Outputs: Clone of Dolly +``` + +En este ejemplo, tenemos una clase `Sheep` con una propiedad `$name`. Cuando clonamos una instancia de esta clase, el método `__clone()` se asegura de que el nombre de la oveja clonada obtenga el prefijo "Clone of". + + +Rasgos .[#toc-traits] +--------------------- + +Los traits en PHP son una herramienta que permite compartir métodos, propiedades y constantes entre clases y evita la duplicación de código. Puede pensar en ellos como un mecanismo de "copiar y pegar" (Ctrl-C y Ctrl-V), donde el contenido de un trait se "pega" en las clases. Esto permite reutilizar código sin tener que crear complicadas jerarquías de clases. + +Veamos un ejemplo sencillo de cómo usar traits en PHP: + +```php +trait Honking +{ + public function honk() + { + echo 'Beep beep!'; + } +} + +class Car +{ + use Honking; +} + +class Truck +{ + use Honking; +} + +$car = new Car; +$car->honk(); // Outputs 'Beep beep!' + +$truck = new Truck; +$truck->honk(); // Also outputs 'Beep beep!' +``` + +En este ejemplo, tenemos un trait llamado `Honking` que contiene un método `honk()`. Luego tenemos dos clases: `Car` y `Truck`, las cuales usan el trait `Honking`. Como resultado, ambas clases "tienen" el método `honk()`, y podemos llamarlo en objetos de ambas clases. + +Los traits permiten compartir código entre clases de forma fácil y eficiente. No entran en la jerarquía de herencia, es decir, `$car instanceof Honking` devolverá `false`. + + +Excepciones +----------- + +Las excepciones en POO nos permiten manejar y gestionar los errores que puedan surgir durante la ejecución de nuestro código. Son esencialmente objetos diseñados para registrar errores o situaciones inesperadas en tu programa. + +En PHP, tenemos la clase incorporada `Exception` para estos objetos. Tiene varios métodos que nos permiten obtener más información sobre la excepción, como el mensaje de error, el archivo y la línea donde se produjo el error, etc. + +Cuando surge un problema, podemos "lanzar" una excepción (utilizando `throw`). Si queremos "atrapar" y procesar esta excepción, utilizamos los bloques `try` y `catch`. + +Veamos cómo funciona: + +```php +try { + throw new Exception('Message explaining the reason for the exception'); + + // This code won't execute + echo 'I am a message that nobody will read'; + +} catch (Exception $e) { + echo 'Exception caught: '. $e->getMessage(); +} +``` + +Es importante notar que una excepción puede ser lanzada más profundamente, durante la llamada a otros métodos. + +Para un bloque `try`, se pueden especificar varios bloques `catch` si se esperan diferentes tipos de excepciones. + +También podemos crear una jerarquía de excepciones, donde cada clase de excepción hereda de la anterior. Como ejemplo, considere una simple aplicación bancaria que permite depósitos y retiros: + +```php +class BankingException extends Exception {} +class InsufficientFundsException extends BankingException {} +class ExceededLimitException extends BankingException {} + +class BankAccount +{ + private int $balance = 0; + private int $dailyLimit = 1000; + + public function deposit(int $amount): int + { + $this->balance += $amount; + return $this->balance; + } + + public function withdraw(int $amount): int + { + if ($amount > $this->balance) { + throw new InsufficientFundsException('Not enough funds in the account.'); + } + + if ($amount > $this->dailyLimit) { + throw new ExceededLimitException('Daily withdrawal limit exceeded.'); + } + + $this->balance -= $amount; + return $this->balance; + } +} + +$account = new BankAccount; +$account->deposit(500); + +try { + $account->withdraw(1500); +} catch (ExceededLimitException $e) { + echo $e->getMessage(); +} catch (InsufficientFundsException $e) { + echo $e->getMessage(); +} catch (BankingException $e) { + echo 'An error occurred during the operation.'; +} +``` + +En este ejemplo, es importante tener en cuenta el orden de los bloques `catch`. Dado que todas las excepciones heredan de `BankingException`, si tuviéramos este bloque en primer lugar, todas las excepciones se atraparían en él sin que el código llegara a los bloques `catch` posteriores. Por lo tanto, es importante tener las excepciones más específicas (es decir, aquellas que heredan de otras) más arriba en el orden del bloque `catch` que sus excepciones padre. + + +Buenas prácticas .[#toc-best-practices] +--------------------------------------- + +Una vez que hayas aprendido los principios básicos de la programación orientada a objetos, es crucial centrarse en las mejores prácticas de la programación orientada a objetos. Éstas te ayudarán a escribir código que no sólo sea funcional, sino también legible, comprensible y fácil de mantener. + +1) **Separación de responsabilidades**: Cada clase debe tener una responsabilidad claramente definida y debe abordar sólo una tarea principal. Si una clase hace demasiadas cosas, puede ser conveniente dividirla en clases más pequeñas y especializadas. +2) **Encapsulación**: Los datos y métodos deben estar lo más ocultos posible y ser accesibles únicamente a través de una interfaz definida. Esto permite cambiar la implementación interna de una clase sin afectar al resto del código. +3) **Inyección de dependencias**: En lugar de crear dependencias directamente dentro de una clase, debes "inyectarlas" desde el exterior. Para una comprensión más profunda de este principio, recomendamos los [capítulos sobre In |dependency-injection:introduction]yección de Dependencias. diff --git a/nette/fr/introduction-to-object-oriented-programming.texy b/nette/fr/introduction-to-object-oriented-programming.texy new file mode 100644 index 0000000000..c6fd46ecbb --- /dev/null +++ b/nette/fr/introduction-to-object-oriented-programming.texy @@ -0,0 +1,719 @@ +Introduction à la programmation orientée objet +********************************************** + +.[perex] +Le terme "POO" signifie programmation orientée objet, c'est-à-dire une façon d'organiser et de structurer le code. La POO nous permet de considérer un programme comme une collection d'objets qui communiquent entre eux, plutôt que comme une séquence de commandes et de fonctions. + +Dans la POO, un "objet" est une unité qui contient des données et des fonctions qui opèrent sur ces données. Les objets sont créés sur la base de "classes", qui peuvent être considérées comme des plans ou des modèles d'objets. Une fois que nous disposons d'une classe, nous pouvons créer son "instance", qui est un objet spécifique fabriqué à partir de cette classe. + +Voyons comment créer une classe simple en PHP. Pour définir une classe, on utilise le mot-clé "class", suivi du nom de la classe, puis des accolades qui entourent les fonctions de la classe (appelées "méthodes") et les variables de la classe (appelées "propriétés" ou "attributs") : + +```php +class Car +{ + function honk() + { + echo 'Beep beep!'; + } +} +``` + +Dans cet exemple, nous avons créé une classe nommée `Car` avec une fonction (ou "méthode") appelée `honk`. + +Chaque classe ne doit résoudre qu'une seule tâche principale. Si une classe fait trop de choses, il peut être judicieux de la diviser en classes plus petites et spécialisées. + +Les classes sont généralement stockées dans des fichiers distincts afin que le code reste organisé et facile à parcourir. Le nom du fichier doit correspondre au nom de la classe. Ainsi, pour la classe `Car`, le nom du fichier sera `Car.php`. + +Pour nommer les classes, il est conseillé de suivre la convention "PascalCase", ce qui signifie que chaque mot du nom commence par une majuscule et qu'il n'y a pas de soulignement ou d'autres séparateurs. Les méthodes et les propriétés suivent la convention "camelCase", c'est-à-dire qu'elles commencent par une lettre minuscule. + +Certaines méthodes en PHP ont des rôles spéciaux et sont préfixées par `__` (deux underscores). L'une des méthodes spéciales les plus importantes est le "constructeur", désigné par `__construct`. Le constructeur est une méthode qui est automatiquement appelée lors de la création d'une nouvelle instance d'une classe. + +Nous utilisons souvent le constructeur pour définir l'état initial d'un objet. Par exemple, lors de la création d'un objet représentant une personne, vous pouvez utiliser le constructeur pour définir son âge, son nom ou d'autres attributs. + +Voyons comment utiliser un constructeur en PHP : + +```php +class Person +{ + private $age; + + function __construct($age) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +$person = new Person(25); +echo $person->howOldAreYou(); // Outputs: 25 +``` + +Dans cet exemple, la classe `Person` possède une propriété `$age` et un constructeur qui définit cette propriété. La méthode `howOldAreYou()` permet ensuite d'accéder à l'âge de la personne. + +Le mot-clé `new` est utilisé pour créer une nouvelle instance d'une classe. Dans l'exemple ci-dessus, nous avons créé une nouvelle personne âgée de 25 ans. + +Vous pouvez également définir des valeurs par défaut pour les paramètres du constructeur s'ils ne sont pas spécifiés lors de la création d'un objet. Par exemple : + +```php +class Person +{ + private $age; + + function __construct($age = 20) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +$person = new Person; // if no argument is passed, parentheses can be omitted +echo $person->howOldAreYou(); // Outputs: 20 +``` + +Dans cet exemple, si vous ne spécifiez pas d'âge lors de la création d'un objet `Person`, la valeur par défaut de 20 sera utilisée. + +Enfin, la définition d'une propriété avec son initialisation via le constructeur peut être raccourcie et simplifiée comme suit : + +```php +class Person +{ + function __construct( + private $age = 20, + ) { + } +} +``` + + +Espaces nominatifs .[#toc-namespaces] +------------------------------------- + +Les espaces de nommage nous permettent d'organiser et de regrouper des classes, des fonctions et des constantes apparentées tout en évitant les conflits de noms. Ils sont comparables aux dossiers d'un ordinateur, où chaque dossier contient des fichiers liés à un projet ou à un sujet spécifique. + +Les espaces de noms sont particulièrement utiles dans les grands projets ou lors de l'utilisation de bibliothèques tierces où des conflits de noms de classes peuvent survenir. + +Imaginez que vous ayez une classe nommée `Car` dans votre projet et que vous souhaitiez la placer dans un espace de noms appelé `Transport`. Voici comment procéder : + +```php +namespace Transport; + +class Car +{ + function honk() + { + echo 'Beep beep!'; + } +} +``` + +Si vous souhaitez utiliser la classe `Car` dans un autre fichier, vous devez spécifier l'espace de noms d'où provient la classe : + +```php +$car = new Transport\Car; +``` + +Pour simplifier, vous pouvez indiquer au début du fichier quelle classe d'un espace de noms particulier vous souhaitez utiliser, ce qui vous permet de créer des instances sans mentionner le chemin d'accès complet : + +```php +use Transport\Car; + +$car = new Car; +``` + + +Héritage .[#toc-inheritance] +---------------------------- + +L'héritage est un outil de la programmation orientée objet qui permet de créer de nouvelles classes basées sur des classes existantes, d'hériter de leurs propriétés et de leurs méthodes, et de les étendre ou de les redéfinir si nécessaire. L'héritage garantit la réutilisation du code et la hiérarchie des classes. + +En d'autres termes, si nous disposons d'une classe et que nous souhaitons en créer une autre dérivée, mais avec quelques modifications, nous pouvons "hériter" la nouvelle classe de la classe d'origine. + +En PHP, l'héritage est mis en œuvre à l'aide du mot-clé `extends`. + +Notre classe `Person` stocke des informations sur l'âge. Nous pouvons avoir une autre classe, `Student`, qui étend `Person` et ajoute des informations sur le domaine d'études. + +Prenons un exemple : + +```php +class Person +{ + private $age; + + function __construct($age) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +class Student extends Person +{ + private $fieldOfStudy; + + function __construct($age, $fieldOfStudy) + { + parent::__construct($age); + $this->fieldOfStudy = $fieldOfStudy; + } + + function printInformation() + { + echo 'Age of student: ', $this->howOldAreYou(); + echo 'Field of study: ', $this->fieldOfStudy; + } +} + +$student = new Student(20, 'Computer Science'); +$student->printInformation(); +``` + +Comment fonctionne ce code ? + +- Nous avons utilisé le mot-clé `extends` pour étendre la classe `Person`, ce qui signifie que la classe `Student` hérite de toutes les méthodes et propriétés de `Person`. + +- Le mot-clé `parent::` nous permet d'appeler des méthodes de la classe mère. Dans ce cas, nous avons appelé le constructeur de la classe `Person` avant d'ajouter notre propre fonctionnalité à la classe `Student`. + +L'héritage est destiné aux situations où il existe une relation "est un" entre les classes. Par exemple, un `Student` est un `Person`. Un chat est un animal. Il nous permet, dans les cas où nous attendons un objet (par exemple, "Personne") dans le code, d'utiliser un objet dérivé à la place (par exemple, "Étudiant"). + +Il est essentiel de comprendre que l'objectif premier de l'héritage **n'est pas** d'empêcher la duplication du code. Au contraire, une mauvaise utilisation de l'héritage peut conduire à un code complexe et difficile à maintenir. S'il n'y a pas de relation "is a" entre les classes, nous devrions envisager la composition plutôt que l'héritage. + + +La composition .[#toc-composition] +---------------------------------- + +La composition est une technique par laquelle, au lieu d'hériter des propriétés et des méthodes d'une autre classe, nous utilisons simplement son instance dans notre classe. Cela nous permet de combiner les fonctionnalités et les propriétés de plusieurs classes sans créer de structures d'héritage complexes. + +Par exemple, nous avons une classe `Engine` et une classe `Car`. Au lieu de dire "Une voiture est un moteur", nous disons "Une voiture a un moteur", ce qui est une relation de composition typique. + +```php +class Engine +{ + function start() + { + echo "Engine is running."; + } +} + +class Car +{ + private $engine; + + function __construct() + { + $this->engine = new Engine; + } + + function start() + { + $this->engine->start(); + echo "The car is ready to drive!"; + } +} + +$car = new Car; +$car->start(); +``` + +Ici, la classe `Car` ne possède pas toutes les propriétés et méthodes de la classe `Engine`, mais elle y a accès par l'intermédiaire de la propriété `$engine`. + +L'avantage de la composition est une plus grande souplesse de conception et une meilleure adaptabilité aux changements futurs. + + +Visibilité .[#toc-visibility] +----------------------------- + +En PHP, vous pouvez définir la "visibilité" des propriétés, méthodes et constantes des classes. La visibilité détermine l'endroit où vous pouvez accéder à ces éléments. + +1. **Public:** Si un élément est marqué comme `public`, cela signifie que vous pouvez y accéder de n'importe où, même en dehors de la classe. + +2. **Protégé:** Un élément marqué comme `protected` n'est accessible qu'au sein de la classe et de toutes ses descendantes (classes qui en héritent). + +3. **Privé:** Si un élément est marqué `private`, il n'est accessible qu'à l'intérieur de la classe dans laquelle il a été défini. + +Si vous ne spécifiez pas la visibilité, PHP la définira automatiquement à `public`. + +Voyons un exemple de code : + +```php +class VisibilityExample +{ + public $publicProperty = 'Public'; + protected $protectedProperty = 'Protected'; + private $privateProperty = 'Private'; + + public function printProperties() + { + echo $this->publicProperty; // Works + echo $this->protectedProperty; // Works + echo $this->privateProperty; // Works + } +} + +$object = new VisibilityExample; +$object->printProperties(); +echo $object->publicProperty; // Works +// echo $object->protectedProperty; // Throws an error +// echo $object->privateProperty; // Throws an error +``` + +Poursuite de l'héritage des classes : + +```php +class ChildClass extends VisibilityExample +{ + public function printProperties() + { + echo $this->publicProperty; // Works + echo $this->protectedProperty; // Works + // echo $this->privateProperty; // Throws an error + } +} +``` + +Dans ce cas, la méthode `printProperties()` de la classe `ChildClass` peut accéder aux propriétés publiques et protégées, mais ne peut pas accéder aux propriétés privées de la classe mère. + +Les données et les méthodes doivent être aussi cachées que possible et accessibles uniquement par l'intermédiaire d'une interface définie. Cela permet de modifier l'implémentation interne de la classe sans affecter le reste du code. + + +Mot-clé final .[#toc-final-keyword] +----------------------------------- + +En PHP, nous pouvons utiliser le mot-clé `final` si nous voulons empêcher une classe, une méthode ou une constante d'être héritée ou surchargée. Lorsqu'une classe est marquée comme `final`, elle ne peut pas être étendue. Lorsqu'une méthode est marquée comme `final`, elle ne peut pas être remplacée dans une sous-classe. + +Le fait de savoir qu'une certaine classe ou méthode ne sera plus modifiée nous permet d'apporter des changements plus facilement sans nous soucier des conflits potentiels. Par exemple, nous pouvons ajouter une nouvelle méthode sans craindre qu'un descendant ait déjà une méthode portant le même nom, ce qui entraînerait une collision. Nous pouvons également modifier les paramètres d'une méthode, toujours sans risquer de provoquer une incohérence avec une méthode surchargée dans un descendant. + +```php +final class FinalClass +{ +} + +// The following code will throw an error because we cannot inherit from a final class. +class ChildOfFinalClass extends FinalClass +{ +} +``` + +Dans cet exemple, tenter d'hériter de la classe finale `FinalClass` entraînera une erreur. + + +Propriétés et méthodes statiques .[#toc-static-properties-and-methods] +---------------------------------------------------------------------- + +Lorsque nous parlons d'éléments "statiques" d'une classe en PHP, nous parlons de méthodes et de propriétés qui appartiennent à la classe elle-même, et non à une instance spécifique de la classe. Cela signifie que vous n'avez pas besoin de créer une instance de la classe pour y accéder. Au lieu de cela, vous les appelez ou y accédez directement par l'intermédiaire du nom de la classe. + +N'oubliez pas qu'étant donné que les éléments statiques appartiennent à la classe et non à ses instances, vous ne pouvez pas utiliser la pseudo-variable `$this` à l'intérieur des méthodes statiques. + +L'utilisation de propriétés statiques conduit à un [code obscurci et plein d'embûches |dependency-injection:global-state], vous ne devriez donc jamais les utiliser, et nous ne montrerons pas d'exemple ici. En revanche, les méthodes statiques sont utiles. En voici un exemple : + +```php +class Calculator +{ + public static function add($a, $b) + { + return $a + $b; + } + + public static function subtract($a, $b) + { + return $a - $b; + } +} + +// Using the static method without creating an instance of the class +echo Calculator::add(5, 3); // Output: 8 +echo Calculator::subtract(5, 3); // Output: 2 +``` + +Dans cet exemple, nous avons créé une classe `Calculator` avec deux méthodes statiques. Nous pouvons appeler ces méthodes directement sans créer une instance de la classe à l'aide de l'opérateur `::`. Les méthodes statiques sont particulièrement utiles pour les opérations qui ne dépendent pas de l'état d'une instance de classe spécifique. + + +Constantes de classe .[#toc-class-constants] +-------------------------------------------- + +Au sein des classes, nous avons la possibilité de définir des constantes. Les constantes sont des valeurs qui ne changent jamais pendant l'exécution du programme. Contrairement aux variables, la valeur d'une constante reste inchangée. + +```php +class Car +{ + public const NumberOfWheels = 4; + + public function displayNumberOfWheels(): int + { + echo self::NumberOfWheels; + } +} + +echo Car::NumberOfWheels; // Output: 4 +``` + +Dans cet exemple, nous avons une classe `Car` avec la constante `NumberOfWheels`. Lorsque nous accédons à la constante à l'intérieur de la classe, nous pouvons utiliser le mot-clé `self` au lieu du nom de la classe. + + +Interfaces d'objets .[#toc-object-interfaces] +--------------------------------------------- + +Les interfaces d'objets agissent comme des "contrats" pour les classes. Si une classe doit implémenter une interface objet, elle doit contenir toutes les méthodes définies par l'interface. C'est un excellent moyen de s'assurer que certaines classes adhèrent au même "contrat" ou à la même structure. + +En PHP, les interfaces sont définies à l'aide du mot-clé `interface`. Toutes les méthodes définies dans une interface sont publiques (`public`). Lorsqu'une classe implémente une interface, elle utilise le mot-clé `implements`. + +```php +interface Animal +{ + function makeSound(); +} + +class Cat implements Animal +{ + public function makeSound() + { + echo 'Meow'; + } +} + +$cat = new Cat; +$cat->makeSound(); +``` + +Si une classe implémente une interface, mais que toutes les méthodes attendues ne sont pas définies, PHP lèvera une erreur. Une classe peut implémenter plusieurs interfaces à la fois, ce qui est différent de l'héritage, où une classe ne peut hériter que d'une seule classe. + + +Classes abstraites .[#toc-abstract-classes] +------------------------------------------- + +Les classes abstraites servent de modèles de base pour d'autres classes, mais vous ne pouvez pas créer leurs instances directement. Elles contiennent un mélange de méthodes complètes et de méthodes abstraites dont le contenu n'est pas défini. Les classes qui héritent de classes abstraites doivent fournir des définitions pour toutes les méthodes abstraites du parent. + +Nous utilisons le mot-clé `abstract` pour définir une classe abstraite. + +```php +abstract class AbstractClass +{ + public function regularMethod() + { + echo 'This is a regular method'; + } + + abstract public function abstractMethod(); +} + +class Child extends AbstractClass +{ + public function abstractMethod() + { + echo 'This is the implementation of the abstract method'; + } +} + +$instance = new Child; +$instance->regularMethod(); +$instance->abstractMethod(); +``` + +Dans cet exemple, nous avons une classe abstraite avec une méthode ordinaire et une méthode abstraite. Nous avons ensuite une classe `Child` qui hérite de `AbstractClass` et fournit une implémentation pour la méthode abstraite. + + +Vérification du type .[#toc-type-checking] +------------------------------------------ + +En programmation, il est crucial de s'assurer que les données avec lesquelles nous travaillons sont du bon type. En PHP, nous avons des outils qui fournissent cette assurance. Vérifier que les données sont du bon type est appelé "vérification de type". + +Les types que nous pouvons rencontrer en PHP : + +1. **Types de base** : Ils comprennent `int` (entiers), `float` (nombres à virgule flottante), `bool` (valeurs booléennes), `string` (chaînes de caractères), `array` (tableaux) et `null`. +2. **Classes** : Lorsque nous voulons qu'une valeur soit une instance d'une classe spécifique. +3. **Interfaces** : Définit un ensemble de méthodes qu'une classe doit implémenter. Une valeur qui répond à une interface doit posséder ces méthodes. +4. **Types mixtes** : Nous pouvons spécifier qu'une variable peut avoir plusieurs types autorisés. +5. **Void** : Ce type spécial indique qu'une fonction ou une méthode ne renvoie aucune valeur. + +Voyons comment modifier le code pour inclure les types : + +```php +class Person +{ + private int $age; + + public function __construct(int $age) + { + $this->age = $age; + } + + public function printAge(): void + { + echo "This person is " . $this->age . " years old."; + } +} + +/** + * A function that accepts a Person object and prints the person's age. + */ +function printPersonAge(Person $person): void +{ + $person->printAge(); +} +``` + +De cette manière, nous nous assurons que notre code s'attend à ce que les données soient du bon type et qu'il fonctionne avec elles, ce qui nous permet d'éviter les erreurs potentielles. + + +Comparaison et identité .[#toc-comparison-and-identity] +------------------------------------------------------- + +En PHP, vous pouvez comparer des objets de deux manières : + +1. Comparaison de valeurs `==`: Vérifie si les objets sont de la même classe et ont les mêmes valeurs dans leurs propriétés. +2. Comparaison d'identité `===`: vérifie s'il s'agit de la même instance de l'objet. + +```php +class Car +{ + public string $brand; + + public function __construct(string $brand) + { + $this->brand = $brand; + } +} + +$car1 = new Car('Skoda'); +$car2 = new Car('Skoda'); +$car3 = $car1; + +var_dump($car1 == $car2); // true, because they have the same value +var_dump($car1 === $car2); // false, because they are not the same instance +var_dump($car1 === $car3); // true, because $car3 is the same instance as $car1 +``` + + +L'opérateur `instanceof` .[#toc-the-instanceof-operator] +-------------------------------------------------------- + +L'opérateur `instanceof` permet de déterminer si un objet donné est une instance d'une classe spécifique, un descendant de cette classe ou s'il implémente une certaine interface. + +Imaginons que nous ayons une classe `Person` et une autre classe `Student`, qui est un descendant de `Person`: + +```php +class Person +{ + private int $age; + + public function __construct(int $age) + { + $this->age = $age; + } +} + +class Student extends Person +{ + private string $major; + + public function __construct(int $age, string $major) + { + parent::__construct($age); + $this->major = $major; + } +} + +$student = new Student(20, 'Computer Science'); + +// Check if $student is an instance of the Student class +var_dump($student instanceof Student); // Output: bool(true) + +// Check if $student is an instance of the Person class (because Student is a descendant of Person) +var_dump($student instanceof Person); // Output: bool(true) +``` + +D'après les résultats, il est évident que l'objet `$student` est considéré comme une instance des classes `Student` et `Person`. + + +Interfaces fluides .[#toc-fluent-interfaces] +-------------------------------------------- + +Une "interface fluide" est une technique de la POO qui permet d'enchaîner des méthodes en un seul appel. Cela permet souvent de simplifier et de clarifier le code. + +L'élément clé d'une interface fluide est que chaque méthode de la chaîne renvoie une référence à l'objet actuel. Pour ce faire, on utilise `return $this;` à la fin de la méthode. Ce style de programmation est souvent associé à des méthodes appelées "setters", qui fixent les valeurs des propriétés d'un objet. + +Voyons à quoi pourrait ressembler une interface fluide pour l'envoi de courriers électroniques : + +```php +public function sendMessage() +{ + $email = new Email; + $email->setFrom('sender@example.com') + ->setRecipient('admin@example.com') + ->setMessage('Hello, this is a message.') + ->send(); +} +``` + +Dans cet exemple, les méthodes `setFrom()`, `setRecipient()`, et `setMessage()` sont utilisées pour définir les valeurs correspondantes (expéditeur, destinataire, contenu du message). Après avoir défini chacune de ces valeurs, les méthodes renvoient l'objet courant (`$email`), ce qui nous permet d'enchaîner une autre méthode après celle-ci. Enfin, nous appelons la méthode `send()`, qui envoie effectivement le courrier électronique. + +Grâce aux interfaces fluides, nous pouvons écrire un code intuitif et facilement lisible. + + +Copier avec `clone` .[#toc-copying-with-clone] +---------------------------------------------- + +En PHP, nous pouvons créer une copie d'un objet en utilisant l'opérateur `clone`. De cette manière, nous obtenons une nouvelle instance avec un contenu identique. + +Si nous devons modifier certaines propriétés lors de la copie d'un objet, nous pouvons définir une méthode spéciale `__clone()` dans la classe. Cette méthode est automatiquement appelée lorsque l'objet est cloné. + +```php +class Sheep +{ + public string $name; + + public function __construct(string $name) + { + $this->name = $name; + } + + public function __clone() + { + $this->name = 'Clone of ' . $this->name; + } +} + +$original = new Sheep('Dolly'); +echo $original->name . "\n"; // Outputs: Dolly + +$clone = clone $original; +echo $clone->name . "\n"; // Outputs: Clone of Dolly +``` + +Dans cet exemple, nous avons une classe `Sheep` avec une propriété `$name`. Lorsque nous clonons une instance de cette classe, la méthode `__clone()` veille à ce que le nom du mouton cloné reçoive le préfixe "Clone de". + + +Traits .[#toc-traits] +--------------------- + +Les traits en PHP sont un outil qui permet de partager des méthodes, des propriétés et des constantes entre les classes et d'éviter la duplication du code. Vous pouvez les considérer comme un mécanisme de "copier-coller" (Ctrl-C et Ctrl-V), où le contenu d'un trait est "collé" dans les classes. Cela vous permet de réutiliser le code sans avoir à créer des hiérarchies de classes compliquées. + +Voyons un exemple simple d'utilisation des traits en PHP : + +```php +trait Honking +{ + public function honk() + { + echo 'Beep beep!'; + } +} + +class Car +{ + use Honking; +} + +class Truck +{ + use Honking; +} + +$car = new Car; +$car->honk(); // Outputs 'Beep beep!' + +$truck = new Truck; +$truck->honk(); // Also outputs 'Beep beep!' +``` + +Dans cet exemple, nous avons un trait nommé `Honking` qui contient une méthode `honk()`. Nous avons ensuite deux classes : `Car` et `Truck`, qui utilisent toutes deux le trait `Honking`. Par conséquent, les deux classes "possèdent" la méthode `honk()` et nous pouvons l'appeler sur des objets des deux classes. + +Les traits vous permettent de partager facilement et efficacement le code entre les classes. Ils n'entrent pas dans la hiérarchie de l'héritage, c'est-à-dire que `$car instanceof Honking` renverra `false`. + + +Exceptions +---------- + +Les exceptions en POO nous permettent de traiter et de gérer les erreurs qui peuvent survenir au cours de l'exécution de notre code. Il s'agit essentiellement d'objets conçus pour enregistrer les erreurs ou les situations inattendues dans votre programme. + +En PHP, nous disposons de la classe intégrée `Exception` pour ces objets. Elle possède plusieurs méthodes qui nous permettent d'obtenir plus d'informations sur l'exception, comme le message d'erreur, le fichier et la ligne où l'erreur s'est produite, etc. + +Lorsqu'un problème survient, nous pouvons "lancer" une exception (en utilisant `throw`). Si nous voulons "attraper" et traiter cette exception, nous utilisons les blocs `try` et `catch`. + +Voyons comment cela fonctionne : + +```php +try { + throw new Exception('Message explaining the reason for the exception'); + + // This code won't execute + echo 'I am a message that nobody will read'; + +} catch (Exception $e) { + echo 'Exception caught: '. $e->getMessage(); +} +``` + +Il est important de noter qu'une exception peut être levée plus profondément, lors de l'appel à d'autres méthodes. + +Pour un bloc `try`, plusieurs blocs `catch` peuvent être spécifiés si vous vous attendez à différents types d'exceptions. + +Nous pouvons également créer une hiérarchie d'exceptions, où chaque classe d'exception hérite de la précédente. Prenons l'exemple d'une application bancaire simple qui autorise les dépôts et les retraits : + +```php +class BankingException extends Exception {} +class InsufficientFundsException extends BankingException {} +class ExceededLimitException extends BankingException {} + +class BankAccount +{ + private int $balance = 0; + private int $dailyLimit = 1000; + + public function deposit(int $amount): int + { + $this->balance += $amount; + return $this->balance; + } + + public function withdraw(int $amount): int + { + if ($amount > $this->balance) { + throw new InsufficientFundsException('Not enough funds in the account.'); + } + + if ($amount > $this->dailyLimit) { + throw new ExceededLimitException('Daily withdrawal limit exceeded.'); + } + + $this->balance -= $amount; + return $this->balance; + } +} + +$account = new BankAccount; +$account->deposit(500); + +try { + $account->withdraw(1500); +} catch (ExceededLimitException $e) { + echo $e->getMessage(); +} catch (InsufficientFundsException $e) { + echo $e->getMessage(); +} catch (BankingException $e) { + echo 'An error occurred during the operation.'; +} +``` + +Dans cet exemple, il est important de noter l'ordre des blocs `catch`. Étant donné que toutes les exceptions héritent de `BankingException`, si nous avions ce bloc en premier, toutes les exceptions seraient capturées dans ce bloc sans que le code n'atteigne les blocs `catch` suivants. Par conséquent, il est important que les exceptions plus spécifiques (c'est-à-dire celles qui héritent d'autres exceptions) soient placées plus haut dans l'ordre du bloc `catch` que leurs exceptions parentales. + + +Meilleures pratiques .[#toc-best-practices] +------------------------------------------- + +Une fois que vous avez assimilé les principes de base de la programmation orientée objet, il est essentiel de vous concentrer sur les meilleures pratiques de la POO. Celles-ci vous aideront à écrire un code non seulement fonctionnel, mais aussi lisible, compréhensible et facile à maintenir. + +1) **Séparation des préoccupations** : Chaque classe doit avoir une responsabilité clairement définie et ne doit s'occuper que d'une seule tâche principale. Si une classe fait trop de choses, il peut être judicieux de la diviser en classes spécialisées plus petites. +2) **Encapsulation** : Les données et les méthodes doivent être aussi cachées que possible et accessibles uniquement par l'intermédiaire d'une interface définie. Cela permet de modifier l'implémentation interne d'une classe sans affecter le reste du code. +3) **Injection de dépendances** : Au lieu de créer des dépendances directement dans une classe, vous devriez les "injecter" depuis l'extérieur. Pour une compréhension plus approfondie de ce principe, nous recommandons les [chapitres sur l'injection de dépendances |dependency-injection:introduction]. diff --git a/nette/hu/introduction-to-object-oriented-programming.texy b/nette/hu/introduction-to-object-oriented-programming.texy new file mode 100644 index 0000000000..c1c8b23bba --- /dev/null +++ b/nette/hu/introduction-to-object-oriented-programming.texy @@ -0,0 +1,719 @@ +Bevezetés az objektumorientált programozásba +******************************************** + +.[perex] +Az "OOP" kifejezés az objektumorientált programozás rövidítése, amely a kód szervezésének és strukturálásának egy módja. Az OOP lehetővé teszi, hogy a programot egymással kommunikáló objektumok gyűjteményének tekintsük, nem pedig parancsok és függvények sorozatának. + +Az OOP-ban az "objektum" olyan egység, amely adatokat és az adatokkal operáló függvényeket tartalmaz. Az objektumok létrehozása "osztályok" alapján történik, amelyek az objektumok tervrajzaként vagy sablonjaként értelmezhetők. Ha már van egy osztályunk, létrehozhatjuk annak "példányát", amely egy konkrét, az osztályból készült objektum. + +Nézzük meg, hogyan hozhatunk létre egy egyszerű osztályt PHP-ben. Egy osztály definiálásakor az "class" kulcsszót használjuk, amelyet az osztály neve követ, majd a szögletes zárójelek az osztály függvényeit (az úgynevezett "metódusokat") és az osztály változóit (az úgynevezett "tulajdonságokat" vagy "attribútumokat") zárják körül: + +```php +class Car +{ + function honk() + { + echo 'Beep beep!'; + } +} +``` + +Ebben a példában egy `Car` nevű osztályt hoztunk létre egy `honk` nevű függvénnyel (vagy "módszerrel"). + +Minden osztály csak egy fő feladatot oldhat meg. Ha egy osztály túl sok mindent csinál, akkor célszerű lehet kisebb, speciális osztályokra osztani. + +Az osztályokat általában külön fájlokban tároljuk, hogy a kódot rendszerezve tartsuk és könnyen áttekinthetővé tegyük. A fájlnévnek meg kell egyeznie az osztály nevével, így a `Car` osztály esetében a fájl neve `Car.php` lenne. + +Az osztályok elnevezésénél célszerű a "PascalCase" konvenciót követni, ami azt jelenti, hogy a névben minden szó nagybetűvel kezdődik, és nincsenek aláhúzások vagy egyéb elválasztójelek. A metódusok és tulajdonságok a "camelCase" konvenciót követik, azaz kisbetűvel kezdődnek. + +A PHP egyes metódusai speciális szerepkörrel rendelkeznek, és a `__` (két aláhúzás) előtaggal vannak ellátva. Az egyik legfontosabb speciális metódus a "konstruktor", amelyet a `__construct` jelöléssel látunk el. A konstruktor egy olyan metódus, amely automatikusan meghívásra kerül, amikor egy osztály új példányát létrehozzuk. + +A konstruktort gyakran használjuk egy objektum kezdeti állapotának beállítására. Például egy személyt reprezentáló objektum létrehozásakor a konstruktort használhatjuk a kor, a név vagy más attribútumok beállítására. + +Lássuk, hogyan használhatunk konstruktort a PHP-ban: + +```php +class Person +{ + private $age; + + function __construct($age) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +$person = new Person(25); +echo $person->howOldAreYou(); // Outputs: 25 +``` + +Ebben a példában a `Person` osztály rendelkezik egy `$age` tulajdonsággal és egy konstruktorral, amely beállítja ezt a tulajdonságot. A `howOldAreYou()` metódus ezután hozzáférést biztosít a személy életkorához. + +A `new` kulcsszó egy osztály új példányának létrehozására szolgál. A fenti példában egy új, 25 éves személyt hoztunk létre. + +A konstruktor paramétereihez alapértelmezett értékeket is megadhatunk, ha azok nincsenek megadva egy objektum létrehozásakor. Például: + +```php +class Person +{ + private $age; + + function __construct($age = 20) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +$person = new Person; // if no argument is passed, parentheses can be omitted +echo $person->howOldAreYou(); // Outputs: 20 +``` + +Ebben a példában, ha a `Person` objektum létrehozásakor nem ad meg életkort, az alapértelmezett 20-as értéket fogja használni. + +Végül a tulajdonság definíciója a konstruktoron keresztül történő inicializálással a következőképpen rövidíthető és egyszerűsíthető: + +```php +class Person +{ + function __construct( + private $age = 20, + ) { + } +} +``` + + +Névterek .[#toc-namespaces] +--------------------------- + +A névterek lehetővé teszik, hogy az egymással összefüggő osztályokat, függvényeket és konstansokat rendszerezzük és csoportosítsuk, miközben elkerüljük a névkonfliktusokat. Úgy gondolhat rájuk, mint a számítógép mappáira, ahol minden mappa egy adott projekthez vagy témához kapcsolódó fájlokat tartalmaz. + +A névterek különösen hasznosak nagyobb projekteknél vagy harmadik féltől származó könyvtárak használatakor, ahol osztályok elnevezési konfliktusok merülhetnek fel. + +Képzelje el, hogy van egy `Car` nevű osztálya a projektjében, és a `Transport` nevű névtérben szeretné elhelyezni. Ezt a következőképpen tenné: + +```php +namespace Transport; + +class Car +{ + function honk() + { + echo 'Beep beep!'; + } +} +``` + +Ha a `Car` osztályt egy másik fájlban szeretné használni, akkor meg kell adnia, hogy az osztály melyik névtérből származik: + +```php +$car = new Transport\Car; +``` + +Az egyszerűsítés érdekében a fájl elején megadhatja, hogy melyik osztályt szeretné használni egy adott névtérből, így a teljes elérési út megadása nélkül hozhat létre példányokat: + +```php +use Transport\Car; + +$car = new Car; +``` + + +Öröklés .[#toc-inheritance] +--------------------------- + +Az öröklés az objektumorientált programozás egyik eszköze, amely lehetővé teszi új osztályok létrehozását a már létező osztályok alapján, örökölve azok tulajdonságait és metódusait, és szükség szerint kibővítve vagy átdefiniálva azokat. Az öröklés biztosítja a kód újrafelhasználhatóságát és az osztályhierarchiát. + +Egyszerűen fogalmazva, ha van egy osztályunk, és szeretnénk létrehozni egy másik, abból származtatott, de némi módosítással rendelkező osztályt, akkor az új osztályt "örökölhetjük" az eredetiből. + +A PHP-ben az öröklés a `extends` kulcsszóval valósul meg. + +A mi `Person` osztályunk az életkori információkat tárolja. Létrehozhatunk egy másik osztályt, a `Student`, amely a `Person` kiterjesztése, és hozzáadhatja a tanulmányi területre vonatkozó információkat. + +Nézzünk egy példát: + +```php +class Person +{ + private $age; + + function __construct($age) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +class Student extends Person +{ + private $fieldOfStudy; + + function __construct($age, $fieldOfStudy) + { + parent::__construct($age); + $this->fieldOfStudy = $fieldOfStudy; + } + + function printInformation() + { + echo 'Age of student: ', $this->howOldAreYou(); + echo 'Field of study: ', $this->fieldOfStudy; + } +} + +$student = new Student(20, 'Computer Science'); +$student->printInformation(); +``` + +Hogyan működik ez a kód? + +- A `extends` kulcsszóval bővítettük a `Person` osztályt, ami azt jelenti, hogy a `Student` osztály minden metódust és tulajdonságot a `Person` osztályból örököl. + +- A `parent::` kulcsszó lehetővé teszi számunkra, hogy a szülő osztály metódusait hívjuk. Ebben az esetben a `Person` osztály konstruktorát hívtuk meg, mielőtt a `Student` osztályhoz hozzáadtuk volna a saját funkcióinkat. + +Az öröklés olyan helyzetekre való, amikor az osztályok között "is a" kapcsolat van. Például egy `Student` egy `Person`. A macska egy állat. Lehetővé teszi számunkra, hogy olyan esetekben, amikor egy objektumot (pl. "Person") várunk a kódban, egy származtatott objektumot használjunk helyette (pl. "Student"). + +Lényeges felismerni, hogy az öröklés elsődleges célja **nem** a kódduplikáció megakadályozása. Éppen ellenkezőleg, az öröklés helytelen használata összetett és nehezen karbantartható kódhoz vezethet. Ha nincs "is a" kapcsolat az osztályok között, akkor az öröklés helyett a kompozíciót kell fontolóra vennünk. + + +Kompozíció .[#toc-composition] +------------------------------ + +A kompozíció egy olyan technika, ahol ahelyett, hogy egy másik osztály tulajdonságait és metódusait örökölnénk, egyszerűen csak használjuk annak példányát a saját osztályunkban. Ez lehetővé teszi, hogy több osztály funkcionalitását és tulajdonságait kombináljuk anélkül, hogy bonyolult öröklési struktúrákat hoznánk létre. + +Például van egy `Engine` és egy `Car` osztályunk. Ahelyett, hogy azt mondanánk, hogy "Egy autó egy motor", azt mondjuk, hogy "Egy autónak van egy motorja", ami egy tipikus kompozíciós kapcsolat. + +```php +class Engine +{ + function start() + { + echo "Engine is running."; + } +} + +class Car +{ + private $engine; + + function __construct() + { + $this->engine = new Engine; + } + + function start() + { + $this->engine->start(); + echo "The car is ready to drive!"; + } +} + +$car = new Car; +$car->start(); +``` + +Itt a `Car` nem rendelkezik a `Engine` osztály összes tulajdonságával és metódusával, de a `$engine` tulajdonságon keresztül hozzáférhet azokhoz. + +A kompozíció előnye a nagyobb tervezési rugalmasság és a jobb alkalmazkodóképesség a jövőbeli változásokhoz. + + +Láthatóság .[#toc-visibility] +----------------------------- + +A PHP-ben az osztályok tulajdonságai, metódusai és konstansai számára meghatározható a "láthatóság". A láthatóság határozza meg, hogy hol lehet hozzáférni ezekhez az elemekhez. + +1. **Public:** Ha egy elemet `public`-ként jelölünk, az azt jelenti, hogy bárhonnan, akár az osztályon kívülről is elérhetjük. + +2. **Védett:** Egy `protected` jelű elem csak az osztályon belül és annak összes leszármazottján (az osztályból öröklődő osztályok) belül érhető el. + +3. **Privát:** Ha egy elem `private`, akkor csak azon az osztályon belül érhető el, ahol definiálták. + +Ha nem adja meg a láthatóságot, a PHP automatikusan `public` értékre állítja. + +Nézzünk meg egy példakódot: + +```php +class VisibilityExample +{ + public $publicProperty = 'Public'; + protected $protectedProperty = 'Protected'; + private $privateProperty = 'Private'; + + public function printProperties() + { + echo $this->publicProperty; // Works + echo $this->protectedProperty; // Works + echo $this->privateProperty; // Works + } +} + +$object = new VisibilityExample; +$object->printProperties(); +echo $object->publicProperty; // Works +// echo $object->protectedProperty; // Throws an error +// echo $object->privateProperty; // Throws an error +``` + +Folytatva az osztályöröklést: + +```php +class ChildClass extends VisibilityExample +{ + public function printProperties() + { + echo $this->publicProperty; // Works + echo $this->protectedProperty; // Works + // echo $this->privateProperty; // Throws an error + } +} +``` + +Ebben az esetben a `printProperties()` metódus a `ChildClass` osztályban hozzáférhet a nyilvános és védett tulajdonságokhoz, de nem férhet hozzá a szülőosztály privát tulajdonságaihoz. + +Az adatoknak és a metódusoknak a lehető legrejtettebbnek kell lenniük, és csak egy meghatározott interfészen keresztül lehet őket elérni. Ez lehetővé teszi, hogy az osztály belső implementációját megváltoztassa anélkül, hogy a kód többi részét befolyásolná. + + +Végleges kulcsszó .[#toc-final-keyword] +--------------------------------------- + +A PHP-ben a `final` kulcsszót használhatjuk, ha meg akarjuk akadályozni, hogy egy osztály, metódus vagy konstans öröklődjön vagy felülíródjon. Ha egy osztályt `final` jelöli, akkor nem bővíthető. Ha egy metódus `final`-ként van megjelölve, akkor nem lehet felülírni egy alosztályban. + +Ha tudatában vagyunk annak, hogy egy bizonyos osztály vagy metódus nem lesz többé módosítható, könnyebben tudunk változtatásokat végrehajtani anélkül, hogy aggódnánk a lehetséges konfliktusok miatt. Például hozzáadhatunk egy új metódust anélkül, hogy attól kellene tartanunk, hogy egy leszármazottnak már van egy ugyanilyen nevű metódusa, ami ütközéshez vezethet. Vagy megváltoztathatjuk egy metódus paramétereit, szintén anélkül, hogy azt kockáztatnánk, hogy következetlenséget okozunk egy leszármazottban lévő felülhajtott metódussal. + +```php +final class FinalClass +{ +} + +// The following code will throw an error because we cannot inherit from a final class. +class ChildOfFinalClass extends FinalClass +{ +} +``` + +Ebben a példában a `FinalClass` végleges osztályból való öröklés megkísérlése hibát eredményez. + + +Statikus tulajdonságok és metódusok .[#toc-static-properties-and-methods] +------------------------------------------------------------------------- + +Amikor egy osztály "statikus" elemeiről beszélünk a PHP-ben, akkor olyan metódusokra és tulajdonságokra gondolunk, amelyek magához az osztályhoz tartoznak, nem pedig az osztály egy adott példányához. Ez azt jelenti, hogy nem kell létrehozni az osztály egy példányát ahhoz, hogy hozzáférjünk hozzájuk. Ehelyett közvetlenül az osztály nevén keresztül hívja meg vagy éri el őket. + +Ne feledje, hogy mivel a statikus elemek az osztályhoz tartoznak, nem pedig annak példányaihoz, nem használhatja a `$this` pszeudováltozót statikus metódusokon belül. + +A statikus tulajdonságok használata [buktatókkal teli homályos kódhoz |dependency-injection:global-state] vezet, ezért soha ne használd őket, és itt nem is mutatunk példát. A statikus metódusok viszont hasznosak. Íme egy példa: + +```php +class Calculator +{ + public static function add($a, $b) + { + return $a + $b; + } + + public static function subtract($a, $b) + { + return $a - $b; + } +} + +// Using the static method without creating an instance of the class +echo Calculator::add(5, 3); // Output: 8 +echo Calculator::subtract(5, 3); // Output: 2 +``` + +Ebben a példában létrehoztunk egy `Calculator` osztályt két statikus metódussal. Ezeket a metódusokat közvetlenül meg tudjuk hívni anélkül, hogy az osztály példányát létrehoznánk a `::` operátor segítségével. A statikus metódusok különösen hasznosak olyan műveleteknél, amelyek nem függnek egy adott osztálypéldány állapotától. + + +Osztálykonstansok .[#toc-class-constants] +----------------------------------------- + +Az osztályokon belül lehetőségünk van konstansok definiálására. A konstansok olyan értékek, amelyek a program végrehajtása során soha nem változnak. A változókkal ellentétben a konstansok értéke változatlan marad. + +```php +class Car +{ + public const NumberOfWheels = 4; + + public function displayNumberOfWheels(): int + { + echo self::NumberOfWheels; + } +} + +echo Car::NumberOfWheels; // Output: 4 +``` + +Ebben a példában van egy `Car` osztályunk a `NumberOfWheels` konstanssal. Az osztályon belüli konstans elérésekor az osztály neve helyett a `self` kulcsszót használhatjuk. + + +Objektum interfészek .[#toc-object-interfaces] +---------------------------------------------- + +Az objektum interfészek az osztályok "szerződéseiként" működnek. Ha egy osztálynak egy objektum interfészt kell implementálnia, akkor tartalmaznia kell az összes metódust, amelyet az interfész definiál. Ez egy nagyszerű módja annak, hogy bizonyos osztályok azonos "szerződést" vagy struktúrát tartsanak be. + +A PHP-ben az interfészeket a `interface` kulcsszóval definiáljuk. Az interfészben definiált összes metódus nyilvános (`public`). Amikor egy osztály megvalósít egy interfészt, akkor a `implements` kulcsszót használja. + +```php +interface Animal +{ + function makeSound(); +} + +class Cat implements Animal +{ + public function makeSound() + { + echo 'Meow'; + } +} + +$cat = new Cat; +$cat->makeSound(); +``` + +Ha egy osztály megvalósít egy interfészt, de nem minden elvárt metódus van definiálva, a PHP hibát fog dobni. Egy osztály egyszerre több interfészt is megvalósíthat, ami eltér az örökléstől, ahol egy osztály csak egy osztálytól örökölhet. + + +Absztrakt osztályok .[#toc-abstract-classes] +-------------------------------------------- + +Az absztrakt osztályok más osztályok alapsablonjaiként szolgálnak, de közvetlenül nem hozhatók létre példányaik. Teljes metódusok és olyan absztrakt metódusok keverékét tartalmazzák, amelyeknek nincs meghatározott tartalma. Az absztrakt osztályokból öröklődő osztályoknak meg kell adniuk a szülőktől származó összes absztrakt metódus definícióját. + +Az absztrakt osztályok definiálására a `abstract` kulcsszót használjuk. + +```php +abstract class AbstractClass +{ + public function regularMethod() + { + echo 'This is a regular method'; + } + + abstract public function abstractMethod(); +} + +class Child extends AbstractClass +{ + public function abstractMethod() + { + echo 'This is the implementation of the abstract method'; + } +} + +$instance = new Child; +$instance->regularMethod(); +$instance->abstractMethod(); +``` + +Ebben a példában egy absztrakt osztályunk van egy reguláris és egy absztrakt metódussal. Ezután van egy `Child` osztályunk, amely a `AbstractClass` osztályból örököl, és implementációt biztosít az absztrakt metódushoz. + + +Típusellenőrzés .[#toc-type-checking] +------------------------------------- + +A programozásban alapvető fontosságú annak biztosítása, hogy az adatok, amelyekkel dolgozunk, megfelelő típusúak legyenek. A PHP-ben vannak olyan eszközeink, amelyek ezt a biztosítékot nyújtják. Az adatok megfelelő típusának ellenőrzését "típusellenőrzésnek" nevezzük. + +Típusok, amelyekkel a PHP-ben találkozhatunk: + +1. **Bázis típusok**: Ezek közé tartozik a `int` (egész számok), `float` (lebegőpontos számok), `bool` (boolék), `string` (karakterláncok), `array` (tömbök) és `null`. +2. **osztályok**: Amikor azt akarjuk, hogy egy érték egy adott osztály példánya legyen. +3. **Interfészek**: Meghatározza azon metódusok halmazát, amelyeket egy osztálynak implementálnia kell. Egy interfésznek megfelelő értéknek rendelkeznie kell ezekkel a metódusokkal. +4. **Keverék típusok**: Megadhatjuk, hogy egy változónak több megengedett típusa is lehet. +5. **Void**: Ez a speciális típus azt jelzi, hogy egy függvény vagy metódus nem ad vissza értéket. + +Lássuk, hogyan módosíthatjuk a kódot a típusok felvételére: + +```php +class Person +{ + private int $age; + + public function __construct(int $age) + { + $this->age = $age; + } + + public function printAge(): void + { + echo "This person is " . $this->age . " years old."; + } +} + +/** + * A function that accepts a Person object and prints the person's age. + */ +function printPersonAge(Person $person): void +{ + $person->printAge(); +} +``` + +Így biztosítjuk, hogy a kódunk a megfelelő típusú adatokat várja el és a megfelelő típusú adatokkal dolgozik, ami segít megelőzni a lehetséges hibákat. + + +Összehasonlítás és azonosság .[#toc-comparison-and-identity] +------------------------------------------------------------ + +A PHP-ben kétféleképpen lehet objektumokat összehasonlítani: + +1. Érték-összehasonlítás `==`: Ellenőrzi, hogy az objektumok ugyanabba az osztályba tartoznak-e, és tulajdonságaikban ugyanazok az értékek szerepelnek-e. +2. Azonosság `===`: Ellenőrzi, hogy az objektum azonos példányáról van-e szó. + +```php +class Car +{ + public string $brand; + + public function __construct(string $brand) + { + $this->brand = $brand; + } +} + +$car1 = new Car('Skoda'); +$car2 = new Car('Skoda'); +$car3 = $car1; + +var_dump($car1 == $car2); // true, because they have the same value +var_dump($car1 === $car2); // false, because they are not the same instance +var_dump($car1 === $car3); // true, because $car3 is the same instance as $car1 +``` + + +A `instanceof` Üzemeltető .[#toc-the-instanceof-operator] +--------------------------------------------------------- + +A `instanceof` operátor lehetővé teszi annak meghatározását, hogy egy adott objektum egy adott osztály példánya, leszármazottja, vagy egy bizonyos interfész megvalósítója-e. + +Képzeljük el, hogy van egy `Person` osztályunk és egy másik osztályunk, a `Student`, amely a `Person` leszármazottja: + +```php +class Person +{ + private int $age; + + public function __construct(int $age) + { + $this->age = $age; + } +} + +class Student extends Person +{ + private string $major; + + public function __construct(int $age, string $major) + { + parent::__construct($age); + $this->major = $major; + } +} + +$student = new Student(20, 'Computer Science'); + +// Check if $student is an instance of the Student class +var_dump($student instanceof Student); // Output: bool(true) + +// Check if $student is an instance of the Person class (because Student is a descendant of Person) +var_dump($student instanceof Person); // Output: bool(true) +``` + +A kimenetekből látható, hogy a `$student` objektumot a `Student` és a `Person` osztályok példányának tekintjük. + + +Folyékony interfészek .[#toc-fluent-interfaces] +----------------------------------------------- + +A "folyékony interfész" egy olyan technika az OOP-ban, amely lehetővé teszi a metódusok egyetlen hívással történő láncolását. Ez gyakran egyszerűsíti és egyértelművé teszi a kódot. + +A folyékony interfész kulcseleme, hogy a lánc minden egyes metódusa az aktuális objektumra való hivatkozást adja vissza. Ezt a `return $this;` használatával érjük el a metódus végén. Ez a programozási stílus gyakran társul a "setters" nevű metódusokkal, amelyek az objektum tulajdonságainak értékeit állítják be. + +Nézzük meg, hogyan nézhet ki egy folyékony interfész az e-mailek küldéséhez: + +```php +public function sendMessage() +{ + $email = new Email; + $email->setFrom('sender@example.com') + ->setRecipient('admin@example.com') + ->setMessage('Hello, this is a message.') + ->send(); +} +``` + +Ebben a példában a `setFrom()`, `setRecipient()` és `setMessage()` metódusok a megfelelő értékek (feladó, címzett, üzenet tartalma) beállítására szolgálnak. Az egyes értékek beállítása után a metódusok visszaadják az aktuális objektumot (`$email`), ami lehetővé teszi számunkra, hogy egy másik metódust láncoljunk utána. Végül meghívjuk a `send()` metódust, amely ténylegesen elküldi az e-mailt. + +A folyékony interfészeknek köszönhetően olyan kódot írhatunk, amely intuitív és könnyen olvasható. + + +Másolás a `clone` címen .[#toc-copying-with-clone] +-------------------------------------------------- + +A PHP-ben a `clone` operátor segítségével létrehozhatjuk egy objektum másolatát. Így egy új, azonos tartalmú példányt kapunk. + +Ha egy objektum másolásakor szükségünk van néhány tulajdonságának módosítására, akkor az osztályban definiálhatunk egy speciális `__clone()` metódust. Ez a metódus automatikusan meghívódik, amikor az objektumot klónozzuk. + +```php +class Sheep +{ + public string $name; + + public function __construct(string $name) + { + $this->name = $name; + } + + public function __clone() + { + $this->name = 'Clone of ' . $this->name; + } +} + +$original = new Sheep('Dolly'); +echo $original->name . "\n"; // Outputs: Dolly + +$clone = clone $original; +echo $clone->name . "\n"; // Outputs: Clone of Dolly +``` + +Ebben a példában van egy `Sheep` osztályunk, amelynek egy tulajdonsága a `$name`. Amikor klónozzuk ennek az osztálynak egy példányát, a `__clone()` metódus biztosítja, hogy a klónozott bárány neve a "Clone of" előtagot kapja. + + +A tulajdonságok. .[#toc-traits] +-------------------------------- + +A PHP-ban a Traits egy olyan eszköz, amely lehetővé teszi a metódusok, tulajdonságok és konstansok megosztását az osztályok között, és megakadályozza a kód duplikálását. Úgy gondolhatsz rájuk, mint egy "másolás és beillesztés" mechanizmusra (Ctrl-C és Ctrl-V), ahol egy tulajdonság tartalma "beillesztésre" kerül az osztályokba. Ez lehetővé teszi a kód újrafelhasználását anélkül, hogy bonyolult osztályhierarchiákat kellene létrehozni. + +Nézzünk meg egy egyszerű példát a vonások PHP-ban való használatára: + +```php +trait Honking +{ + public function honk() + { + echo 'Beep beep!'; + } +} + +class Car +{ + use Honking; +} + +class Truck +{ + use Honking; +} + +$car = new Car; +$car->honk(); // Outputs 'Beep beep!' + +$truck = new Truck; +$truck->honk(); // Also outputs 'Beep beep!' +``` + +Ebben a példában van egy `Honking` nevű tulajdonságunk, amely egy metódust tartalmaz: `honk()`. Ezután van két osztályunk: `Car` és `Truck`, amelyek mindkettő a `Honking` tulajdonságot használja. Ennek eredményeképpen mindkét osztály "rendelkezik" a `honk()` metódussal, és mindkét osztály objektumain meg tudjuk hívni azt. + +A tulajdonságok lehetővé teszik az osztályok közötti egyszerű és hatékony kódmegosztást. Nem lépnek be az öröklési hierarchiába, azaz a `$car instanceof Honking` a `false`-t fogja visszaadni. + + +Kivételek .[#toc-exceptions] +---------------------------- + +A kivételek az OOP-ban lehetővé teszik számunkra a kódunk végrehajtása során felmerülő hibák kezelését és kezelését. Ezek lényegében olyan objektumok, amelyeket arra terveztek, hogy rögzítsék a programban előforduló hibákat vagy váratlan helyzeteket. + +A PHP-ben ezekre az objektumokra a beépített `Exception` osztály áll rendelkezésünkre. Számos olyan metódussal rendelkezik, amelyek lehetővé teszik számunkra, hogy több információt kapjunk a kivételről, például a hibaüzenetet, a fájlt és a sort, ahol a hiba előfordult, stb. + +Ha probléma merül fel, "dobhatunk" egy kivételt (a `throw`) segítségével. Ha ezt a kivételt "el akarjuk kapni" és feldolgozni, akkor a `try` és a `catch` blokkokat használjuk. + +Lássuk, hogyan működik ez: + +```php +try { + throw new Exception('Message explaining the reason for the exception'); + + // This code won't execute + echo 'I am a message that nobody will read'; + +} catch (Exception $e) { + echo 'Exception caught: '. $e->getMessage(); +} +``` + +Fontos megjegyezni, hogy a kivétel mélyebben, más metódusok hívása közben is dobható. + +Egy `try` blokkhoz több `catch` blokk is megadható, ha különböző típusú kivételekre számítunk. + +Létrehozhatunk egy kivételhierarchiát is, ahol minden kivételosztály örökli az előzőt. Példaként tekintsünk egy egyszerű banki alkalmazást, amely lehetővé teszi a befizetéseket és a kifizetéseket: + +```php +class BankingException extends Exception {} +class InsufficientFundsException extends BankingException {} +class ExceededLimitException extends BankingException {} + +class BankAccount +{ + private int $balance = 0; + private int $dailyLimit = 1000; + + public function deposit(int $amount): int + { + $this->balance += $amount; + return $this->balance; + } + + public function withdraw(int $amount): int + { + if ($amount > $this->balance) { + throw new InsufficientFundsException('Not enough funds in the account.'); + } + + if ($amount > $this->dailyLimit) { + throw new ExceededLimitException('Daily withdrawal limit exceeded.'); + } + + $this->balance -= $amount; + return $this->balance; + } +} + +$account = new BankAccount; +$account->deposit(500); + +try { + $account->withdraw(1500); +} catch (ExceededLimitException $e) { + echo $e->getMessage(); +} catch (InsufficientFundsException $e) { + echo $e->getMessage(); +} catch (BankingException $e) { + echo 'An error occurred during the operation.'; +} +``` + +Ebben a példában fontos megjegyezni a `catch` blokkok sorrendjét. Mivel minden kivétel a `BankingException`-tól öröklődik, ha ez a blokk lenne az első, akkor minden kivételt elkapnánk benne anélkül, hogy a kód elérné a következő `catch` blokkokat. Ezért fontos, hogy a specifikusabb (azaz másoktól öröklődő) kivételek a `catch` blokkok sorrendjében előrébb legyenek, mint a szülő kivételek. + + +Legjobb gyakorlatok .[#toc-best-practices] +------------------------------------------ + +Ha már az objektumorientált programozás alapelveivel megismerkedtél, elengedhetetlen, hogy az OOP legjobb gyakorlataira koncentrálj. Ezek segítenek olyan kódot írni, amely nemcsak funkcionális, hanem olvasható, érthető és könnyen karbantartható is. + +1) **Separation of Concerns**: Minden osztálynak egyértelműen meghatározott felelősségi körrel kell rendelkeznie, és csak egy elsődleges feladattal kell foglalkoznia. Ha egy osztály túl sok mindent csinál, célszerű lehet kisebb, specializált osztályokra bontani. +2) **Kapszulázás**: Az adatoknak és a metódusoknak a lehető legrejtettebbnek kell lenniük, és csak egy meghatározott interfészen keresztül lehet hozzájuk hozzáférni. Ez lehetővé teszi, hogy egy osztály belső megvalósítását megváltoztassuk anélkül, hogy a kód többi részét befolyásolná. +3) **Függőségi injektálás**: Ahelyett, hogy közvetlenül egy osztályon belül hoznánk létre függőségeket, inkább kívülről "injektáljuk" azokat. Ennek az elvnek a mélyebb megértéséhez ajánljuk a [Dependency Injection fejezeteket |dependency-injection:introduction]. diff --git a/nette/it/introduction-to-object-oriented-programming.texy b/nette/it/introduction-to-object-oriented-programming.texy new file mode 100644 index 0000000000..f7a3452daf --- /dev/null +++ b/nette/it/introduction-to-object-oriented-programming.texy @@ -0,0 +1,719 @@ +Introduzione alla programmazione orientata agli oggetti +******************************************************* + +.[perex] +Il termine "OOP" sta per Object-Oriented Programming (programmazione orientata agli oggetti), un modo per organizzare e strutturare il codice. L'OOP ci permette di vedere un programma come un insieme di oggetti che comunicano tra loro, piuttosto che come una sequenza di comandi e funzioni. + +Nell'OOP, un "oggetto" è un'unità che contiene dati e funzioni che operano su tali dati. Gli oggetti vengono creati sulla base di "classi", che possono essere intese come progetti o modelli di oggetti. Una volta che abbiamo una classe, possiamo creare la sua "istanza", che è un oggetto specifico creato a partire da quella classe. + +Vediamo come creare una semplice classe in PHP. Quando si definisce una classe, si usa la parola chiave "class", seguita dal nome della classe e poi dalle parentesi graffe che racchiudono le funzioni della classe (chiamate "metodi") e le variabili della classe (chiamate "proprietà" o "attributi"): + +```php +class Car +{ + function honk() + { + echo 'Beep beep!'; + } +} +``` + +In questo esempio, abbiamo creato una classe chiamata `Car` con una funzione (o "metodo") chiamata `honk`. + +Ogni classe dovrebbe risolvere un solo compito principale. Se una classe fa troppe cose, può essere opportuno dividerla in classi più piccole e specializzate. + +Le classi sono in genere memorizzate in file separati per mantenere il codice organizzato e facile da navigare. Il nome del file deve corrispondere al nome della classe, quindi per la classe `Car` il nome del file sarà `Car.php`. + +Quando si nominano le classi, è bene seguire la convenzione "PascalCase", cioè ogni parola del nome inizia con una lettera maiuscola e non ci sono sottolineature o altri separatori. I metodi e le proprietà seguono la convenzione "camelCase", cioè iniziano con una lettera minuscola. + +Alcuni metodi in PHP hanno ruoli speciali e sono preceduti da `__` (due trattini bassi). Uno dei metodi speciali più importanti è il "costruttore", contrassegnato con `__construct`. Il costruttore è un metodo che viene chiamato automaticamente quando si crea una nuova istanza di una classe. + +Spesso si usa il costruttore per impostare lo stato iniziale di un oggetto. Per esempio, quando si crea un oggetto che rappresenta una persona, si può usare il costruttore per impostarne l'età, il nome o altri attributi. + +Vediamo come utilizzare un costruttore in PHP: + +```php +class Person +{ + private $age; + + function __construct($age) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +$person = new Person(25); +echo $person->howOldAreYou(); // Outputs: 25 +``` + +In questo esempio, la classe `Person` ha una proprietà `$age` e un costruttore che imposta questa proprietà. Il metodo `howOldAreYou()` consente di accedere all'età della persona. + +La parola chiave `new` viene utilizzata per creare una nuova istanza di una classe. Nell'esempio precedente, abbiamo creato una nuova persona di 25 anni. + +È anche possibile impostare valori predefiniti per i parametri del costruttore, se non sono specificati durante la creazione di un oggetto. Per esempio: + +```php +class Person +{ + private $age; + + function __construct($age = 20) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +$person = new Person; // if no argument is passed, parentheses can be omitted +echo $person->howOldAreYou(); // Outputs: 20 +``` + +In questo esempio, se non si specifica l'età quando si crea un oggetto `Person`, verrà usato il valore predefinito di 20. + +Infine, la definizione della proprietà con la sua inizializzazione tramite il costruttore può essere abbreviata e semplificata in questo modo: + +```php +class Person +{ + function __construct( + private $age = 20, + ) { + } +} +``` + + +Spazi dei nomi .[#toc-namespaces] +--------------------------------- + +Gli spazi dei nomi consentono di organizzare e raggruppare classi, funzioni e costanti correlate, evitando conflitti di denominazione. Si possono considerare come le cartelle di un computer, dove ogni cartella contiene file relativi a un progetto o a un argomento specifico. + +Gli spazi dei nomi sono particolarmente utili in progetti di grandi dimensioni o quando si utilizzano librerie di terze parti in cui potrebbero sorgere conflitti di denominazione delle classi. + +Immaginate di avere una classe chiamata `Car` nel vostro progetto e di volerla inserire in uno spazio dei nomi chiamato `Transport`. Si procederà in questo modo: + +```php +namespace Transport; + +class Car +{ + function honk() + { + echo 'Beep beep!'; + } +} +``` + +Se si vuole utilizzare la classe `Car` in un altro file, occorre specificare da quale spazio dei nomi proviene la classe: + +```php +$car = new Transport\Car; +``` + +Per semplificare, si può specificare all'inizio del file quale classe di un particolare spazio dei nomi si vuole utilizzare, consentendo di creare istanze senza citare il percorso completo: + +```php +use Transport\Car; + +$car = new Car; +``` + + +Eredità .[#toc-inheritance] +--------------------------- + +L'ereditarietà è uno strumento della programmazione orientata agli oggetti che consente di creare nuove classi basate su quelle esistenti, ereditandone proprietà e metodi ed estendendole o ridefinendole a seconda delle necessità. L'ereditarietà garantisce la riusabilità del codice e la gerarchia delle classi. + +In parole povere, se abbiamo una classe e vogliamo crearne un'altra derivata da essa ma con alcune modifiche, possiamo "ereditare" la nuova classe da quella originale. + +In PHP, l'ereditarietà viene implementata utilizzando la parola chiave `extends`. + +La nostra classe `Person` memorizza informazioni sull'età. Possiamo avere un'altra classe, `Student`, che estende `Person` e aggiunge informazioni sul campo di studi. + +Vediamo un esempio: + +```php +class Person +{ + private $age; + + function __construct($age) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +class Student extends Person +{ + private $fieldOfStudy; + + function __construct($age, $fieldOfStudy) + { + parent::__construct($age); + $this->fieldOfStudy = $fieldOfStudy; + } + + function printInformation() + { + echo 'Age of student: ', $this->howOldAreYou(); + echo 'Field of study: ', $this->fieldOfStudy; + } +} + +$student = new Student(20, 'Computer Science'); +$student->printInformation(); +``` + +Come funziona questo codice? + +- Abbiamo usato la parola chiave `extends` per estendere la classe `Person`, il che significa che la classe `Student` eredita tutti i metodi e le proprietà da `Person`. + +- La parola chiave `parent::` ci consente di richiamare i metodi della classe padre. In questo caso, abbiamo richiamato il costruttore della classe `Person`, prima di aggiungere le nostre funzionalità alla classe `Student`. + +L'ereditarietà è pensata per le situazioni in cui esiste una relazione "is a" tra le classi. Per esempio, un `Student` è un `Person`. Un gatto è un animale. Ci consente, nei casi in cui ci aspettiamo un oggetto (ad esempio, "Persona") nel codice, di utilizzare invece un oggetto derivato (ad esempio, "Studente"). + +È essenziale rendersi conto che lo scopo principale dell'ereditarietà **non** è quello di prevenire la duplicazione del codice. Al contrario, un uso improprio dell'ereditarietà può portare a codice complesso e difficile da mantenere. Se non c'è una relazione "è un" tra le classi, dovremmo considerare la composizione invece dell'ereditarietà. + + +Composizione .[#toc-composition] +-------------------------------- + +La composizione è una tecnica in cui, invece di ereditare proprietà e metodi da un'altra classe, si usa semplicemente la sua istanza nella propria classe. Questo ci permette di combinare funzionalità e proprietà di più classi senza creare complesse strutture di ereditarietà. + +Ad esempio, abbiamo una classe `Engine` e una classe `Car`. Invece di dire "Un'auto è un motore", diciamo "Un'auto ha un motore", che è una tipica relazione di composizione. + +```php +class Engine +{ + function start() + { + echo "Engine is running."; + } +} + +class Car +{ + private $engine; + + function __construct() + { + $this->engine = new Engine; + } + + function start() + { + $this->engine->start(); + echo "The car is ready to drive!"; + } +} + +$car = new Car; +$car->start(); +``` + +In questo caso, la classe `Car` non possiede tutte le proprietà e i metodi della classe `Engine`, ma vi ha accesso attraverso la proprietà `$engine`. + +Il vantaggio della composizione è una maggiore flessibilità di progettazione e una migliore adattabilità ai cambiamenti futuri. + + +Visibilità .[#toc-visibility] +----------------------------- + +In PHP, è possibile definire la "visibilità" per le proprietà, i metodi e le costanti delle classi. La visibilità determina dove è possibile accedere a questi elementi. + +1. Se un elemento è contrassegnato come `public`, significa che è possibile accedervi da qualsiasi punto, anche al di fuori della classe. + +2. Un elemento contrassegnato come `protected` è accessibile solo all'interno della classe e di tutti i suoi discendenti (classi che ereditano da essa). + +3. Se un elemento è `private`, è possibile accedervi solo dalla classe in cui è stato definito. + +Se non si specifica la visibilità, PHP la imposterà automaticamente a `public`. + +Vediamo un esempio di codice: + +```php +class VisibilityExample +{ + public $publicProperty = 'Public'; + protected $protectedProperty = 'Protected'; + private $privateProperty = 'Private'; + + public function printProperties() + { + echo $this->publicProperty; // Works + echo $this->protectedProperty; // Works + echo $this->privateProperty; // Works + } +} + +$object = new VisibilityExample; +$object->printProperties(); +echo $object->publicProperty; // Works +// echo $object->protectedProperty; // Throws an error +// echo $object->privateProperty; // Throws an error +``` + +Continuare con l'ereditarietà delle classi: + +```php +class ChildClass extends VisibilityExample +{ + public function printProperties() + { + echo $this->publicProperty; // Works + echo $this->protectedProperty; // Works + // echo $this->privateProperty; // Throws an error + } +} +``` + +In questo caso, il metodo `printProperties()` della classe `ChildClass` può accedere alle proprietà pubbliche e protette, ma non alle proprietà private della classe padre. + +I dati e i metodi devono essere il più possibile nascosti e accessibili solo attraverso un'interfaccia definita. Ciò consente di modificare l'implementazione interna della classe senza influenzare il resto del codice. + + +Parola chiave finale .[#toc-final-keyword] +------------------------------------------ + +In PHP, si può usare la parola chiave `final` se si vuole impedire che una classe, un metodo o una costante vengano ereditati o sovrascritti. Quando una classe è contrassegnata come `final`, non può essere estesa. Quando un metodo è contrassegnato come `final`, non può essere sovrascritto in una sottoclasse. + +Essere consapevoli che una certa classe o un certo metodo non saranno più modificati ci permette di apportare modifiche più facilmente senza preoccuparci di potenziali conflitti. Ad esempio, possiamo aggiungere un nuovo metodo senza temere che un discendente abbia già un metodo con lo stesso nome, causando una collisione. Oppure possiamo cambiare i parametri di un metodo, sempre senza il rischio di causare incoerenze con un metodo sovrascritto in un discendente. + +```php +final class FinalClass +{ +} + +// The following code will throw an error because we cannot inherit from a final class. +class ChildOfFinalClass extends FinalClass +{ +} +``` + +In questo esempio, il tentativo di ereditare dalla classe finale `FinalClass` produrrà un errore. + + +Proprietà e metodi statici .[#toc-static-properties-and-methods] +---------------------------------------------------------------- + +Quando si parla di elementi "statici" di una classe in PHP, si intendono metodi e proprietà che appartengono alla classe stessa, non a un'istanza specifica della classe. Ciò significa che non è necessario creare un'istanza della classe per accedervi. Al contrario, è possibile chiamarli o accedervi direttamente attraverso il nome della classe. + +Tenere presente che, poiché gli elementi statici appartengono alla classe e non alle sue istanze, non è possibile utilizzare la pseudo-variabile `$this` all'interno dei metodi statici. + +L'uso di proprietà statiche porta a un [codice offuscato e pieno di insidie |dependency-injection:global-state], quindi non si dovrebbe mai usarle e non ne mostreremo un esempio qui. D'altra parte, i metodi statici sono utili. Ecco un esempio: + +```php +class Calculator +{ + public static function add($a, $b) + { + return $a + $b; + } + + public static function subtract($a, $b) + { + return $a - $b; + } +} + +// Using the static method without creating an instance of the class +echo Calculator::add(5, 3); // Output: 8 +echo Calculator::subtract(5, 3); // Output: 2 +``` + +In questo esempio, abbiamo creato una classe `Calculator` con due metodi statici. Possiamo chiamare questi metodi direttamente, senza creare un'istanza della classe, utilizzando l'operatore `::`. I metodi statici sono particolarmente utili per le operazioni che non dipendono dallo stato di una specifica istanza della classe. + + +Costanti di classe .[#toc-class-constants] +------------------------------------------ + +All'interno delle classi è possibile definire delle costanti. Le costanti sono valori che non cambiano mai durante l'esecuzione del programma. A differenza delle variabili, il valore di una costante rimane invariato. + +```php +class Car +{ + public const NumberOfWheels = 4; + + public function displayNumberOfWheels(): int + { + echo self::NumberOfWheels; + } +} + +echo Car::NumberOfWheels; // Output: 4 +``` + +In questo esempio, abbiamo una classe `Car` con la costante `NumberOfWheels`. Quando si accede alla costante all'interno della classe, si può usare la parola chiave `self` invece del nome della classe. + + +Interfacce di oggetti .[#toc-object-interfaces] +----------------------------------------------- + +Le interfacce di oggetti agiscono come "contratti" per le classi. Se una classe deve implementare un'interfaccia di oggetti, deve contenere tutti i metodi definiti dall'interfaccia. È un ottimo modo per garantire che alcune classi aderiscano allo stesso "contratto" o struttura. + +In PHP, le interfacce sono definite utilizzando la parola chiave `interface`. Tutti i metodi definiti in un'interfaccia sono pubblici (`public`). Quando una classe implementa un'interfaccia, utilizza la parola chiave `implements`. + +```php +interface Animal +{ + function makeSound(); +} + +class Cat implements Animal +{ + public function makeSound() + { + echo 'Meow'; + } +} + +$cat = new Cat; +$cat->makeSound(); +``` + +Se una classe implementa un'interfaccia, ma non tutti i metodi previsti sono definiti, PHP lancia un errore. Una classe può implementare più interfacce contemporaneamente, a differenza dell'ereditarietà, dove una classe può ereditare solo da una classe. + + +Classi astratte .[#toc-abstract-classes] +---------------------------------------- + +Le classi astratte servono come modelli di base per altre classi, ma non è possibile creare direttamente le loro istanze. Contengono un mix di metodi completi e metodi astratti che non hanno un contenuto definito. Le classi che ereditano da classi astratte devono fornire le definizioni di tutti i metodi astratti del genitore. + +Per definire una classe astratta si usa la parola chiave `abstract`. + +```php +abstract class AbstractClass +{ + public function regularMethod() + { + echo 'This is a regular method'; + } + + abstract public function abstractMethod(); +} + +class Child extends AbstractClass +{ + public function abstractMethod() + { + echo 'This is the implementation of the abstract method'; + } +} + +$instance = new Child; +$instance->regularMethod(); +$instance->abstractMethod(); +``` + +In questo esempio, abbiamo una classe astratta con un metodo regolare e uno astratto. Poi abbiamo una classe `Child` che eredita da `AbstractClass` e fornisce un'implementazione per il metodo astratto. + + +Verifica del tipo .[#toc-type-checking] +--------------------------------------- + +Nella programmazione è fondamentale assicurarsi che i dati con cui si lavora siano del tipo corretto. In PHP, disponiamo di strumenti che forniscono questa garanzia. Verificare che i dati siano del tipo corretto si chiama "controllo del tipo". + +Tipi che possiamo incontrare in PHP: + +1. **Tipi di base**: Questi includono `int` (numeri interi), `float` (numeri in virgola mobile), `bool` (valori booleani), `string` (stringhe), `array` (array) e `null`. +2. **Classi**: Quando si vuole che un valore sia un'istanza di una classe specifica. +3. **Interfacce**: Definisce un insieme di metodi che una classe deve implementare. Un valore che soddisfa un'interfaccia deve avere questi metodi. +4. **Tipi misti**: Si può specificare che una variabile può avere più tipi consentiti. +5. **Voide**: Questo tipo speciale indica che una funzione o un metodo non restituisce alcun valore. + +Vediamo come modificare il codice per includere i tipi: + +```php +class Person +{ + private int $age; + + public function __construct(int $age) + { + $this->age = $age; + } + + public function printAge(): void + { + echo "This person is " . $this->age . " years old."; + } +} + +/** + * A function that accepts a Person object and prints the person's age. + */ +function printPersonAge(Person $person): void +{ + $person->printAge(); +} +``` + +In questo modo, ci assicuriamo che il nostro codice si aspetti e lavori con dati del tipo corretto, aiutandoci a prevenire potenziali errori. + + +Confronto e identità .[#toc-comparison-and-identity] +---------------------------------------------------- + +In PHP, è possibile confrontare gli oggetti in due modi: + +1. Confronto tra valori `==`: verifica se gli oggetti appartengono alla stessa classe e hanno gli stessi valori nelle loro proprietà. +2. Identità `===`: verifica se si tratta della stessa istanza dell'oggetto. + +```php +class Car +{ + public string $brand; + + public function __construct(string $brand) + { + $this->brand = $brand; + } +} + +$car1 = new Car('Skoda'); +$car2 = new Car('Skoda'); +$car3 = $car1; + +var_dump($car1 == $car2); // true, because they have the same value +var_dump($car1 === $car2); // false, because they are not the same instance +var_dump($car1 === $car3); // true, because $car3 is the same instance as $car1 +``` + + +L'operatore di `instanceof` .[#toc-the-instanceof-operator] +----------------------------------------------------------- + +L'operatore `instanceof` consente di determinare se un dato oggetto è un'istanza di una classe specifica, un discendente di quella classe o se implementa una certa interfaccia. + +Immaginiamo di avere una classe `Person` e un'altra classe `Student`, che è un discendente di `Person`: + +```php +class Person +{ + private int $age; + + public function __construct(int $age) + { + $this->age = $age; + } +} + +class Student extends Person +{ + private string $major; + + public function __construct(int $age, string $major) + { + parent::__construct($age); + $this->major = $major; + } +} + +$student = new Student(20, 'Computer Science'); + +// Check if $student is an instance of the Student class +var_dump($student instanceof Student); // Output: bool(true) + +// Check if $student is an instance of the Person class (because Student is a descendant of Person) +var_dump($student instanceof Person); // Output: bool(true) +``` + +Dai risultati, è evidente che l'oggetto `$student` è considerato un'istanza di entrambe le classi `Student` e `Person`. + + +Interfacce fluenti .[#toc-fluent-interfaces] +-------------------------------------------- + +Una "interfaccia fluida" è una tecnica dell'OOP che consente di concatenare i metodi in un'unica chiamata. Questo spesso semplifica e chiarisce il codice. + +L'elemento chiave di un'interfaccia fluente è che ogni metodo della catena restituisce un riferimento all'oggetto corrente. Questo si ottiene utilizzando `return $this;` alla fine del metodo. Questo stile di programmazione è spesso associato ai metodi chiamati "setter", che impostano i valori delle proprietà di un oggetto. + +Vediamo come potrebbe essere un'interfaccia fluente per l'invio di e-mail: + +```php +public function sendMessage() +{ + $email = new Email; + $email->setFrom('sender@example.com') + ->setRecipient('admin@example.com') + ->setMessage('Hello, this is a message.') + ->send(); +} +``` + +In questo esempio, i metodi `setFrom()`, `setRecipient()` e `setMessage()` sono usati per impostare i valori corrispondenti (mittente, destinatario, contenuto del messaggio). Dopo aver impostato ciascuno di questi valori, i metodi restituiscono l'oggetto corrente (`$email`), consentendoci di concatenare un altro metodo dopo di esso. Infine, chiamiamo il metodo `send()`, che invia effettivamente l'e-mail. + +Grazie alle interfacce fluide, possiamo scrivere codice intuitivo e facilmente leggibile. + + +Copiare con `clone` .[#toc-copying-with-clone] +---------------------------------------------- + +In PHP, possiamo creare una copia di un oggetto usando l'operatore `clone`. In questo modo, si ottiene una nuova istanza con contenuti identici. + +Se durante la copia di un oggetto è necessario modificarne alcune proprietà, è possibile definire un metodo speciale `__clone()` nella classe. Questo metodo viene richiamato automaticamente quando l'oggetto viene clonato. + +```php +class Sheep +{ + public string $name; + + public function __construct(string $name) + { + $this->name = $name; + } + + public function __clone() + { + $this->name = 'Clone of ' . $this->name; + } +} + +$original = new Sheep('Dolly'); +echo $original->name . "\n"; // Outputs: Dolly + +$clone = clone $original; +echo $clone->name . "\n"; // Outputs: Clone of Dolly +``` + +In questo esempio, abbiamo una classe `Sheep` con una proprietà `$name`. Quando si clona un'istanza di questa classe, il metodo `__clone()` assicura che il nome della pecora clonata ottenga il prefisso "Clone di". + + +Tratti .[#toc-traits] +--------------------- + +I tratti in PHP sono uno strumento che consente di condividere metodi, proprietà e costanti tra le classi, evitando la duplicazione del codice. Si può pensare a loro come a un meccanismo di "copia e incolla" (Ctrl-C e Ctrl-V), in cui il contenuto di un tratto viene "incollato" nelle classi. Ciò consente di riutilizzare il codice senza dover creare complicate gerarchie di classi. + +Vediamo un semplice esempio di utilizzo dei tratti in PHP: + +```php +trait Honking +{ + public function honk() + { + echo 'Beep beep!'; + } +} + +class Car +{ + use Honking; +} + +class Truck +{ + use Honking; +} + +$car = new Car; +$car->honk(); // Outputs 'Beep beep!' + +$truck = new Truck; +$truck->honk(); // Also outputs 'Beep beep!' +``` + +In questo esempio, abbiamo un tratto chiamato `Honking` che contiene un metodo `honk()`. Abbiamo poi due classi: `Car` e `Truck`, che utilizzano entrambe il tratto `Honking`. Di conseguenza, entrambe le classi "possiedono" il metodo `honk()` e possiamo chiamarlo su oggetti di entrambe le classi. + +I tratti consentono di condividere facilmente ed efficacemente il codice tra le classi. Non entrano nella gerarchia ereditaria, cioè `$car instanceof Honking` restituirà `false`. + + +Eccezioni +--------- + +Le eccezioni in OOP consentono di gestire gli errori che possono verificarsi durante l'esecuzione del codice. Sono essenzialmente oggetti progettati per registrare errori o situazioni inaspettate nel programma. + +In PHP, per questi oggetti esiste la classe `Exception`. Essa dispone di diversi metodi che consentono di ottenere ulteriori informazioni sull'eccezione, come il messaggio di errore, il file e la riga in cui si è verificato l'errore, ecc. + +Quando si verifica un problema, possiamo "lanciare" un'eccezione (usando `throw`). Se vogliamo "catturare" ed elaborare questa eccezione, utilizziamo i blocchi `try` e `catch`. + +Vediamo come funziona: + +```php +try { + throw new Exception('Message explaining the reason for the exception'); + + // This code won't execute + echo 'I am a message that nobody will read'; + +} catch (Exception $e) { + echo 'Exception caught: '. $e->getMessage(); +} +``` + +È importante notare che un'eccezione può essere lanciata più in profondità, durante la chiamata ad altri metodi. + +Per un blocco `try`, si possono specificare più blocchi `catch`, se ci si aspetta diversi tipi di eccezioni. + +Si può anche creare una gerarchia di eccezioni, in cui ogni classe di eccezione eredita dalla precedente. A titolo di esempio, si consideri una semplice applicazione bancaria che consente depositi e prelievi: + +```php +class BankingException extends Exception {} +class InsufficientFundsException extends BankingException {} +class ExceededLimitException extends BankingException {} + +class BankAccount +{ + private int $balance = 0; + private int $dailyLimit = 1000; + + public function deposit(int $amount): int + { + $this->balance += $amount; + return $this->balance; + } + + public function withdraw(int $amount): int + { + if ($amount > $this->balance) { + throw new InsufficientFundsException('Not enough funds in the account.'); + } + + if ($amount > $this->dailyLimit) { + throw new ExceededLimitException('Daily withdrawal limit exceeded.'); + } + + $this->balance -= $amount; + return $this->balance; + } +} + +$account = new BankAccount; +$account->deposit(500); + +try { + $account->withdraw(1500); +} catch (ExceededLimitException $e) { + echo $e->getMessage(); +} catch (InsufficientFundsException $e) { + echo $e->getMessage(); +} catch (BankingException $e) { + echo 'An error occurred during the operation.'; +} +``` + +In questo esempio, è importante notare l'ordine dei blocchi `catch`. Poiché tutte le eccezioni ereditano da `BankingException`, se avessimo questo blocco per primo, tutte le eccezioni verrebbero catturate in esso, senza che il codice raggiunga i successivi blocchi `catch`. Pertanto, è importante che le eccezioni più specifiche (cioè quelle che ereditano da altre) si trovino più in alto nell'ordine dei blocchi `catch` rispetto alle loro eccezioni padre. + + +Migliori pratiche .[#toc-best-practices] +---------------------------------------- + +Una volta acquisiti i principi di base della programmazione orientata agli oggetti, è fondamentale concentrarsi sulle best practice dell'OOP. Queste vi aiuteranno a scrivere codice non solo funzionale, ma anche leggibile, comprensibile e facilmente manutenibile. + +1) **Separazione delle preoccupazioni**: Ogni classe dovrebbe avere una responsabilità chiaramente definita e dovrebbe occuparsi di un solo compito primario. Se una classe fa troppe cose, potrebbe essere opportuno dividerla in classi più piccole e specializzate. +2) **Incapsulamento**: I dati e i metodi devono essere il più possibile nascosti e accessibili solo attraverso un'interfaccia definita. Ciò consente di modificare l'implementazione interna di una classe senza influenzare il resto del codice. +3) **Iniezione di dipendenze**: Invece di creare dipendenze direttamente all'interno di una classe, è opportuno "iniettarle" dall'esterno. Per una comprensione più approfondita di questo principio, si consiglia di leggere i [capitoli sulla Dependency Injection |dependency-injection:introduction]. diff --git a/nette/pl/introduction-to-object-oriented-programming.texy b/nette/pl/introduction-to-object-oriented-programming.texy new file mode 100644 index 0000000000..e3d31673e2 --- /dev/null +++ b/nette/pl/introduction-to-object-oriented-programming.texy @@ -0,0 +1,719 @@ +Wprowadzenie do programowania obiektowego +***************************************** + +.[perex] +Termin "OOP" oznacza programowanie obiektowe (Object-Oriented Programming), które jest sposobem organizacji i strukturyzacji kodu. OOP pozwala nam postrzegać program jako zbiór obiektów, które komunikują się ze sobą, a nie jako sekwencję poleceń i funkcji. + +W OOP "obiekt" to jednostka zawierająca dane i funkcje, które działają na tych danych. Obiekty są tworzone w oparciu o "klasy", które można rozumieć jako plany lub szablony obiektów. Gdy mamy już klasę, możemy utworzyć jej "instancję", która jest konkretnym obiektem utworzonym z tej klasy. + +Przyjrzyjmy się jak możemy stworzyć prostą klasę w PHP. Podczas definiowania klasy używamy słowa kluczowego "class", po którym następuje nazwa klasy, a następnie nawiasy klamrowe, które otaczają funkcje klasy (zwane "metodami") i zmienne klasy (zwane "właściwościami" lub "atrybutami"): + +```php +class Car +{ + function honk() + { + echo 'Beep beep!'; + } +} +``` + +W tym przykładzie utworzyliśmy klasę o nazwie `Car` z jedną funkcją (lub "metodą") o nazwie `honk`. + +Każda klasa powinna rozwiązywać tylko jedno główne zadanie. Jeśli klasa wykonuje zbyt wiele zadań, może być wskazane podzielenie jej na mniejsze, wyspecjalizowane klasy. + +Klasy są zwykle przechowywane w oddzielnych plikach, aby kod był uporządkowany i łatwy w nawigacji. Nazwa pliku powinna być zgodna z nazwą klasy, więc dla klasy `Car` nazwa pliku brzmiałaby `Car.php`. + +Podczas nazywania klas dobrze jest przestrzegać konwencji "PascalCase", co oznacza, że każde słowo w nazwie zaczyna się wielką literą i nie ma podkreśleń ani innych separatorów. Metody i właściwości są zgodne z konwencją "camelCase", co oznacza, że zaczynają się od małej litery. + +Niektóre metody w PHP mają specjalne role i są poprzedzone `__` (dwa podkreślenia). Jedną z najważniejszych metod specjalnych jest "konstruktor", oznaczony jako `__construct`. Konstruktor jest metodą, która jest automatycznie wywoływana podczas tworzenia nowej instancji klasy. + +Często używamy konstruktora do ustawienia początkowego stanu obiektu. Na przykład, podczas tworzenia obiektu reprezentującego osobę, można użyć konstruktora, aby ustawić jej wiek, imię lub inne atrybuty. + +Zobaczmy jak używać konstruktora w PHP: + +```php +class Person +{ + private $age; + + function __construct($age) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +$person = new Person(25); +echo $person->howOldAreYou(); // Outputs: 25 +``` + +W tym przykładzie klasa `Person` ma właściwość `$age` i konstruktor, który ustawia tę właściwość. Metoda `howOldAreYou()` zapewnia następnie dostęp do wieku osoby. + +Słowo kluczowe `new` służy do tworzenia nowej instancji klasy. W powyższym przykładzie utworzyliśmy nową osobę w wieku 25 lat. + +Można również ustawić wartości domyślne dla parametrów konstruktora, jeśli nie zostały one określone podczas tworzenia obiektu. Na przykład: + +```php +class Person +{ + private $age; + + function __construct($age = 20) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +$person = new Person; // if no argument is passed, parentheses can be omitted +echo $person->howOldAreYou(); // Outputs: 20 +``` + +W tym przykładzie, jeśli nie określisz wieku podczas tworzenia obiektu `Person`, zostanie użyta domyślna wartość 20. + +Wreszcie, definicję właściwości z jej inicjalizacją za pomocą konstruktora można skrócić i uprościć w następujący sposób: + +```php +class Person +{ + function __construct( + private $age = 20, + ) { + } +} +``` + + +Przestrzenie nazw .[#toc-namespaces] +------------------------------------ + +Przestrzenie nazw pozwalają nam organizować i grupować powiązane klasy, funkcje i stałe, unikając jednocześnie konfliktów nazewnictwa. Można o nich myśleć jak o folderach na komputerze, gdzie każdy folder zawiera pliki związane z konkretnym projektem lub tematem. + +Przestrzenie nazw są szczególnie przydatne w większych projektach lub podczas korzystania z bibliotek innych firm, gdzie mogą wystąpić konflikty nazewnictwa klas. + +Wyobraź sobie, że masz w projekcie klasę o nazwie `Car` i chcesz umieścić ją w przestrzeni nazw o nazwie `Transport`. Można to zrobić w następujący sposób: + +```php +namespace Transport; + +class Car +{ + function honk() + { + echo 'Beep beep!'; + } +} +``` + +Jeśli chcesz użyć klasy `Car` w innym pliku, musisz określić, z której przestrzeni nazw pochodzi ta klasa: + +```php +$car = new Transport\Car; +``` + +Dla uproszczenia można określić na początku pliku, której klasy z danej przestrzeni nazw chcemy użyć, co pozwala na tworzenie instancji bez podawania pełnej ścieżki: + +```php +use Transport\Car; + +$car = new Car; +``` + + +Dziedziczenie .[#toc-inheritance] +--------------------------------- + +Dziedziczenie jest narzędziem programowania obiektowego, które umożliwia tworzenie nowych klas na podstawie istniejących, dziedziczenie ich właściwości i metod oraz rozszerzanie lub redefiniowanie ich w razie potrzeby. Dziedziczenie zapewnia możliwość ponownego wykorzystania kodu i hierarchię klas. + +Mówiąc prościej, jeśli mamy jedną klasę i chcemy utworzyć inną, pochodną od niej, ale z pewnymi modyfikacjami, możemy "odziedziczyć" nową klasę z oryginalnej. + +W PHP dziedziczenie jest implementowane za pomocą słowa kluczowego `extends`. + +Nasza klasa `Person` przechowuje informacje o wieku. Możemy mieć inną klasę, `Student`, która rozszerza `Person` i dodaje informacje o kierunku studiów. + +Spójrzmy na przykład: + +```php +class Person +{ + private $age; + + function __construct($age) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +class Student extends Person +{ + private $fieldOfStudy; + + function __construct($age, $fieldOfStudy) + { + parent::__construct($age); + $this->fieldOfStudy = $fieldOfStudy; + } + + function printInformation() + { + echo 'Age of student: ', $this->howOldAreYou(); + echo 'Field of study: ', $this->fieldOfStudy; + } +} + +$student = new Student(20, 'Computer Science'); +$student->printInformation(); +``` + +Jak działa ten kod? + +- Użyliśmy słowa kluczowego `extends`, aby rozszerzyć klasę `Person`, co oznacza, że klasa `Student` dziedziczy wszystkie metody i właściwości z `Person`. + +- Słowo kluczowe `parent::` pozwala nam wywoływać metody z klasy nadrzędnej. W tym przypadku wywołaliśmy konstruktor z klasy `Person` przed dodaniem naszej własnej funkcjonalności do klasy `Student`. + +Dziedziczenie jest przeznaczone dla sytuacji, w których istnieje relacja "is a" między klasami. Na przykład, klasa `Student` jest klasą `Person`. Kot jest zwierzęciem. Pozwala nam to w przypadkach, w których oczekujemy jednego obiektu (np. "Osoba") w kodzie na użycie obiektu pochodnego (np. "Student"). + +Ważne jest, aby zdać sobie sprawę, że głównym celem dziedziczenia **nie jest** zapobieganie powielaniu kodu. Wręcz przeciwnie, niewłaściwe wykorzystanie dziedziczenia może prowadzić do skomplikowanego i trudnego w utrzymaniu kodu. Jeśli między klasami nie ma relacji "is a", powinniśmy rozważyć kompozycję zamiast dziedziczenia. + + +Kompozycja .[#toc-composition] +------------------------------ + +Kompozycja to technika, w której zamiast dziedziczyć właściwości i metody z innej klasy, po prostu używamy jej instancji w naszej klasie. Pozwala nam to łączyć funkcjonalności i właściwości wielu klas bez tworzenia złożonych struktur dziedziczenia. + +Na przykład, mamy klasę `Engine` i klasę `Car`. Zamiast mówić "Samochód jest silnikiem", mówimy "Samochód ma silnik", co jest typową relacją kompozycji. + +```php +class Engine +{ + function start() + { + echo "Engine is running."; + } +} + +class Car +{ + private $engine; + + function __construct() + { + $this->engine = new Engine; + } + + function start() + { + $this->engine->start(); + echo "The car is ready to drive!"; + } +} + +$car = new Car; +$car->start(); +``` + +W tym przypadku klasa `Car` nie ma wszystkich właściwości i metod klasy `Engine`, ale ma do nich dostęp poprzez właściwość `$engine`. + +Zaletą kompozycji jest większa elastyczność projektu i lepsza zdolność adaptacji do przyszłych zmian. + + +Widoczność .[#toc-visibility] +----------------------------- + +W PHP można zdefiniować "widoczność" dla właściwości, metod i stałych klasy. Widoczność określa, gdzie można uzyskać dostęp do tych elementów. + +1. Jeśli element jest oznaczony jako `public`, oznacza to, że można uzyskać do niego dostęp z dowolnego miejsca, nawet spoza klasy. + +2. Element oznaczony jako `protected` jest dostępny tylko w obrębie klasy i wszystkich jej klas potomnych (klas, które po niej dziedziczą). + +3. Jeśli element jest `private`, można uzyskać do niego dostęp tylko w obrębie klasy, w której został zdefiniowany. + +Jeśli nie określisz widoczności, PHP automatycznie ustawi ją na `public`. + +Spójrzmy na przykładowy kod: + +```php +class VisibilityExample +{ + public $publicProperty = 'Public'; + protected $protectedProperty = 'Protected'; + private $privateProperty = 'Private'; + + public function printProperties() + { + echo $this->publicProperty; // Works + echo $this->protectedProperty; // Works + echo $this->privateProperty; // Works + } +} + +$object = new VisibilityExample; +$object->printProperties(); +echo $object->publicProperty; // Works +// echo $object->protectedProperty; // Throws an error +// echo $object->privateProperty; // Throws an error +``` + +Kontynuacja dziedziczenia klas: + +```php +class ChildClass extends VisibilityExample +{ + public function printProperties() + { + echo $this->publicProperty; // Works + echo $this->protectedProperty; // Works + // echo $this->privateProperty; // Throws an error + } +} +``` + +W tym przypadku metoda `printProperties()` w klasie `ChildClass` może uzyskać dostęp do właściwości publicznych i chronionych, ale nie może uzyskać dostępu do właściwości prywatnych klasy nadrzędnej. + +Dane i metody powinny być jak najbardziej ukryte i dostępne tylko poprzez zdefiniowany interfejs. Pozwala to na zmianę wewnętrznej implementacji klasy bez wpływu na resztę kodu. + + +Końcowe słowo kluczowe .[#toc-final-keyword] +-------------------------------------------- + +W PHP możemy użyć słowa kluczowego `final`, jeśli chcemy zapobiec dziedziczeniu lub nadpisywaniu klasy, metody lub stałej. Gdy klasa jest oznaczona jako `final`, nie może zostać rozszerzona. Gdy metoda jest oznaczona jako `final`, nie może zostać nadpisana w podklasie. + +Świadomość, że dana klasa lub metoda nie będzie już modyfikowana, pozwala nam łatwiej wprowadzać zmiany bez obawy o potencjalne konflikty. Na przykład, możemy dodać nową metodę bez obawy, że potomek może już mieć metodę o tej samej nazwie, co doprowadzi do kolizji. Możemy też zmienić parametry metody, ponownie bez ryzyka spowodowania niespójności z nadpisaną metodą w metodzie potomnej. + +```php +final class FinalClass +{ +} + +// The following code will throw an error because we cannot inherit from a final class. +class ChildOfFinalClass extends FinalClass +{ +} +``` + +W tym przykładzie próba dziedziczenia z klasy finalnej `FinalClass` spowoduje błąd. + + +Statyczne właściwości i metody .[#toc-static-properties-and-methods] +-------------------------------------------------------------------- + +Kiedy mówimy o "statycznych" elementach klasy w PHP, mamy na myśli metody i właściwości, które należą do samej klasy, a nie do konkretnej instancji klasy. Oznacza to, że nie musisz tworzyć instancji klasy, aby uzyskać do nich dostęp. Zamiast tego, wywołujesz je lub uzyskujesz do nich dostęp bezpośrednio poprzez nazwę klasy. + +Należy pamiętać, że ponieważ elementy statyczne należą do klasy, a nie do jej instancji, nie można używać pseudo-zmiennej `$this` wewnątrz metod statycznych. + +Używanie właściwości statycznych prowadzi do [zaciemniania kodu pełnego pułapek |dependency-injection:global-state], więc nigdy nie powinieneś ich używać, a my nie pokażemy tutaj przykładu. Z drugiej strony, metody statyczne są użyteczne. Oto przykład: + +```php +class Calculator +{ + public static function add($a, $b) + { + return $a + $b; + } + + public static function subtract($a, $b) + { + return $a - $b; + } +} + +// Using the static method without creating an instance of the class +echo Calculator::add(5, 3); // Output: 8 +echo Calculator::subtract(5, 3); // Output: 2 +``` + +W tym przykładzie utworzyliśmy klasę `Calculator` z dwiema metodami statycznymi. Możemy wywołać te metody bezpośrednio bez tworzenia instancji klasy za pomocą operatora `::`. Metody statyczne są szczególnie przydatne w przypadku operacji, które nie zależą od stanu konkretnej instancji klasy. + + +Stałe klasowe .[#toc-class-constants] +------------------------------------- + +W ramach klas mamy możliwość definiowania stałych. Stałe to wartości, które nigdy nie zmieniają się podczas wykonywania programu. W przeciwieństwie do zmiennych, wartość stałej pozostaje taka sama. + +```php +class Car +{ + public const NumberOfWheels = 4; + + public function displayNumberOfWheels(): int + { + echo self::NumberOfWheels; + } +} + +echo Car::NumberOfWheels; // Output: 4 +``` + +W tym przykładzie mamy klasę `Car` ze stałą `NumberOfWheels`. Podczas uzyskiwania dostępu do stałej wewnątrz klasy możemy użyć słowa kluczowego `self` zamiast nazwy klasy. + + +Interfejsy obiektów .[#toc-object-interfaces] +--------------------------------------------- + +Interfejsy obiektowe działają jak "kontrakty" dla klas. Jeśli klasa ma zaimplementować interfejs obiektowy, musi zawierać wszystkie metody zdefiniowane przez interfejs. Jest to świetny sposób na zapewnienie, że niektóre klasy przestrzegają tego samego "kontraktu" lub struktury. + +W PHP interfejsy definiowane są za pomocą słowa kluczowego `interface`. Wszystkie metody zdefiniowane w interfejsie są publiczne (`public`). Gdy klasa implementuje interfejs, używa słowa kluczowego `implements`. + +```php +interface Animal +{ + function makeSound(); +} + +class Cat implements Animal +{ + public function makeSound() + { + echo 'Meow'; + } +} + +$cat = new Cat; +$cat->makeSound(); +``` + +Jeśli klasa implementuje interfejs, ale nie wszystkie oczekiwane metody są zdefiniowane, PHP zgłosi błąd. Klasa może implementować wiele interfejsów jednocześnie, co różni się od dziedziczenia, gdzie klasa może dziedziczyć tylko z jednej klasy. + + +Klasy abstrakcyjne .[#toc-abstract-classes] +------------------------------------------- + +Klasy abstrakcyjne służą jako szablony bazowe dla innych klas, ale nie można bezpośrednio tworzyć ich instancji. Zawierają one mieszankę kompletnych metod i metod abstrakcyjnych, które nie mają zdefiniowanej zawartości. Klasy dziedziczące po klasach abstrakcyjnych muszą zawierać definicje wszystkich metod abstrakcyjnych z klasy nadrzędnej. + +Do zdefiniowania klasy abstrakcyjnej używamy słowa kluczowego `abstract`. + +```php +abstract class AbstractClass +{ + public function regularMethod() + { + echo 'This is a regular method'; + } + + abstract public function abstractMethod(); +} + +class Child extends AbstractClass +{ + public function abstractMethod() + { + echo 'This is the implementation of the abstract method'; + } +} + +$instance = new Child; +$instance->regularMethod(); +$instance->abstractMethod(); +``` + +W tym przykładzie mamy klasę abstrakcyjną z jedną zwykłą i jedną abstrakcyjną metodą. Następnie mamy klasę `Child`, która dziedziczy po `AbstractClass` i zapewnia implementację metody abstrakcyjnej. + + +Sprawdzanie typu .[#toc-type-checking] +-------------------------------------- + +W programowaniu kluczowe jest upewnienie się, że dane, z którymi pracujemy, są poprawnego typu. W PHP mamy narzędzia, które to zapewniają. Weryfikacja poprawności typu danych nazywana jest "sprawdzaniem typu". + +Typy, które możemy napotkać w PHP: + +1. **Podstawowe typy**: Należą do nich `int` (liczby całkowite), `float` (liczby zmiennoprzecinkowe), `bool` (wartości logiczne), `string` (ciągi znaków), `array` (tablice) i `null`. +2. **Klasy**: Gdy chcemy, aby wartość była instancją określonej klasy. +3. **Interfaces**: Definiuje zestaw metod, które klasa musi zaimplementować. Wartość, która spełnia interfejs, musi mieć te metody. +4. **Typ mieszany**: Możemy określić, że zmienna może mieć wiele dozwolonych typów. +5. **Void**: Ten specjalny typ wskazuje, że funkcja lub metoda nie zwraca żadnej wartości. + +Zobaczmy, jak zmodyfikować kod, aby uwzględnić typy: + +```php +class Person +{ + private int $age; + + public function __construct(int $age) + { + $this->age = $age; + } + + public function printAge(): void + { + echo "This person is " . $this->age . " years old."; + } +} + +/** + * A function that accepts a Person object and prints the person's age. + */ +function printPersonAge(Person $person): void +{ + $person->printAge(); +} +``` + +W ten sposób upewniamy się, że nasz kod oczekuje i działa z danymi odpowiedniego typu, pomagając nam zapobiegać potencjalnym błędom. + + +Porównanie i tożsamość .[#toc-comparison-and-identity] +------------------------------------------------------ + +W PHP można porównywać obiekty na dwa sposoby: + +1. Porównanie wartości `==`: Sprawdza, czy obiekty są tej samej klasy i mają te same wartości we właściwościach. +2. Tożsamość `===`: Sprawdza, czy jest to ta sama instancja obiektu. + +```php +class Car +{ + public string $brand; + + public function __construct(string $brand) + { + $this->brand = $brand; + } +} + +$car1 = new Car('Skoda'); +$car2 = new Car('Skoda'); +$car3 = $car1; + +var_dump($car1 == $car2); // true, because they have the same value +var_dump($car1 === $car2); // false, because they are not the same instance +var_dump($car1 === $car3); // true, because $car3 is the same instance as $car1 +``` + + +Operator `instanceof` .[#toc-the-instanceof-operator] +----------------------------------------------------- + +Operator `instanceof` pozwala określić, czy dany obiekt jest instancją określonej klasy, potomkiem tej klasy lub czy implementuje określony interfejs. + +Wyobraźmy sobie, że mamy klasę `Person` i inną klasę `Student`, która jest potomkiem klasy `Person`: + +```php +class Person +{ + private int $age; + + public function __construct(int $age) + { + $this->age = $age; + } +} + +class Student extends Person +{ + private string $major; + + public function __construct(int $age, string $major) + { + parent::__construct($age); + $this->major = $major; + } +} + +$student = new Student(20, 'Computer Science'); + +// Check if $student is an instance of the Student class +var_dump($student instanceof Student); // Output: bool(true) + +// Check if $student is an instance of the Person class (because Student is a descendant of Person) +var_dump($student instanceof Person); // Output: bool(true) +``` + +Z danych wyjściowych wynika, że obiekt `$student` jest uważany za instancję zarówno klasy `Student`, jak i `Person`. + + +Płynne interfejsy .[#toc-fluent-interfaces] +------------------------------------------- + +"Fluent Interface" to technika w OOP, która pozwala na łączenie metod w jednym wywołaniu. Często upraszcza to i wyjaśnia kod. + +Kluczowym elementem płynnego interfejsu jest to, że każda metoda w łańcuchu zwraca odniesienie do bieżącego obiektu. Osiąga się to za pomocą `return $this;` na końcu metody. Ten styl programowania jest często kojarzony z metodami zwanymi "setterami", które ustawiają wartości właściwości obiektu. + +Zobaczmy, jak mógłby wyglądać płynny interfejs do wysyłania wiadomości e-mail: + +```php +public function sendMessage() +{ + $email = new Email; + $email->setFrom('sender@example.com') + ->setRecipient('admin@example.com') + ->setMessage('Hello, this is a message.') + ->send(); +} +``` + +W tym przykładzie metody `setFrom()`, `setRecipient()` i `setMessage()` są używane do ustawiania odpowiednich wartości (nadawca, odbiorca, treść wiadomości). Po ustawieniu każdej z tych wartości, metody zwracają bieżący obiekt (`$email`), pozwalając nam na łańcuchowanie kolejnej metody po nim. Na koniec wywołujemy metodę `send()`, która faktycznie wysyła wiadomość e-mail. + +Dzięki płynnym interfejsom możemy pisać kod, który jest intuicyjny i czytelny. + + +Kopiowanie z `clone` .[#toc-copying-with-clone] +----------------------------------------------- + +W PHP możemy utworzyć kopię obiektu za pomocą operatora `clone`. W ten sposób otrzymujemy nową instancję o identycznej zawartości. + +Jeśli podczas kopiowania obiektu musimy zmodyfikować niektóre z jego właściwości, możemy zdefiniować specjalną metodę `__clone()` w klasie. Metoda ta jest automatycznie wywoływana, gdy obiekt jest klonowany. + +```php +class Sheep +{ + public string $name; + + public function __construct(string $name) + { + $this->name = $name; + } + + public function __clone() + { + $this->name = 'Clone of ' . $this->name; + } +} + +$original = new Sheep('Dolly'); +echo $original->name . "\n"; // Outputs: Dolly + +$clone = clone $original; +echo $clone->name . "\n"; // Outputs: Clone of Dolly +``` + +W tym przykładzie mamy klasę `Sheep` z jedną właściwością `$name`. Kiedy klonujemy instancję tej klasy, metoda `__clone()` zapewnia, że nazwa sklonowanej owcy otrzyma przedrostek "Clone of". + + +Cechy .[#toc-traits] +-------------------- + +Traity w PHP są narzędziem, które pozwala na współdzielenie metod, właściwości i stałych pomiędzy klasami i zapobiega duplikacji kodu. Można o nich myśleć jak o mechanizmie "kopiuj-wklej" (Ctrl-C i Ctrl-V), w którym zawartość cechy jest "wklejana" do klas. Pozwala to na ponowne wykorzystanie kodu bez konieczności tworzenia skomplikowanych hierarchii klas. + +Przyjrzyjmy się prostemu przykładowi wykorzystania cech w PHP: + +```php +trait Honking +{ + public function honk() + { + echo 'Beep beep!'; + } +} + +class Car +{ + use Honking; +} + +class Truck +{ + use Honking; +} + +$car = new Car; +$car->honk(); // Outputs 'Beep beep!' + +$truck = new Truck; +$truck->honk(); // Also outputs 'Beep beep!' +``` + +W tym przykładzie mamy cechę o nazwie `Honking`, która zawiera jedną metodę `honk()`. Następnie mamy dwie klasy: `Car` i `Truck`, z których obie używają cechy `Honking`. W rezultacie obie klasy "mają" metodę `honk()` i możemy ją wywołać na obiektach obu klas. + +Cechy pozwalają na łatwe i efektywne współdzielenie kodu pomiędzy klasami. Nie wchodzą one w hierarchię dziedziczenia, tzn. `$car instanceof Honking` zwróci `false`. + + +Wyjątki +------- + +Wyjątki w OOP pozwalają nam obsługiwać i zarządzać błędami, które mogą pojawić się podczas wykonywania naszego kodu. Zasadniczo są to obiekty zaprojektowane do rejestrowania błędów lub nieoczekiwanych sytuacji w programie. + +W PHP mamy wbudowaną klasę `Exception` dla tych obiektów. Posiada ona kilka metod, które pozwalają nam uzyskać więcej informacji o wyjątku, takich jak komunikat o błędzie, plik i wiersz, w którym wystąpił błąd itp. + +Kiedy pojawia się problem, możemy "rzucić" wyjątek (używając `throw`). Jeśli chcemy "złapać" i przetworzyć ten wyjątek, używamy bloków `try` i `catch`. + +Zobaczmy, jak to działa: + +```php +try { + throw new Exception('Message explaining the reason for the exception'); + + // This code won't execute + echo 'I am a message that nobody will read'; + +} catch (Exception $e) { + echo 'Exception caught: '. $e->getMessage(); +} +``` + +Ważne jest, aby pamiętać, że wyjątek może zostać rzucony głębiej, podczas wywoływania innych metod. + +Dla jednego bloku `try` można określić wiele bloków `catch`, jeśli spodziewane są różne typy wyjątków. + +Możemy również utworzyć hierarchię wyjątków, w której każda klasa wyjątków dziedziczy po poprzedniej. Jako przykład rozważmy prostą aplikację bankową, która umożliwia wpłaty i wypłaty: + +```php +class BankingException extends Exception {} +class InsufficientFundsException extends BankingException {} +class ExceededLimitException extends BankingException {} + +class BankAccount +{ + private int $balance = 0; + private int $dailyLimit = 1000; + + public function deposit(int $amount): int + { + $this->balance += $amount; + return $this->balance; + } + + public function withdraw(int $amount): int + { + if ($amount > $this->balance) { + throw new InsufficientFundsException('Not enough funds in the account.'); + } + + if ($amount > $this->dailyLimit) { + throw new ExceededLimitException('Daily withdrawal limit exceeded.'); + } + + $this->balance -= $amount; + return $this->balance; + } +} + +$account = new BankAccount; +$account->deposit(500); + +try { + $account->withdraw(1500); +} catch (ExceededLimitException $e) { + echo $e->getMessage(); +} catch (InsufficientFundsException $e) { + echo $e->getMessage(); +} catch (BankingException $e) { + echo 'An error occurred during the operation.'; +} +``` + +W tym przykładzie ważne jest, aby zwrócić uwagę na kolejność bloków `catch`. Ponieważ wszystkie wyjątki dziedziczą z `BankingException`, gdybyśmy mieli ten blok jako pierwszy, wszystkie wyjątki zostałyby w nim przechwycone, a kod nie dotarłby do kolejnych bloków `catch`. Dlatego ważne jest, aby bardziej specyficzne wyjątki (tj. te, które dziedziczą po innych) znajdowały się wyżej w kolejności bloków `catch` niż ich wyjątki nadrzędne. + + +Najlepsze praktyki .[#toc-best-practices] +----------------------------------------- + +Po opanowaniu podstawowych zasad programowania obiektowego ważne jest, aby skupić się na najlepszych praktykach OOP. Pomogą ci one pisać kod, który jest nie tylko funkcjonalny, ale także czytelny, zrozumiały i łatwy w utrzymaniu. + +1) **Separation of Concerns**: Każda klasa powinna mieć jasno określoną odpowiedzialność i powinna zajmować się tylko jednym podstawowym zadaniem. Jeśli klasa robi zbyt wiele rzeczy, może być właściwe podzielenie jej na mniejsze, wyspecjalizowane klasy. +2) **Ekapsułkowanie**: Dane i metody powinny być jak najbardziej ukryte i dostępne tylko poprzez zdefiniowany interfejs. Pozwala to na zmianę wewnętrznej implementacji klasy bez wpływu na resztę kodu. +3) **Wstrzykiwanie zależności**: Zamiast tworzyć zależności bezpośrednio w klasie, należy "wstrzykiwać" je z zewnątrz. Aby lepiej zrozumieć tę zasadę, zalecamy zapoznanie się z [rozdziałami dotyczącymi wst |dependency-injection:introduction]rzykiwania zależności. diff --git a/nette/pt/introduction-to-object-oriented-programming.texy b/nette/pt/introduction-to-object-oriented-programming.texy new file mode 100644 index 0000000000..41c4ffb88f --- /dev/null +++ b/nette/pt/introduction-to-object-oriented-programming.texy @@ -0,0 +1,719 @@ +Introdução à programação orientada a objetos +******************************************** + +.[perex] +O termo "OOP" significa Object-Oriented Programming (Programação orientada a objetos), que é uma forma de organizar e estruturar o código. A OOP nos permite ver um programa como uma coleção de objetos que se comunicam entre si, em vez de uma sequência de comandos e funções. + +Na OOP, um "objeto" é uma unidade que contém dados e funções que operam com esses dados. Os objetos são criados com base em "classes", que podem ser entendidas como planos ou modelos para objetos. Quando temos uma classe, podemos criar sua "instância", que é um objeto específico criado a partir dessa classe. + +Vamos ver como podemos criar uma classe simples no PHP. Quando definimos uma classe, usamos a palavra-chave "class" (classe), seguida pelo nome da classe e, em seguida, chaves que envolvem as funções da classe (chamadas de "métodos") e as variáveis da classe (chamadas de "propriedades" ou "atributos"): + +```php +class Car +{ + function honk() + { + echo 'Beep beep!'; + } +} +``` + +Neste exemplo, criamos uma classe chamada `Car` com uma função (ou "método") chamada `honk`. + +Cada classe deve resolver apenas uma tarefa principal. Se uma classe estiver fazendo muitas coisas, pode ser apropriado dividi-la em classes menores e especializadas. + +Normalmente, as classes são armazenadas em arquivos separados para manter o código organizado e fácil de navegar. O nome do arquivo deve corresponder ao nome da classe, portanto, para a classe `Car`, o nome do arquivo seria `Car.php`. + +Ao nomear as classes, é bom seguir a convenção "PascalCase", o que significa que cada palavra do nome começa com uma letra maiúscula e não há sublinhados ou outros separadores. Os métodos e as propriedades seguem a convenção "camelCase", ou seja, começam com uma letra minúscula. + +Alguns métodos no PHP têm funções especiais e são prefixados com `__` (dois sublinhados). Um dos métodos especiais mais importantes é o "construtor", rotulado como `__construct`. O construtor é um método que é chamado automaticamente ao criar uma nova instância de uma classe. + +Geralmente usamos o construtor para definir o estado inicial de um objeto. Por exemplo, ao criar um objeto que representa uma pessoa, você pode usar o construtor para definir sua idade, nome ou outros atributos. + +Vamos ver como usar um construtor no PHP: + +```php +class Person +{ + private $age; + + function __construct($age) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +$person = new Person(25); +echo $person->howOldAreYou(); // Outputs: 25 +``` + +Neste exemplo, a classe `Person` tem uma propriedade `$age` e um construtor que define essa propriedade. O método `howOldAreYou()` fornece acesso à idade da pessoa. + +A palavra-chave `new` é usada para criar uma nova instância de uma classe. No exemplo acima, criamos uma nova pessoa com 25 anos. + +Você também pode definir valores padrão para os parâmetros do construtor se eles não forem especificados ao criar um objeto. Por exemplo: + +```php +class Person +{ + private $age; + + function __construct($age = 20) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +$person = new Person; // if no argument is passed, parentheses can be omitted +echo $person->howOldAreYou(); // Outputs: 20 +``` + +Neste exemplo, se você não especificar uma idade ao criar um objeto `Person`, o valor padrão de 20 será usado. + +Por fim, a definição da propriedade com sua inicialização por meio do construtor pode ser encurtada e simplificada da seguinte forma: + +```php +class Person +{ + function __construct( + private $age = 20, + ) { + } +} +``` + + +Namespaces .[#toc-namespaces] +----------------------------- + +Os namespaces nos permitem organizar e agrupar classes, funções e constantes relacionadas, evitando conflitos de nomes. Você pode pensar neles como pastas em um computador, onde cada pasta contém arquivos relacionados a um projeto ou tópico específico. + +Os namespaces são especialmente úteis em projetos maiores ou ao usar bibliotecas de terceiros, onde podem surgir conflitos de nomes de classes. + +Imagine que você tenha uma classe chamada `Car` em seu projeto e queira colocá-la em um namespace chamado `Transport`. Você faria isso da seguinte forma: + +```php +namespace Transport; + +class Car +{ + function honk() + { + echo 'Beep beep!'; + } +} +``` + +Se quiser usar a classe `Car` em outro arquivo, precisará especificar de qual namespace a classe se origina: + +```php +$car = new Transport\Car; +``` + +Para simplificar, você pode especificar no início do arquivo qual classe de um determinado namespace deseja usar, o que lhe permite criar instâncias sem mencionar o caminho completo: + +```php +use Transport\Car; + +$car = new Car; +``` + + +Herança .[#toc-inheritance] +--------------------------- + +A herança é uma ferramenta de programação orientada a objetos que permite a criação de novas classes com base nas existentes, herdando suas propriedades e métodos e estendendo-os ou redefinindo-os conforme necessário. A herança garante a reutilização do código e a hierarquia de classes. + +Em termos simples, se tivermos uma classe e quisermos criar outra derivada dela, mas com algumas modificações, podemos "herdar" a nova classe da original. + +No PHP, a herança é implementada usando a palavra-chave `extends`. + +Nossa classe `Person` armazena informações de idade. Podemos ter outra classe, `Student`, que estende a `Person` e acrescenta informações sobre o campo de estudo. + +Vamos dar uma olhada em um exemplo: + +```php +class Person +{ + private $age; + + function __construct($age) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +class Student extends Person +{ + private $fieldOfStudy; + + function __construct($age, $fieldOfStudy) + { + parent::__construct($age); + $this->fieldOfStudy = $fieldOfStudy; + } + + function printInformation() + { + echo 'Age of student: ', $this->howOldAreYou(); + echo 'Field of study: ', $this->fieldOfStudy; + } +} + +$student = new Student(20, 'Computer Science'); +$student->printInformation(); +``` + +Como esse código funciona? + +- Usamos a palavra-chave `extends` para estender a classe `Person`, o que significa que a classe `Student` herda todos os métodos e propriedades de `Person`. + +- A palavra-chave `parent::` nos permite chamar métodos da classe pai. Nesse caso, chamamos o construtor da classe `Person` antes de adicionar nossa própria funcionalidade à classe `Student`. + +A herança é destinada a situações em que há um relacionamento "é um" entre as classes. Por exemplo, um `Student` é um `Person`. Um gato é um animal. Ela nos permite, nos casos em que esperamos um objeto (por exemplo, "Person") no código, usar um objeto derivado (por exemplo, "Student"). + +É essencial perceber que o objetivo principal da herança **não** é evitar a duplicação de código. Pelo contrário, o uso incorreto da herança pode levar a um código complexo e de difícil manutenção. Se não houver uma relação "é um" entre as classes, devemos considerar a composição em vez da herança. + + +Composição .[#toc-composition] +------------------------------ + +A composição é uma técnica em que, em vez de herdar propriedades e métodos de outra classe, simplesmente usamos sua instância em nossa classe. Isso nos permite combinar funcionalidades e propriedades de várias classes sem criar estruturas de herança complexas. + +Por exemplo, temos uma classe `Engine` e uma classe `Car`. Em vez de dizer "Um carro é um motor", dizemos "Um carro tem um motor", que é uma relação de composição típica. + +```php +class Engine +{ + function start() + { + echo "Engine is running."; + } +} + +class Car +{ + private $engine; + + function __construct() + { + $this->engine = new Engine; + } + + function start() + { + $this->engine->start(); + echo "The car is ready to drive!"; + } +} + +$car = new Car; +$car->start(); +``` + +Aqui, o `Car` não tem todas as propriedades e métodos do `Engine`, mas tem acesso a eles por meio da propriedade `$engine`. + +A vantagem da composição é a maior flexibilidade de design e a melhor adaptabilidade a mudanças futuras. + + +Visibilidade .[#toc-visibility] +------------------------------- + +No PHP, você pode definir "visibilidade" para propriedades de classe, métodos e constantes. A visibilidade determina onde você pode acessar esses elementos. + +1. **Public:** Se um elemento estiver marcado como `public`, isso significa que você pode acessá-lo de qualquer lugar, mesmo fora da classe. + +2. **Protegido:** Um elemento marcado como `protected` é acessível somente dentro da classe e de todos os seus descendentes (classes que herdam dela). + +3. **Private:** Se um elemento for `private`, você poderá acessá-lo somente na classe em que ele foi definido. + +Se você não especificar a visibilidade, o PHP a definirá automaticamente como `public`. + +Vamos dar uma olhada em um exemplo de código: + +```php +class VisibilityExample +{ + public $publicProperty = 'Public'; + protected $protectedProperty = 'Protected'; + private $privateProperty = 'Private'; + + public function printProperties() + { + echo $this->publicProperty; // Works + echo $this->protectedProperty; // Works + echo $this->privateProperty; // Works + } +} + +$object = new VisibilityExample; +$object->printProperties(); +echo $object->publicProperty; // Works +// echo $object->protectedProperty; // Throws an error +// echo $object->privateProperty; // Throws an error +``` + +Continuando com a herança de classes: + +```php +class ChildClass extends VisibilityExample +{ + public function printProperties() + { + echo $this->publicProperty; // Works + echo $this->protectedProperty; // Works + // echo $this->privateProperty; // Throws an error + } +} +``` + +Nesse caso, o método `printProperties()` no `ChildClass` pode acessar as propriedades públicas e protegidas, mas não pode acessar as propriedades privadas da classe principal. + +Os dados e os métodos devem ser tão ocultos quanto possível e acessíveis somente por meio de uma interface definida. Isso permite que você altere a implementação interna da classe sem afetar o restante do código. + + +Palavra-chave final .[#toc-final-keyword] +----------------------------------------- + +No PHP, podemos usar a palavra-chave `final` se quisermos impedir que uma classe, um método ou uma constante seja herdado ou substituído. Quando uma classe é marcada como `final`, ela não pode ser estendida. Quando um método é marcado como `final`, ele não pode ser substituído em uma subclasse. + +O fato de saber que uma determinada classe ou método não será mais modificado nos permite fazer alterações com mais facilidade sem nos preocuparmos com possíveis conflitos. Por exemplo, podemos adicionar um novo método sem medo de que um descendente já tenha um método com o mesmo nome, levando a uma colisão. Ou podemos alterar os parâmetros de um método, novamente sem o risco de causar inconsistência com um método substituído em um descendente. + +```php +final class FinalClass +{ +} + +// The following code will throw an error because we cannot inherit from a final class. +class ChildOfFinalClass extends FinalClass +{ +} +``` + +Neste exemplo, a tentativa de herdar da classe final `FinalClass` resultará em um erro. + + +Propriedades e métodos estáticos .[#toc-static-properties-and-methods] +---------------------------------------------------------------------- + +Quando falamos de elementos "estáticos" de uma classe no PHP, queremos dizer métodos e propriedades que pertencem à própria classe, não a uma instância específica da classe. Isso significa que não é necessário criar uma instância da classe para acessá-los. Em vez disso, você os chama ou acessa diretamente por meio do nome da classe. + +Lembre-se de que, como os elementos estáticos pertencem à classe e não às suas instâncias, você não pode usar a pseudovariável `$this` dentro dos métodos estáticos. + +O uso de propriedades estáticas leva a um [código ofuscado e cheio de armadilhas |dependency-injection:global-state], portanto, você nunca deve usá-las, e não mostraremos um exemplo aqui. Por outro lado, os métodos estáticos são úteis. Aqui está um exemplo: + +```php +class Calculator +{ + public static function add($a, $b) + { + return $a + $b; + } + + public static function subtract($a, $b) + { + return $a - $b; + } +} + +// Using the static method without creating an instance of the class +echo Calculator::add(5, 3); // Output: 8 +echo Calculator::subtract(5, 3); // Output: 2 +``` + +Neste exemplo, criamos uma classe `Calculator` com dois métodos estáticos. Podemos chamar esses métodos diretamente sem criar uma instância da classe usando o operador `::`. Os métodos estáticos são especialmente úteis para operações que não dependem do estado de uma instância específica da classe. + + +Constantes de classe .[#toc-class-constants] +-------------------------------------------- + +Nas classes, temos a opção de definir constantes. Constantes são valores que nunca mudam durante a execução do programa. Ao contrário das variáveis, o valor de uma constante permanece o mesmo. + +```php +class Car +{ + public const NumberOfWheels = 4; + + public function displayNumberOfWheels(): int + { + echo self::NumberOfWheels; + } +} + +echo Car::NumberOfWheels; // Output: 4 +``` + +Neste exemplo, temos uma classe `Car` com a constante `NumberOfWheels`. Ao acessar a constante dentro da classe, podemos usar a palavra-chave `self` em vez do nome da classe. + + +Interfaces de objeto .[#toc-object-interfaces] +---------------------------------------------- + +As interfaces de objetos funcionam como "contratos" para as classes. Se uma classe tiver que implementar uma interface de objeto, ela deverá conter todos os métodos que a interface define. Essa é uma ótima maneira de garantir que determinadas classes sigam o mesmo "contrato" ou estrutura. + +No PHP, as interfaces são definidas usando a palavra-chave `interface`. Todos os métodos definidos em uma interface são públicos (`public`). Quando uma classe implementa uma interface, ela usa a palavra-chave `implements`. + +```php +interface Animal +{ + function makeSound(); +} + +class Cat implements Animal +{ + public function makeSound() + { + echo 'Meow'; + } +} + +$cat = new Cat; +$cat->makeSound(); +``` + +Se uma classe implementar uma interface, mas nem todos os métodos esperados estiverem definidos, o PHP lançará um erro. Uma classe pode implementar várias interfaces de uma vez, o que é diferente da herança, em que uma classe só pode herdar de uma classe. + + +Classes abstratas .[#toc-abstract-classes] +------------------------------------------ + +As classes abstratas servem como modelos de base para outras classes, mas você não pode criar suas instâncias diretamente. Elas contêm uma mistura de métodos completos e métodos abstratos que não têm um conteúdo definido. As classes que herdam de classes abstratas devem fornecer definições para todos os métodos abstratos da classe pai. + +Usamos a palavra-chave `abstract` para definir uma classe abstrata. + +```php +abstract class AbstractClass +{ + public function regularMethod() + { + echo 'This is a regular method'; + } + + abstract public function abstractMethod(); +} + +class Child extends AbstractClass +{ + public function abstractMethod() + { + echo 'This is the implementation of the abstract method'; + } +} + +$instance = new Child; +$instance->regularMethod(); +$instance->abstractMethod(); +``` + +Neste exemplo, temos uma classe abstrata com um método regular e um método abstrato. Em seguida, temos uma classe `Child` que herda de `AbstractClass` e fornece uma implementação para o método abstrato. + + +Verificação de tipo .[#toc-type-checking] +----------------------------------------- + +Na programação, é fundamental garantir que os dados com os quais trabalhamos sejam do tipo correto. No PHP, temos ferramentas que oferecem essa garantia. A verificação de que os dados são do tipo correto é chamada de "verificação de tipo". + +Tipos que podemos encontrar no PHP: + +1. **Tipos básicos**: Incluem `int` (inteiros), `float` (números de ponto flutuante), `bool` (valores booleanos), `string` (strings), `array` (arrays) e `null`. +2. **Classes**: Quando queremos que um valor seja uma instância de uma classe específica. +3. **Interfaces**: Define um conjunto de métodos que uma classe deve implementar. Um valor que atende a uma interface deve ter esses métodos. +4. **Tipos mistos**: Podemos especificar que uma variável pode ter vários tipos permitidos. +5. **Void**: Esse tipo especial indica que uma função ou método não retorna nenhum valor. + +Vamos ver como modificar o código para incluir tipos: + +```php +class Person +{ + private int $age; + + public function __construct(int $age) + { + $this->age = $age; + } + + public function printAge(): void + { + echo "This person is " . $this->age . " years old."; + } +} + +/** + * A function that accepts a Person object and prints the person's age. + */ +function printPersonAge(Person $person): void +{ + $person->printAge(); +} +``` + +Dessa forma, garantimos que nosso código espera e trabalha com dados do tipo correto, o que nos ajuda a evitar possíveis erros. + + +Comparação e identidade .[#toc-comparison-and-identity] +------------------------------------------------------- + +No PHP, você pode comparar objetos de duas maneiras: + +1. Comparação de valores `==`: Verifica se os objetos são da mesma classe e têm os mesmos valores em suas propriedades. +2. Identidade `===`: Verifica se é a mesma instância do objeto. + +```php +class Car +{ + public string $brand; + + public function __construct(string $brand) + { + $this->brand = $brand; + } +} + +$car1 = new Car('Skoda'); +$car2 = new Car('Skoda'); +$car3 = $car1; + +var_dump($car1 == $car2); // true, because they have the same value +var_dump($car1 === $car2); // false, because they are not the same instance +var_dump($car1 === $car3); // true, because $car3 is the same instance as $car1 +``` + + +O operador do `instanceof` .[#toc-the-instanceof-operator] +---------------------------------------------------------- + +O operador `instanceof` permite que você determine se um determinado objeto é uma instância de uma classe específica, um descendente dessa classe ou se implementa uma determinada interface. + +Imagine que temos uma classe `Person` e outra classe `Student`, que é descendente de `Person`: + +```php +class Person +{ + private int $age; + + public function __construct(int $age) + { + $this->age = $age; + } +} + +class Student extends Person +{ + private string $major; + + public function __construct(int $age, string $major) + { + parent::__construct($age); + $this->major = $major; + } +} + +$student = new Student(20, 'Computer Science'); + +// Check if $student is an instance of the Student class +var_dump($student instanceof Student); // Output: bool(true) + +// Check if $student is an instance of the Person class (because Student is a descendant of Person) +var_dump($student instanceof Person); // Output: bool(true) +``` + +A partir dos resultados, fica evidente que o objeto `$student` é considerado uma instância das classes `Student` e `Person`. + + +Interfaces fluentes .[#toc-fluent-interfaces] +--------------------------------------------- + +Uma "Interface Fluente" é uma técnica em OOP que permite encadear métodos em uma única chamada. Isso geralmente simplifica e esclarece o código. + +O principal elemento de uma interface fluente é que cada método na cadeia retorna uma referência ao objeto atual. Isso é obtido com o uso do endereço `return $this;` no final do método. Esse estilo de programação é frequentemente associado a métodos chamados "setters", que definem os valores das propriedades de um objeto. + +Vamos ver como seria uma interface fluente para o envio de e-mails: + +```php +public function sendMessage() +{ + $email = new Email; + $email->setFrom('sender@example.com') + ->setRecipient('admin@example.com') + ->setMessage('Hello, this is a message.') + ->send(); +} +``` + +Neste exemplo, os métodos `setFrom()`, `setRecipient()` e `setMessage()` são usados para definir os valores correspondentes (remetente, destinatário, conteúdo da mensagem). Depois de definir cada um desses valores, os métodos retornam o objeto atual (`$email`), o que nos permite encadear outro método depois dele. Por fim, chamamos o método `send()`, que de fato envia o e-mail. + +Graças às interfaces fluentes, podemos escrever códigos intuitivos e de fácil leitura. + + +Copiando com `clone` .[#toc-copying-with-clone] +----------------------------------------------- + +No PHP, podemos criar uma cópia de um objeto usando o operador `clone`. Dessa forma, obtemos uma nova instância com conteúdo idêntico. + +Se precisarmos modificar algumas de suas propriedades ao copiar um objeto, podemos definir um método `__clone()` especial na classe. Esse método é chamado automaticamente quando o objeto é clonado. + +```php +class Sheep +{ + public string $name; + + public function __construct(string $name) + { + $this->name = $name; + } + + public function __clone() + { + $this->name = 'Clone of ' . $this->name; + } +} + +$original = new Sheep('Dolly'); +echo $original->name . "\n"; // Outputs: Dolly + +$clone = clone $original; +echo $clone->name . "\n"; // Outputs: Clone of Dolly +``` + +Neste exemplo, temos uma classe `Sheep` com uma propriedade `$name`. Quando clonamos uma instância dessa classe, o método `__clone()` garante que o nome da ovelha clonada receba o prefixo "Clone of". + + +Características .[#toc-traits] +------------------------------ + +As características no PHP são uma ferramenta que permite o compartilhamento de métodos, propriedades e constantes entre classes e evita a duplicação de código. Você pode pensar nelas como um mecanismo de "copiar e colar" (Ctrl-C e Ctrl-V), em que o conteúdo de uma característica é "colado" nas classes. Isso permite que você reutilize o código sem precisar criar hierarquias de classe complicadas. + +Vamos dar uma olhada em um exemplo simples de como usar características no PHP: + +```php +trait Honking +{ + public function honk() + { + echo 'Beep beep!'; + } +} + +class Car +{ + use Honking; +} + +class Truck +{ + use Honking; +} + +$car = new Car; +$car->honk(); // Outputs 'Beep beep!' + +$truck = new Truck; +$truck->honk(); // Also outputs 'Beep beep!' +``` + +Neste exemplo, temos uma característica chamada `Honking` que contém um método `honk()`. Em seguida, temos duas classes: `Car` e `Truck`, ambas as quais usam a característica `Honking`. Como resultado, ambas as classes "têm" o método `honk()` e podemos chamá-lo em objetos de ambas as classes. + +As características permitem o compartilhamento fácil e eficiente de código entre classes. Elas não entram na hierarquia de herança, ou seja, `$car instanceof Honking` retornará `false`. + + +Exceções +-------- + +As exceções em OOP nos permitem tratar e gerenciar erros que possam surgir durante a execução do nosso código. Basicamente, elas são objetos projetados para registrar erros ou situações inesperadas no programa. + +No PHP, temos a classe `Exception` integrada para esses objetos. Ela tem vários métodos que nos permitem obter mais informações sobre a exceção, como a mensagem de erro, o arquivo e a linha em que o erro ocorreu etc. + +Quando surge um problema, podemos "lançar" uma exceção (usando `throw`). Se quisermos "capturar" e processar essa exceção, usaremos os blocos `try` e `catch`. + +Vamos ver como isso funciona: + +```php +try { + throw new Exception('Message explaining the reason for the exception'); + + // This code won't execute + echo 'I am a message that nobody will read'; + +} catch (Exception $e) { + echo 'Exception caught: '. $e->getMessage(); +} +``` + +É importante observar que uma exceção pode ser lançada mais profundamente, durante a chamada para outros métodos. + +Para um bloco `try`, vários blocos `catch` podem ser especificados se você espera diferentes tipos de exceções. + +Também podemos criar uma hierarquia de exceções, em que cada classe de exceção herda da anterior. Como exemplo, considere um aplicativo bancário simples que permite depósitos e saques: + +```php +class BankingException extends Exception {} +class InsufficientFundsException extends BankingException {} +class ExceededLimitException extends BankingException {} + +class BankAccount +{ + private int $balance = 0; + private int $dailyLimit = 1000; + + public function deposit(int $amount): int + { + $this->balance += $amount; + return $this->balance; + } + + public function withdraw(int $amount): int + { + if ($amount > $this->balance) { + throw new InsufficientFundsException('Not enough funds in the account.'); + } + + if ($amount > $this->dailyLimit) { + throw new ExceededLimitException('Daily withdrawal limit exceeded.'); + } + + $this->balance -= $amount; + return $this->balance; + } +} + +$account = new BankAccount; +$account->deposit(500); + +try { + $account->withdraw(1500); +} catch (ExceededLimitException $e) { + echo $e->getMessage(); +} catch (InsufficientFundsException $e) { + echo $e->getMessage(); +} catch (BankingException $e) { + echo 'An error occurred during the operation.'; +} +``` + +Nesse exemplo, é importante observar a ordem dos blocos `catch`. Como todas as exceções são herdadas de `BankingException`, se tivéssemos esse bloco primeiro, todas as exceções seriam capturadas nele sem que o código chegasse aos blocos `catch` subsequentes. Portanto, é importante que as exceções mais específicas (ou seja, aquelas que herdam de outras) estejam em uma posição mais alta na ordem do bloco `catch` do que suas exceções pai. + + +Melhores práticas .[#toc-best-practices] +---------------------------------------- + +Depois de aprender os princípios básicos da programação orientada a objetos, é fundamental concentrar-se nas práticas recomendadas de OOP. Elas o ajudarão a escrever códigos que não sejam apenas funcionais, mas também legíveis, compreensíveis e de fácil manutenção. + +1) **Separação de preocupações**: Cada classe deve ter uma responsabilidade claramente definida e deve tratar apenas de uma tarefa principal. Se uma classe fizer muitas coisas, pode ser apropriado dividi-la em classes menores e especializadas. +2) **Encapsulamento**: Os dados e métodos devem ser tão ocultos quanto possível e acessíveis somente por meio de uma interface definida. Isso permite que você altere a implementação interna de uma classe sem afetar o restante do código. +3) **Injeção de dependência**: Em vez de criar dependências diretamente em uma classe, você deve "injetá-las" do lado de fora. Para entender melhor esse princípio, recomendamos os [capítulos sobre Injeção de Dependência |dependency-injection:introduction]. diff --git a/nette/ro/introduction-to-object-oriented-programming.texy b/nette/ro/introduction-to-object-oriented-programming.texy new file mode 100644 index 0000000000..8fb5e33237 --- /dev/null +++ b/nette/ro/introduction-to-object-oriented-programming.texy @@ -0,0 +1,719 @@ +Introducere în programarea orientată pe obiecte +*********************************************** + +.[perex] +Termenul "OOP" înseamnă Object-Oriented Programming (programare orientată pe obiecte), care reprezintă o modalitate de organizare și structurare a codului. OOP ne permite să privim un program ca pe o colecție de obiecte care comunică între ele, mai degrabă decât ca pe o secvență de comenzi și funcții. + +În OOP, un "obiect" este o unitate care conține date și funcții care operează cu aceste date. Obiectele sunt create pe baza unor "clase", care pot fi înțelese ca planuri sau șabloane pentru obiecte. Odată ce avem o clasă, putem crea o "instanță" a acesteia, care este un obiect specific creat din clasa respectivă. + +Să vedem cum putem crea o clasă simplă în PHP. Atunci când definim o clasă, folosim cuvântul cheie "class", urmat de numele clasei și apoi de parantezele curbe care înconjoară funcțiile clasei (numite "metode") și variabilele clasei (numite "proprietăți" sau "atribute"): + +```php +class Car +{ + function honk() + { + echo 'Beep beep!'; + } +} +``` + +În acest exemplu, am creat o clasă numită `Car` cu o funcție (sau "metodă") numită `honk`. + +Fiecare clasă trebuie să rezolve o singură sarcină principală. În cazul în care o clasă face prea multe lucruri, ar putea fi oportună împărțirea ei în clase mai mici, specializate. + +Clasele sunt de obicei stocate în fișiere separate pentru a păstra codul organizat și ușor de navigat. Numele fișierului ar trebui să se potrivească cu numele clasei, astfel încât pentru clasa `Car`, numele fișierului ar fi `Car.php`. + +Atunci când denumiți clasele, este bine să urmați convenția "PascalCase", ceea ce înseamnă că fiecare cuvânt din nume începe cu majusculă și nu există sublinieri sau alți separatori. Metodele și proprietățile urmează convenția "camelCase", ceea ce înseamnă că încep cu o literă mică. + +Unele metode din PHP au roluri speciale și sunt prefixate cu `__` (două liniuțe de subliniere). Una dintre cele mai importante metode speciale este "constructorul", etichetat cu `__construct`. Constructorul este o metodă care este apelată automat atunci când se creează o nouă instanță a unei clase. + +Utilizăm adesea constructorul pentru a stabili starea inițială a unui obiect. De exemplu, atunci când creați un obiect care reprezintă o persoană, ați putea folosi constructorul pentru a seta vârsta, numele sau alte atribute ale acesteia. + +Să vedem cum să folosim un constructor în PHP: + +```php +class Person +{ + private $age; + + function __construct($age) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +$person = new Person(25); +echo $person->howOldAreYou(); // Outputs: 25 +``` + +În acest exemplu, clasa `Person` are o proprietate `$age` și un constructor care stabilește această proprietate. Metoda `howOldAreYou()` oferă apoi acces la vârsta persoanei. + +Cuvântul cheie `new` este utilizat pentru a crea o nouă instanță a unei clase. În exemplul de mai sus, am creat o nouă persoană în vârstă de 25 de ani. + +De asemenea, puteți seta valori implicite pentru parametrii constructorului dacă nu sunt specificate la crearea unui obiect. De exemplu: + +```php +class Person +{ + private $age; + + function __construct($age = 20) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +$person = new Person; // if no argument is passed, parentheses can be omitted +echo $person->howOldAreYou(); // Outputs: 20 +``` + +În acest exemplu, dacă nu se specifică o vârstă la crearea unui obiect `Person`, se va utiliza valoarea implicită de 20 de ani. + +În cele din urmă, definirea proprietății cu inițializarea acesteia prin intermediul constructorului poate fi scurtată și simplificată astfel: + +```php +class Person +{ + function __construct( + private $age = 20, + ) { + } +} +``` + + +Spații de nume .[#toc-namespaces] +--------------------------------- + +Spațiile de nume ne permit să organizăm și să grupăm clase, funcții și constante înrudite, evitând în același timp conflictele de denumire. Vă puteți gândi la ele ca la dosarele de pe un computer, unde fiecare dosar conține fișiere legate de un anumit proiect sau subiect. + +Spațiile de nume sunt deosebit de utile în proiectele mai mari sau atunci când se utilizează biblioteci de la terți, unde pot apărea conflicte de denumire a claselor. + +Imaginați-vă că aveți o clasă numită `Car` în proiectul dumneavoastră și doriți să o plasați într-un namespace numit `Transport`. Ați face acest lucru în felul următor: + +```php +namespace Transport; + +class Car +{ + function honk() + { + echo 'Beep beep!'; + } +} +``` + +Dacă doriți să utilizați clasa `Car` într-un alt fișier, trebuie să specificați din ce spațiu de nume provine clasa: + +```php +$car = new Transport\Car; +``` + +Pentru simplificare, puteți specifica la începutul fișierului ce clasă dintr-un anumit spațiu de nume doriți să utilizați, ceea ce vă permite să creați instanțe fără a menționa calea completă: + +```php +use Transport\Car; + +$car = new Car; +``` + + +Moștenirea .[#toc-inheritance] +------------------------------ + +Moștenirea este un instrument al programării orientate pe obiecte care permite crearea de noi clase pe baza celor existente, moștenind proprietățile și metodele acestora și extinzându-le sau redefinindu-le în funcție de necesități. Moștenirea asigură reutilizarea codului și ierarhia claselor. + +Pur și simplu, dacă avem o clasă și dorim să creăm o alta derivată din ea, dar cu unele modificări, putem "moșteni" noua clasă din cea originală. + +În PHP, moștenirea este implementată cu ajutorul cuvântului cheie `extends`. + +Clasa noastră `Person` stochează informații despre vârstă. Putem avea o altă clasă, `Student`, care extinde `Person` și adaugă informații despre domeniul de studiu. + +Să ne uităm la un exemplu: + +```php +class Person +{ + private $age; + + function __construct($age) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +class Student extends Person +{ + private $fieldOfStudy; + + function __construct($age, $fieldOfStudy) + { + parent::__construct($age); + $this->fieldOfStudy = $fieldOfStudy; + } + + function printInformation() + { + echo 'Age of student: ', $this->howOldAreYou(); + echo 'Field of study: ', $this->fieldOfStudy; + } +} + +$student = new Student(20, 'Computer Science'); +$student->printInformation(); +``` + +Cum funcționează acest cod? + +- Am folosit cuvântul cheie `extends` pentru a extinde clasa `Person`, ceea ce înseamnă că clasa `Student` moștenește toate metodele și proprietățile de la `Person`. + +- Cuvântul cheie `parent::` ne permite să apelăm metode din clasa părinte. În acest caz, am apelat constructorul din clasa `Person` înainte de a adăuga propria noastră funcționalitate la clasa `Student`. + +Moștenirea este destinată situațiilor în care există o relație "este o" între clase. De exemplu, un `Student` este un `Person`. O pisică este un animal. Ne permite ca în cazurile în care ne așteptăm ca un obiect (de exemplu, "Persoană") din cod să folosim în schimb un obiect derivat (de exemplu, "Student"). + +Este esențial să ne dăm seama că scopul principal al moștenirii **nu este** acela de a preveni duplicarea codului. Dimpotrivă, utilizarea greșită a moștenirii poate duce la un cod complex și greu de întreținut. În cazul în care nu există o relație "este un" între clase, ar trebui să luăm în considerare compoziția în locul moștenirii. + + +Compoziția .[#toc-composition] +------------------------------ + +Compoziția este o tehnică prin care, în loc să moștenim proprietăți și metode dintr-o altă clasă, pur și simplu folosim instanța acesteia în clasa noastră. Acest lucru ne permite să combinăm funcționalitățile și proprietățile mai multor clase fără a crea structuri complexe de moștenire. + +De exemplu, avem o clasă `Engine` și o clasă `Car`. În loc să spunem "O mașină este un motor", spunem "O mașină are un motor", ceea ce reprezintă o relație de compoziție tipică. + +```php +class Engine +{ + function start() + { + echo "Engine is running."; + } +} + +class Car +{ + private $engine; + + function __construct() + { + $this->engine = new Engine; + } + + function start() + { + $this->engine->start(); + echo "The car is ready to drive!"; + } +} + +$car = new Car; +$car->start(); +``` + +Aici, `Car` nu are toate proprietățile și metodele clasei `Engine`, dar are acces la acestea prin intermediul proprietății `$engine`. + +Avantajul compoziției este o mai mare flexibilitate de proiectare și o mai bună adaptabilitate la schimbările viitoare. + + +Vizibilitate .[#toc-visibility] +------------------------------- + +În PHP, puteți defini "vizibilitatea" pentru proprietățile, metodele și constantele clasei. Vizibilitatea determină unde puteți accesa aceste elemente. + +1. **Public:** Dacă un element este marcat ca fiind `public`, înseamnă că îl puteți accesa de oriunde, chiar și din afara clasei. + +2. **Protected:** Un element marcat ca `protected` este accesibil numai în cadrul clasei și al tuturor descendenților săi (clase care moștenesc din aceasta). + +3. **Privat:** Dacă un element este marcat `private`, acesta poate fi accesat numai din interiorul clasei în care a fost definit. + +Dacă nu specificați vizibilitatea, PHP o va seta automat la `public`. + +Să ne uităm la un exemplu de cod: + +```php +class VisibilityExample +{ + public $publicProperty = 'Public'; + protected $protectedProperty = 'Protected'; + private $privateProperty = 'Private'; + + public function printProperties() + { + echo $this->publicProperty; // Works + echo $this->protectedProperty; // Works + echo $this->privateProperty; // Works + } +} + +$object = new VisibilityExample; +$object->printProperties(); +echo $object->publicProperty; // Works +// echo $object->protectedProperty; // Throws an error +// echo $object->privateProperty; // Throws an error +``` + +Continuăm cu moștenirea claselor: + +```php +class ChildClass extends VisibilityExample +{ + public function printProperties() + { + echo $this->publicProperty; // Works + echo $this->protectedProperty; // Works + // echo $this->privateProperty; // Throws an error + } +} +``` + +În acest caz, metoda `printProperties()` din `ChildClass` poate accesa proprietățile publice și protejate, dar nu poate accesa proprietățile private ale clasei părinte. + +Datele și metodele ar trebui să fie cât mai ascunse posibil și să fie accesibile numai printr-o interfață definită. Acest lucru vă permite să modificați implementarea internă a clasei fără a afecta restul codului. + + +Cuvântul cheie final .[#toc-final-keyword] +------------------------------------------ + +În PHP, putem folosi cuvântul cheie `final` dacă dorim să împiedicăm moștenirea sau suprapunerea unei clase, metode sau constante. Atunci când o clasă este marcată ca `final`, aceasta nu poate fi extinsă. Atunci când o metodă este marcată ca `final`, aceasta nu poate fi suprascrisă într-o subclasă. + +Faptul că știm că o anumită clasă sau metodă nu va mai fi modificată ne permite să facem modificări mai ușor, fără a ne face griji cu privire la eventualele conflicte. De exemplu, putem adăuga o nouă metodă fără să ne temem că un descendent ar putea avea deja o metodă cu același nume, ceea ce ar duce la o coliziune. Sau putem modifica parametrii unei metode, din nou fără riscul de a provoca o inconsecvență cu o metodă suprascrisă într-un descendent. + +```php +final class FinalClass +{ +} + +// The following code will throw an error because we cannot inherit from a final class. +class ChildOfFinalClass extends FinalClass +{ +} +``` + +În acest exemplu, încercarea de a moșteni din clasa finală `FinalClass` va duce la o eroare. + + +Proprietăți și metode statice .[#toc-static-properties-and-methods] +------------------------------------------------------------------- + +Când vorbim despre elemente "statice" ale unei clase în PHP, ne referim la metode și proprietăți care aparțin clasei în sine, nu unei instanțe specifice a clasei. Acest lucru înseamnă că nu trebuie să creați o instanță a clasei pentru a le accesa. În schimb, le apelați sau le accesați direct prin intermediul numelui clasei. + +Rețineți că, deoarece elementele statice aparțin clasei și nu instanțelor sale, nu puteți utiliza pseudo-variabila `$this` în cadrul metodelor statice. + +Utilizarea proprietăților statice duce la un [cod ofuscat și plin de capcane |dependency-injection:global-state], așa că nu ar trebui să le folosiți niciodată și nu vom arăta un exemplu aici. Pe de altă parte, metodele statice sunt utile. Iată un exemplu: + +```php +class Calculator +{ + public static function add($a, $b) + { + return $a + $b; + } + + public static function subtract($a, $b) + { + return $a - $b; + } +} + +// Using the static method without creating an instance of the class +echo Calculator::add(5, 3); // Output: 8 +echo Calculator::subtract(5, 3); // Output: 2 +``` + +În acest exemplu, am creat o clasă `Calculator` cu două metode statice. Putem apela aceste metode direct fără a crea o instanță a clasei folosind operatorul `::`. Metodele statice sunt utile în special pentru operațiile care nu depind de starea unei instanțe specifice a clasei. + + +Constantele clasei .[#toc-class-constants] +------------------------------------------ + +În cadrul claselor, avem opțiunea de a defini constante. Constantele sunt valori care nu se schimbă niciodată în timpul execuției programului. Spre deosebire de variabile, valoarea unei constante rămâne aceeași. + +```php +class Car +{ + public const NumberOfWheels = 4; + + public function displayNumberOfWheels(): int + { + echo self::NumberOfWheels; + } +} + +echo Car::NumberOfWheels; // Output: 4 +``` + +În acest exemplu, avem o clasă `Car` cu constanta `NumberOfWheels`. Atunci când accesăm constanta în interiorul clasei, putem folosi cuvântul cheie `self` în loc de numele clasei. + + +Interfețe de obiecte .[#toc-object-interfaces] +---------------------------------------------- + +Interfețele de obiect acționează ca "contracte" pentru clase. Dacă o clasă trebuie să implementeze o interfață de obiect, aceasta trebuie să conțină toate metodele definite de interfață. Este o modalitate excelentă de a vă asigura că anumite clase respectă același "contract" sau structură. + +În PHP, interfețele sunt definite cu ajutorul cuvântului cheie `interface`. Toate metodele definite într-o interfață sunt publice (`public`). Atunci când o clasă implementează o interfață, aceasta utilizează cuvântul cheie `implements`. + +```php +interface Animal +{ + function makeSound(); +} + +class Cat implements Animal +{ + public function makeSound() + { + echo 'Meow'; + } +} + +$cat = new Cat; +$cat->makeSound(); +``` + +În cazul în care o clasă implementează o interfață, dar nu sunt definite toate metodele așteptate, PHP va genera o eroare. O clasă poate implementa mai multe interfețe în același timp, ceea ce este diferit de moștenire, unde o clasă poate moșteni doar de la o singură clasă. + + +Clase abstracte .[#toc-abstract-classes] +---------------------------------------- + +Clasele abstracte servesc drept șabloane de bază pentru alte clase, dar nu puteți crea instanțe ale acestora în mod direct. Ele conțin un amestec de metode complete și metode abstracte care nu au un conținut definit. Clasele care moștenesc din clase abstracte trebuie să furnizeze definiții pentru toate metodele abstracte de la părintele lor. + +Utilizăm cuvântul cheie `abstract` pentru a defini o clasă abstractă. + +```php +abstract class AbstractClass +{ + public function regularMethod() + { + echo 'This is a regular method'; + } + + abstract public function abstractMethod(); +} + +class Child extends AbstractClass +{ + public function abstractMethod() + { + echo 'This is the implementation of the abstract method'; + } +} + +$instance = new Child; +$instance->regularMethod(); +$instance->abstractMethod(); +``` + +În acest exemplu, avem o clasă abstractă cu o metodă obișnuită și una abstractă. Apoi avem o clasă `Child` care moștenește din `AbstractClass` și oferă o implementare pentru metoda abstractă. + + +Verificarea tipurilor .[#toc-type-checking] +------------------------------------------- + +În programare, este esențial să ne asigurăm că datele cu care lucrăm sunt de tipul corect. În PHP, dispunem de instrumente care oferă această asigurare. Verificarea faptului că datele sunt de tipul corect se numește "verificare de tip". + +Tipuri pe care le putem întâlni în PHP: + +1. **Tipuri de bază**: Acestea includ `int` (numere întregi), `float` (numere cu virgulă mobilă), `bool` (valori booleene), `string` (șiruri de caractere), `array` (matrice) și `null`. +2. **Classe**: Atunci când dorim ca o valoare să fie o instanță a unei anumite clase. +3. **Interfețe**: Definește un set de metode pe care o clasă trebuie să le implementeze. O valoare care corespunde unei interfețe trebuie să aibă aceste metode. +4. **Tipuri mixte**: Putem specifica faptul că o variabilă poate avea mai multe tipuri permise. +5. **Void**: Acest tip special indică faptul că o funcție sau o metodă nu returnează nicio valoare. + +Să vedem cum să modificăm codul pentru a include tipurile: + +```php +class Person +{ + private int $age; + + public function __construct(int $age) + { + $this->age = $age; + } + + public function printAge(): void + { + echo "This person is " . $this->age . " years old."; + } +} + +/** + * A function that accepts a Person object and prints the person's age. + */ +function printPersonAge(Person $person): void +{ + $person->printAge(); +} +``` + +În acest fel, ne asigurăm că codul nostru așteaptă și lucrează cu date de tipul corect, ceea ce ne ajută să prevenim eventualele erori. + + +Comparație și identitate .[#toc-comparison-and-identity] +-------------------------------------------------------- + +În PHP, puteți compara obiecte în două moduri: + +1. Compararea valorilor `==`: Verifică dacă obiectele sunt din aceeași clasă și au aceleași valori în proprietățile lor. +2. Identitate `===`: Verifică dacă este vorba de aceeași instanță a obiectului. + +```php +class Car +{ + public string $brand; + + public function __construct(string $brand) + { + $this->brand = $brand; + } +} + +$car1 = new Car('Skoda'); +$car2 = new Car('Skoda'); +$car3 = $car1; + +var_dump($car1 == $car2); // true, because they have the same value +var_dump($car1 === $car2); // false, because they are not the same instance +var_dump($car1 === $car3); // true, because $car3 is the same instance as $car1 +``` + + +Operatorul `instanceof` .[#toc-the-instanceof-operator] +------------------------------------------------------- + +Operatorul `instanceof` vă permite să determinați dacă un obiect dat este o instanță a unei anumite clase, un descendent al acelei clase sau dacă implementează o anumită interfață. + +Imaginați-vă că avem o clasă `Person` și o altă clasă `Student`, care este un descendent al `Person`: + +```php +class Person +{ + private int $age; + + public function __construct(int $age) + { + $this->age = $age; + } +} + +class Student extends Person +{ + private string $major; + + public function __construct(int $age, string $major) + { + parent::__construct($age); + $this->major = $major; + } +} + +$student = new Student(20, 'Computer Science'); + +// Check if $student is an instance of the Student class +var_dump($student instanceof Student); // Output: bool(true) + +// Check if $student is an instance of the Person class (because Student is a descendant of Person) +var_dump($student instanceof Person); // Output: bool(true) +``` + +Din rezultatele obținute, este evident că obiectul `$student` este considerat o instanță atât a clasei `Student`, cât și a clasei `Person`. + + +Interfețe fluente .[#toc-fluent-interfaces] +------------------------------------------- + +O "interfață fluidă" este o tehnică din OOP care permite înlănțuirea metodelor într-un singur apel. Acest lucru simplifică și clarifică adesea codul. + +Elementul cheie al unei interfețe fluente este că fiecare metodă din lanț returnează o referință la obiectul curent. Acest lucru se realizează prin utilizarea `return $this;` la sfârșitul metodei. Acest stil de programare este adesea asociat cu metode numite "setters", care stabilesc valorile proprietăților unui obiect. + +Să vedem cum ar putea arăta o interfață fluentă pentru trimiterea de e-mailuri: + +```php +public function sendMessage() +{ + $email = new Email; + $email->setFrom('sender@example.com') + ->setRecipient('admin@example.com') + ->setMessage('Hello, this is a message.') + ->send(); +} +``` + +În acest exemplu, metodele `setFrom()`, `setRecipient()`, și `setMessage()` sunt utilizate pentru a seta valorile corespunzătoare (expeditor, destinatar, conținutul mesajului). După stabilirea fiecăreia dintre aceste valori, metodele returnează obiectul curent (`$email`), permițându-ne să înlănțuim o altă metodă după ea. În cele din urmă, apelăm metoda `send()`, care trimite efectiv e-mailul. + +Datorită interfețelor fluente, putem scrie un cod intuitiv și ușor de citit. + + +Copiere cu `clone` .[#toc-copying-with-clone] +--------------------------------------------- + +În PHP, putem crea o copie a unui obiect folosind operatorul `clone`. În acest fel, obținem o nouă instanță cu conținut identic. + +Dacă avem nevoie să modificăm unele dintre proprietăți atunci când copiem un obiect, putem defini o metodă specială `__clone()` în clasă. Această metodă este apelată automat atunci când obiectul este clonat. + +```php +class Sheep +{ + public string $name; + + public function __construct(string $name) + { + $this->name = $name; + } + + public function __clone() + { + $this->name = 'Clone of ' . $this->name; + } +} + +$original = new Sheep('Dolly'); +echo $original->name . "\n"; // Outputs: Dolly + +$clone = clone $original; +echo $clone->name . "\n"; // Outputs: Clone of Dolly +``` + +În acest exemplu, avem o clasă `Sheep` cu o proprietate `$name`. Atunci când clonăm o instanță a acestei clase, metoda `__clone()` se asigură că numele oii clonate primește prefixul "Clone of". + + +Trăsături .[#toc-traits] +------------------------ + +În PHP, trăsăturile sunt un instrument care permite partajarea metodelor, proprietăților și constantelor între clase și previne duplicarea codului. Vă puteți gândi la ele ca la un mecanism de "copy and paste" (Ctrl-C și Ctrl-V), în care conținutul unei trăsături este "lipit" în clase. Acest lucru vă permite să reutilizați codul fără a fi nevoie să creați ierarhii complicate de clase. + +Să aruncăm o privire la un exemplu simplu de utilizare a trăsăturilor în PHP: + +```php +trait Honking +{ + public function honk() + { + echo 'Beep beep!'; + } +} + +class Car +{ + use Honking; +} + +class Truck +{ + use Honking; +} + +$car = new Car; +$car->honk(); // Outputs 'Beep beep!' + +$truck = new Truck; +$truck->honk(); // Also outputs 'Beep beep!' +``` + +În acest exemplu, avem o trăsătură numită `Honking` care conține o metodă `honk()`. Apoi, avem două clase: `Car` și `Truck`, ambele folosind trăsătura `Honking`. Ca urmare, ambele clase "au" metoda `honk()` și o putem apela pe obiectele ambelor clase. + +Trăsăturile vă permit să partajați ușor și eficient codul între clase. Ele nu intră în ierarhia de moștenire, adică `$car instanceof Honking` va returna `false`. + + +Excepții +-------- + +Excepțiile în OOP ne permit să gestionăm și să tratăm erorile care pot apărea în timpul execuției codului nostru. Ele sunt, în esență, obiecte concepute pentru a înregistra erorile sau situațiile neașteptate din programul dumneavoastră. + +În PHP, avem clasa integrată `Exception` pentru aceste obiecte. Aceasta are mai multe metode care ne permit să obținem mai multe informații despre excepție, cum ar fi mesajul de eroare, fișierul și linia în care a apărut eroarea etc. + +Atunci când apare o problemă, putem "arunca" o excepție (folosind `throw`). Dacă dorim să "capturăm" și să procesăm această excepție, folosim blocurile `try` și `catch`. + +Să vedem cum funcționează: + +```php +try { + throw new Exception('Message explaining the reason for the exception'); + + // This code won't execute + echo 'I am a message that nobody will read'; + +} catch (Exception $e) { + echo 'Exception caught: '. $e->getMessage(); +} +``` + +Este important să rețineți că o excepție poate fi aruncată mai adânc, în timpul apelării altor metode. + +Pentru un singur bloc `try`, pot fi specificate mai multe blocuri `catch` dacă vă așteptați la diferite tipuri de excepții. + +De asemenea, putem crea o ierarhie a excepțiilor, în care fiecare clasă de excepții moștenește din cea anterioară. Ca exemplu, să luăm în considerare o aplicație bancară simplă care permite depuneri și retrageri: + +```php +class BankingException extends Exception {} +class InsufficientFundsException extends BankingException {} +class ExceededLimitException extends BankingException {} + +class BankAccount +{ + private int $balance = 0; + private int $dailyLimit = 1000; + + public function deposit(int $amount): int + { + $this->balance += $amount; + return $this->balance; + } + + public function withdraw(int $amount): int + { + if ($amount > $this->balance) { + throw new InsufficientFundsException('Not enough funds in the account.'); + } + + if ($amount > $this->dailyLimit) { + throw new ExceededLimitException('Daily withdrawal limit exceeded.'); + } + + $this->balance -= $amount; + return $this->balance; + } +} + +$account = new BankAccount; +$account->deposit(500); + +try { + $account->withdraw(1500); +} catch (ExceededLimitException $e) { + echo $e->getMessage(); +} catch (InsufficientFundsException $e) { + echo $e->getMessage(); +} catch (BankingException $e) { + echo 'An error occurred during the operation.'; +} +``` + +În acest exemplu, este important să rețineți ordinea blocurilor `catch`. Deoarece toate excepțiile moștenesc de la `BankingException`, dacă am avea acest bloc primul, toate excepțiile ar fi prinse în el fără ca codul să ajungă la blocurile `catch` ulterioare. Prin urmare, este important ca excepțiile mai specifice (adică cele care moștenesc de la altele) să fie mai sus în ordinea blocului `catch` decât excepțiile părinte. + + +Cele mai bune practici .[#toc-best-practices] +--------------------------------------------- + +Odată ce ați învățat principiile de bază ale programării orientate pe obiecte, este esențial să vă concentrați asupra celor mai bune practici în OOP. Acestea vă vor ajuta să scrieți un cod care să fie nu numai funcțional, ci și ușor de citit, de înțeles și de întreținut. + +1) **Separarea preocupărilor**: Fiecare clasă ar trebui să aibă o responsabilitate clar definită și ar trebui să abordeze doar o singură sarcină principală. Dacă o clasă face prea multe lucruri, ar putea fi indicat să o împărțiți în clase mai mici, specializate. +2) **Încapsularea**: Datele și metodele ar trebui să fie cât mai ascunse posibil și să fie accesibile numai printr-o interfață definită. Acest lucru vă permite să modificați implementarea internă a unei clase fără a afecta restul codului. +3) **Injectarea dependenței**: În loc să creați dependențe direct în interiorul unei clase, ar trebui să le "injectați" din exterior. Pentru o înțelegere mai profundă a acestui principiu, vă recomandăm [capitolele despre Injecția de dependență |dependency-injection:introduction]. diff --git a/nette/ru/introduction-to-object-oriented-programming.texy b/nette/ru/introduction-to-object-oriented-programming.texy new file mode 100644 index 0000000000..d79be5714a --- /dev/null +++ b/nette/ru/introduction-to-object-oriented-programming.texy @@ -0,0 +1,719 @@ +Введение в объектно-ориентированное программирование +**************************************************** + +.[perex] +Термин "ООП" означает объектно-ориентированное программирование - способ организации и структурирования кода. ООП позволяет рассматривать программу не как последовательность команд и функций, а как набор объектов, взаимодействующих друг с другом. + +В ООП "объект" - это единица, содержащая данные и функции, которые оперируют этими данными. Объекты создаются на основе "классов", которые можно понимать как чертежи или шаблоны объектов. Имея класс, мы можем создать его "экземпляр", то есть конкретный объект, созданный на основе этого класса. + +Рассмотрим, как можно создать простой класс в PHP. При определении класса используется ключевое слово "class", за которым следует имя класса, а затем фигурные скобки, в которые заключаются функции класса (называемые "методами") и переменные класса (называемые "свойствами" или "атрибутами"): + +```php +class Car +{ + function honk() + { + echo 'Beep beep!'; + } +} +``` + +В данном примере мы создали класс `Car` с одной функцией (или "методом") `honk`. + +Каждый класс должен решать только одну основную задачу. Если класс решает слишком много задач, то целесообразно разделить его на более мелкие, специализированные классы. + +Классы обычно хранятся в отдельных файлах, что позволяет упорядочить код и облегчить навигацию по нему. Имя файла должно совпадать с именем класса, поэтому для класса `Car` имя файла будет `Car.php`. + +При именовании классов следует придерживаться правила "PascalCase", то есть каждое слово в имени начинается с заглавной буквы, без подчеркиваний и других разделителей. Методы и свойства следует называть в "camelCase", то есть со строчной буквы. + +Некоторые методы в PHP играют особую роль и имеют префикс `__` (два знака подчеркивания). Одним из наиболее важных специальных методов является "конструктор", обозначаемый как `__construct`. Конструктор - это метод, который автоматически вызывается при создании нового экземпляра класса. + +Мы часто используем конструктор для установки начального состояния объекта. Например, при создании объекта, представляющего человека, с помощью конструктора можно задать его возраст, имя или другие атрибуты. + +Рассмотрим, как использовать конструктор в PHP: + +```php +class Person +{ + private $age; + + function __construct($age) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +$person = new Person(25); +echo $person->howOldAreYou(); // Outputs: 25 +``` + +В данном примере класс `Person` имеет свойство `$age` и конструктор, который устанавливает это свойство. Затем метод `howOldAreYou()` предоставляет доступ к возрасту человека. + +Ключевое слово `new` используется для создания нового экземпляра класса. В приведенном примере мы создали нового человека в возрасте 25 лет. + +Также можно задать значения по умолчанию для параметров конструктора, если они не указаны при создании объекта. Например: + +```php +class Person +{ + private $age; + + function __construct($age = 20) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +$person = new Person; // if no argument is passed, parentheses can be omitted +echo $person->howOldAreYou(); // Outputs: 20 +``` + +В данном примере, если при создании объекта `Person` не указать возраст, будет использовано значение по умолчанию 20. + +Наконец, определение свойства с его инициализацией через конструктор можно сократить и упростить следующим образом: + +```php +class Person +{ + function __construct( + private $age = 20, + ) { + } +} +``` + + +Пространства имен .[#toc-namespaces] +------------------------------------ + +Пространства имен позволяют упорядочить и сгруппировать связанные классы, функции и константы, избегая при этом конфликтов имен. Их можно представить себе как папки на компьютере, где каждая папка содержит файлы, относящиеся к определенному проекту или теме. + +Пространства имен особенно полезны в больших проектах или при использовании сторонних библиотек, где могут возникать конфликты в наименованиях классов. + +Представьте, что в вашем проекте есть класс с именем `Car`, и вы хотите поместить его в пространство имен `Transport`. Это можно сделать следующим образом: + +```php +namespace Transport; + +class Car +{ + function honk() + { + echo 'Beep beep!'; + } +} +``` + +Если вы хотите использовать класс `Car` в другом файле, то вам необходимо указать, из какого пространства имен он происходит: + +```php +$car = new Transport\Car; +``` + +Для упрощения можно указать в начале файла, какой класс из того или иного пространства имен вы хотите использовать, что позволит создавать экземпляры без указания полного пути: + +```php +use Transport\Car; + +$car = new Car; +``` + + +Наследование .[#toc-inheritance] +-------------------------------- + +Наследование - это инструмент объектно-ориентированного программирования, позволяющий создавать новые классы на основе существующих, наследуя их свойства и методы, а также расширяя или переопределяя их по мере необходимости. Наследование обеспечивает многократное использование кода и иерархию классов. + +Проще говоря, если у нас есть один класс и мы хотим создать другой, производный от него, но с некоторыми изменениями, то мы можем "унаследовать" новый класс от исходного. + +В PHP наследование реализуется с помощью ключевого слова `extends`. + +Наш класс `Person` хранит информацию о возрасте. Мы можем иметь другой класс, `Student`, который расширяет `Person` и добавляет информацию о специальности. + +Рассмотрим пример: + +```php +class Person +{ + private $age; + + function __construct($age) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +class Student extends Person +{ + private $fieldOfStudy; + + function __construct($age, $fieldOfStudy) + { + parent::__construct($age); + $this->fieldOfStudy = $fieldOfStudy; + } + + function printInformation() + { + echo 'Age of student: ', $this->howOldAreYou(); + echo 'Field of study: ', $this->fieldOfStudy; + } +} + +$student = new Student(20, 'Computer Science'); +$student->printInformation(); +``` + +Как работает этот код? + +- Мы использовали ключевое слово `extends` для расширения класса `Person`, то есть класс `Student` наследует все методы и свойства от `Person`. + +- Ключевое слово `parent::` позволяет нам вызывать методы из родительского класса. В данном случае мы вызвали конструктор из класса `Person`, а затем добавили собственную функциональность в класс `Student`. + +Наследование предназначено для ситуаций, когда между классами существует связь "есть". Например, `Student` - это `Person`. Кошка - это животное. Это позволяет нам в случаях, когда в коде ожидается один объект (например, "Person"), использовать вместо него производный объект (например, "Student"). + +Важно понимать, что основная цель наследования **не** заключается в предотвращении дублирования кода. Напротив, неправильное использование наследования может привести к появлению сложного и трудноразрешимого кода. Если между классами нет отношения "является", то вместо наследования следует рассмотреть композицию. + + +Композиция .[#toc-composition] +------------------------------ + +Композиция - это техника, при которой вместо наследования свойств и методов другого класса мы просто используем его экземпляр в своем классе. Это позволяет объединить функциональные возможности и свойства нескольких классов без создания сложных структур наследования. + +Например, у нас есть класс `Engine` и класс `Car`. Вместо того чтобы сказать "Автомобиль - это двигатель", мы говорим "Автомобиль имеет двигатель", что является типичным композиционным отношением. + +```php +class Engine +{ + function start() + { + echo "Engine is running."; + } +} + +class Car +{ + private $engine; + + function __construct() + { + $this->engine = new Engine; + } + + function start() + { + $this->engine->start(); + echo "The car is ready to drive!"; + } +} + +$car = new Car; +$car->start(); +``` + +Здесь `Car` не имеет всех свойств и методов `Engine`, но имеет доступ к ним через свойство `$engine`. + +Преимуществом композиции является большая гибкость проектирования и лучшая адаптируемость к будущим изменениям. + + +Наглядность .[#toc-visibility] +------------------------------ + +В PHP можно определить "видимость" для свойств, методов и констант класса. Видимость определяет, где можно получить доступ к этим элементам. + +1. **Public:** Если элемент помечен как `public`, это означает, что вы можете получить к нему доступ из любого места, даже за пределами класса. + +2. **Защищенный:** Элемент, помеченный как `protected`, доступен только в пределах данного класса и всех его потомков (классов, наследующих от него). + +3. **Private:** Если элемент помечен как `private`, то доступ к нему возможен только из класса, в котором он был определен. + +Если не указать значение видимости, PHP автоматически установит его равным `public`. + +Рассмотрим пример кода: + +```php +class VisibilityExample +{ + public $publicProperty = 'Public'; + protected $protectedProperty = 'Protected'; + private $privateProperty = 'Private'; + + public function printProperties() + { + echo $this->publicProperty; // Works + echo $this->protectedProperty; // Works + echo $this->privateProperty; // Works + } +} + +$object = new VisibilityExample; +$object->printProperties(); +echo $object->publicProperty; // Works +// echo $object->protectedProperty; // Throws an error +// echo $object->privateProperty; // Throws an error +``` + +Продолжаем наследование классов: + +```php +class ChildClass extends VisibilityExample +{ + public function printProperties() + { + echo $this->publicProperty; // Works + echo $this->protectedProperty; // Works + // echo $this->privateProperty; // Throws an error + } +} +``` + +В данном случае метод `printProperties()` в `ChildClass` может получить доступ к публичным и защищенным свойствам, но не может получить доступ к приватным свойствам родительского класса. + +Данные и методы должны быть максимально скрыты и доступны только через определенный интерфейс. Это позволяет изменять внутреннюю реализацию класса, не затрагивая остальной части кода. + + +Ключевое слово final .[#toc-final-keyword] +------------------------------------------ + +В PHP мы можем использовать ключевое слово `final`, если хотим запретить наследование или переопределение класса, метода или константы. Если класс помечен как `final`, он не может быть расширен. Если метод помечен как `final`, он не может быть переопределен в подклассе. + +Знание того, что определенный класс или метод больше не будет модифицироваться, позволяет нам легче вносить изменения, не беспокоясь о возможных конфликтах. Например, мы можем добавить новый метод, не опасаясь, что у потомка уже есть метод с таким же именем, что приведет к коллизии. Или мы можем изменить параметры метода, опять же не опасаясь, что это приведет к несоответствию с переопределенным методом потомка. + +```php +final class FinalClass +{ +} + +// The following code will throw an error because we cannot inherit from a final class. +class ChildOfFinalClass extends FinalClass +{ +} +``` + +В данном примере попытка наследоваться от конечного класса `FinalClass` приведет к ошибке. + + +Статические свойства и методы .[#toc-static-properties-and-methods] +------------------------------------------------------------------- + +Когда мы говорим о "статических" элементах класса в PHP, мы имеем в виду методы и свойства, которые принадлежат самому классу, а не его конкретному экземпляру. Это означает, что для доступа к ним не нужно создавать экземпляр класса. Вместо этого вы вызываете или обращаетесь к ним непосредственно через имя класса. + +Следует помнить, что поскольку статические элементы принадлежат классу, а не его экземплярам, то внутри статических методов нельзя использовать псевдопеременную `$this`. + +Использование статических свойств приводит к [обфусцированному коду, полному подводных камней |dependency-injection:global-state], поэтому их никогда не следует использовать, и мы не будем приводить здесь пример. С другой стороны, статические методы полезны. Вот пример: + +```php +class Calculator +{ + public static function add($a, $b) + { + return $a + $b; + } + + public static function subtract($a, $b) + { + return $a - $b; + } +} + +// Using the static method without creating an instance of the class +echo Calculator::add(5, 3); // Output: 8 +echo Calculator::subtract(5, 3); // Output: 2 +``` + +В этом примере мы создали класс `Calculator` с двумя статическими методами. Мы можем вызывать эти методы напрямую, не создавая экземпляр класса, используя оператор `::`. Статические методы особенно полезны для операций, которые не зависят от состояния конкретного экземпляра класса. + + +Константы класса .[#toc-class-constants] +---------------------------------------- + +Внутри классов мы имеем возможность определять константы. Константы - это значения, которые никогда не изменяются в процессе выполнения программы. В отличие от переменных, значение константы остается неизменным. + +```php +class Car +{ + public const NumberOfWheels = 4; + + public function displayNumberOfWheels(): int + { + echo self::NumberOfWheels; + } +} + +echo Car::NumberOfWheels; // Output: 4 +``` + +В данном примере мы имеем класс `Car` с константой `NumberOfWheels`. При обращении к константе внутри класса мы можем использовать ключевое слово `self` вместо имени класса. + + +Объектные интерфейсы .[#toc-object-interfaces] +---------------------------------------------- + +Объектные интерфейсы выступают в роли "контрактов" для классов. Если класс должен реализовать объектный интерфейс, то он должен содержать все методы, определяемые интерфейсом. Это отличный способ гарантировать, что определенные классы придерживаются одного и того же "контракта" или структуры. + +В PHP интерфейсы определяются с помощью ключевого слова `interface`. Все методы, определенные в интерфейсе, являются публичными (`public`). Когда класс реализует интерфейс, он использует ключевое слово `implements`. + +```php +interface Animal +{ + function makeSound(); +} + +class Cat implements Animal +{ + public function makeSound() + { + echo 'Meow'; + } +} + +$cat = new Cat; +$cat->makeSound(); +``` + +Если класс реализует интерфейс, но не все ожидаемые методы определены, то PHP выдаст ошибку. Класс может реализовывать несколько интерфейсов одновременно, что отличается от наследования, при котором класс может наследоваться только от одного класса. + + +Абстрактные классы .[#toc-abstract-classes] +------------------------------------------- + +Абстрактные классы служат базовыми шаблонами для других классов, но их экземпляры нельзя создавать напрямую. Они содержат смесь полных методов и абстрактных методов, которые не имеют определенного содержания. Классы, наследующие от абстрактных классов, должны предоставлять определения для всех абстрактных методов родительского класса. + +Для определения абстрактного класса мы используем ключевое слово `abstract`. + +```php +abstract class AbstractClass +{ + public function regularMethod() + { + echo 'This is a regular method'; + } + + abstract public function abstractMethod(); +} + +class Child extends AbstractClass +{ + public function abstractMethod() + { + echo 'This is the implementation of the abstract method'; + } +} + +$instance = new Child; +$instance->regularMethod(); +$instance->abstractMethod(); +``` + +В данном примере мы имеем абстрактный класс с одним обычным и одним абстрактным методом. Затем у нас есть класс `Child`, который наследуется от `AbstractClass` и предоставляет реализацию абстрактного метода. + + +Проверка типа .[#toc-type-checking] +----------------------------------- + +В программировании очень важно убедиться в том, что данные, с которыми мы работаем, имеют правильный тип. В PHP есть инструменты, позволяющие обеспечить такую гарантию. Проверка правильности типа данных называется "проверкой типа". + +Типы, с которыми мы можем столкнуться в PHP: + +1. **Базовые типы**: К ним относятся `int` (целые числа), `float` (числа с плавающей точкой), `bool` (булевы значения), `string` (строки), `array` (массивы) и `null`. +2. **Классы**: Когда мы хотим, чтобы значение было экземпляром определенного класса. +3. **Интерфейсы**: Определяют набор методов, которые должен реализовать класс. Значение, удовлетворяющее интерфейсу, должно обладать этими методами. +4. **Смешанные типы**: Мы можем указать, что переменная может иметь несколько допустимых типов. +5. **Void**: Этот специальный тип указывает на то, что функция или метод не возвращает никакого значения. + +Рассмотрим, как модифицировать код для включения типов: + +```php +class Person +{ + private int $age; + + public function __construct(int $age) + { + $this->age = $age; + } + + public function printAge(): void + { + echo "This person is " . $this->age . " years old."; + } +} + +/** + * A function that accepts a Person object and prints the person's age. + */ +function printPersonAge(Person $person): void +{ + $person->printAge(); +} +``` + +Таким образом, мы гарантируем, что наш код ожидает и работает с данными правильного типа, что помогает нам предотвратить возможные ошибки. + + +Сравнение и идентичность .[#toc-comparison-and-identity] +-------------------------------------------------------- + +В PHP можно сравнивать объекты двумя способами: + +1. Сравнение по значению `==`: проверяется, относятся ли объекты к одному классу и имеют ли они одинаковые значения в своих свойствах. +2. Идентичность `===`: Проверяет, является ли объект одним и тем же экземпляром. + +```php +class Car +{ + public string $brand; + + public function __construct(string $brand) + { + $this->brand = $brand; + } +} + +$car1 = new Car('Skoda'); +$car2 = new Car('Skoda'); +$car3 = $car1; + +var_dump($car1 == $car2); // true, because they have the same value +var_dump($car1 === $car2); // false, because they are not the same instance +var_dump($car1 === $car3); // true, because $car3 is the same instance as $car1 +``` + + +Оператор `instanceof` .[#toc-the-instanceof-operator] +----------------------------------------------------- + +Оператор `instanceof` позволяет определить, является ли данный объект экземпляром определенного класса, потомком этого класса или реализует ли он определенный интерфейс. + +Представьте, что у нас есть класс `Person` и другой класс `Student`, который является потомком `Person`: + +```php +class Person +{ + private int $age; + + public function __construct(int $age) + { + $this->age = $age; + } +} + +class Student extends Person +{ + private string $major; + + public function __construct(int $age, string $major) + { + parent::__construct($age); + $this->major = $major; + } +} + +$student = new Student(20, 'Computer Science'); + +// Check if $student is an instance of the Student class +var_dump($student instanceof Student); // Output: bool(true) + +// Check if $student is an instance of the Person class (because Student is a descendant of Person) +var_dump($student instanceof Person); // Output: bool(true) +``` + +Из выводов видно, что объект `$student` считается экземпляром обоих классов `Student` и `Person`. + + +Текучие интерфейсы .[#toc-fluent-interfaces] +-------------------------------------------- + +Fluent Interface" - это техника в ООП, позволяющая объединять методы в цепочку одним вызовом. Это часто упрощает и уточняет код. + +Ключевым элементом флюентного интерфейса является то, что каждый метод в цепочке возвращает ссылку на текущий объект. Это достигается за счет использования `return $this;` в конце метода. Такой стиль программирования часто ассоциируется с методами, называемыми "сеттерами", которые устанавливают значения свойств объекта. + +Давайте посмотрим, как может выглядеть свободный интерфейс для отправки электронной почты: + +```php +public function sendMessage() +{ + $email = new Email; + $email->setFrom('sender@example.com') + ->setRecipient('admin@example.com') + ->setMessage('Hello, this is a message.') + ->send(); +} +``` + +В данном примере методы `setFrom()`, `setRecipient()` и `setMessage()` используются для установки соответствующих значений (отправитель, получатель, содержание сообщения). После установки каждого из этих значений методы возвращают текущий объект (`$email`), что позволяет выстроить после него цепочку других методов. Наконец, мы вызываем метод `send()`, который, собственно, и отправляет письмо. + +Благодаря свободным интерфейсам мы можем писать интуитивно понятный и легко читаемый код. + + +Копирование с помощью `clone` .[#toc-copying-with-clone] +-------------------------------------------------------- + +В PHP мы можем создать копию объекта с помощью оператора `clone`. Таким образом, мы получаем новый экземпляр с идентичным содержимым. + +Если при копировании объекта нам необходимо изменить некоторые его свойства, мы можем определить в классе специальный метод `__clone()`. Этот метод автоматически вызывается при клонировании объекта. + +```php +class Sheep +{ + public string $name; + + public function __construct(string $name) + { + $this->name = $name; + } + + public function __clone() + { + $this->name = 'Clone of ' . $this->name; + } +} + +$original = new Sheep('Dolly'); +echo $original->name . "\n"; // Outputs: Dolly + +$clone = clone $original; +echo $clone->name . "\n"; // Outputs: Clone of Dolly +``` + +В данном примере мы имеем класс `Sheep` с одним свойством `$name`. Когда мы клонируем экземпляр этого класса, метод `__clone()` гарантирует, что имя клонированной овцы получит префикс "Clone of". + + +Свойства .[#toc-traits] +----------------------- + +Трейты в PHP - это инструмент, позволяющий совместно использовать методы, свойства и константы между классами и предотвращающий дублирование кода. Их можно рассматривать как механизм "копирования и вставки" (Ctrl-C и Ctrl-V), когда содержимое трейта "вставляется" в классы. Это позволяет повторно использовать код без создания сложных иерархий классов. + +Рассмотрим простой пример использования трейтов в PHP: + +```php +trait Honking +{ + public function honk() + { + echo 'Beep beep!'; + } +} + +class Car +{ + use Honking; +} + +class Truck +{ + use Honking; +} + +$car = new Car; +$car->honk(); // Outputs 'Beep beep!' + +$truck = new Truck; +$truck->honk(); // Also outputs 'Beep beep!' +``` + +В этом примере у нас есть тред `Honking`, содержащий один метод `honk()`. Затем у нас есть два класса: `Car` и `Truck`, оба из которых используют признак `Honking`. В результате оба класса "имеют" метод `honk()`, и мы можем вызывать его на объектах обоих классов. + +Трейты позволяют легко и эффективно обмениваться кодом между классами. Они не входят в иерархию наследования, т.е. `$car instanceof Honking` вернет `false`. + + +Исключения +---------- + +Исключения в ООП позволяют обрабатывать и управлять ошибками, которые могут возникнуть в процессе выполнения кода. По сути, это объекты, предназначенные для регистрации ошибок или неожиданных ситуаций в вашей программе. + +В PHP для таких объектов существует встроенный класс `Exception`. Он имеет несколько методов, позволяющих получить дополнительную информацию об исключении, например, сообщение об ошибке, файл, строку, в которой произошла ошибка, и т.д. + +При возникновении проблемы мы можем "выбросить" исключение (используя `throw`). Если мы хотим "поймать" и обработать это исключение, мы используем блоки `try` и `catch`. + +Давайте посмотрим, как это работает: + +```php +try { + throw new Exception('Message explaining the reason for the exception'); + + // This code won't execute + echo 'I am a message that nobody will read'; + +} catch (Exception $e) { + echo 'Exception caught: '. $e->getMessage(); +} +``` + +Важно отметить, что исключение может быть выброшено и глубже, во время вызова других методов. + +Для одного блока `try` можно указать несколько блоков `catch`, если ожидаются различные типы исключений. + +Можно также создать иерархию исключений, в которой каждый класс исключений наследуется от предыдущего. В качестве примера рассмотрим простое банковское приложение, позволяющее вносить и снимать деньги: + +```php +class BankingException extends Exception {} +class InsufficientFundsException extends BankingException {} +class ExceededLimitException extends BankingException {} + +class BankAccount +{ + private int $balance = 0; + private int $dailyLimit = 1000; + + public function deposit(int $amount): int + { + $this->balance += $amount; + return $this->balance; + } + + public function withdraw(int $amount): int + { + if ($amount > $this->balance) { + throw new InsufficientFundsException('Not enough funds in the account.'); + } + + if ($amount > $this->dailyLimit) { + throw new ExceededLimitException('Daily withdrawal limit exceeded.'); + } + + $this->balance -= $amount; + return $this->balance; + } +} + +$account = new BankAccount; +$account->deposit(500); + +try { + $account->withdraw(1500); +} catch (ExceededLimitException $e) { + echo $e->getMessage(); +} catch (InsufficientFundsException $e) { + echo $e->getMessage(); +} catch (BankingException $e) { + echo 'An error occurred during the operation.'; +} +``` + +В этом примере важно обратить внимание на порядок следования блоков `catch`. Поскольку все исключения наследуются от `BankingException`, то если бы этот блок был первым, то все исключения были бы пойманы в нем, а код не дошел бы до последующих блоков `catch`. Поэтому важно, чтобы более специфические исключения (т.е. те, которые наследуются от других) располагались выше в порядке блоков `catch`, чем их родительские исключения. + + +Лучшие практики .[#toc-best-practices] +-------------------------------------- + +После того как вы освоили основные принципы объектно-ориентированного программирования, необходимо обратить внимание на лучшие практики ООП. Это поможет вам писать не только функциональный, но и читабельный, понятный и легко сопровождаемый код. + +1) **Разделение обязанностей**: Каждый класс должен иметь четко определенную ответственность и решать только одну основную задачу. Если класс выполняет слишком много задач, то целесообразно разделить его на более мелкие специализированные классы. +2) **Инкапсуляция**: Данные и методы должны быть максимально скрыты и доступны только через определенный интерфейс. Это позволяет изменять внутреннюю реализацию класса, не затрагивая остальной код. +3) **Инъекция зависимостей**: Вместо того чтобы создавать зависимости непосредственно внутри класса, следует "инжектировать" их извне. Для более глубокого понимания этого принципа мы рекомендуем [главы, посвященные Dependency Injection |dependency-injection:introduction]. diff --git a/nette/sl/introduction-to-object-oriented-programming.texy b/nette/sl/introduction-to-object-oriented-programming.texy new file mode 100644 index 0000000000..b322b6dd76 --- /dev/null +++ b/nette/sl/introduction-to-object-oriented-programming.texy @@ -0,0 +1,719 @@ +Uvod v objektno usmerjeno programiranje +*************************************** + +.[perex] +Izraz "OOP" pomeni objektno usmerjeno programiranje, ki je način organiziranja in strukturiranja kode. OOP nam omogoča, da na program gledamo kot na zbirko predmetov, ki med seboj komunicirajo, in ne kot na zaporedje ukazov in funkcij. + +V OOP je "objekt" enota, ki vsebuje podatke in funkcije, ki delujejo na teh podatkih. Objekti so ustvarjeni na podlagi "razredov", ki jih lahko razumemo kot načrte ali predloge za objekte. Ko imamo razred, lahko ustvarimo njegov "primerek", ki je poseben objekt, narejen iz tega razreda. + +Oglejmo si, kako lahko ustvarimo preprost razred v PHP. Pri definiranju razreda uporabimo ključno besedo "class", ki ji sledi ime razreda, nato pa še oglati oklepaji, ki zapirajo funkcije razreda (imenovane "metode") in spremenljivke razreda (imenovane "lastnosti" ali "atributi"): + +```php +class Car +{ + function honk() + { + echo 'Beep beep!'; + } +} +``` + +V tem primeru smo ustvarili razred z imenom `Car` z eno funkcijo (ali "metodo") z imenom `honk`. + +Vsak razred mora rešiti le eno glavno nalogo. Če razred opravlja preveč stvari, ga je morda primerno razdeliti na manjše, specializirane razrede. + +Razredi so običajno shranjeni v ločenih datotekah, da bi bila koda urejena in bi bilo po njej lažje krmariti. Ime datoteke se mora ujemati z imenom razreda, tako da bi bilo ime datoteke za razred `Car` `Car.php` . + +Pri poimenovanju razredov je dobro upoštevati konvencijo "PascalCase", kar pomeni, da se vsaka beseda v imenu začne z veliko črko in ni podčrtank ali drugih ločil. Za metode in lastnosti velja konvencija "camelCase", kar pomeni, da se začnejo z malo črko. + +Nekatere metode v PHP imajo posebne vloge in imajo predpono `__` (dva podčrtaja). Ena najpomembnejših posebnih metod je "konstruktor", ki je označen kot `__construct`. Konstruktor je metoda, ki se samodejno pokliče pri ustvarjanju novega primerka razreda. + +Konstruktor pogosto uporabljamo za določanje začetnega stanja predmeta. Na primer, ko ustvarjate objekt, ki predstavlja osebo, lahko konstruktor uporabite za nastavitev njene starosti, imena ali drugih atributov. + +Oglejmo si, kako uporabiti konstruktor v PHP: + +```php +class Person +{ + private $age; + + function __construct($age) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +$person = new Person(25); +echo $person->howOldAreYou(); // Outputs: 25 +``` + +V tem primeru ima razred `Person` lastnost `$age` in konstruktor, ki to lastnost nastavi. Metoda `howOldAreYou()` nato omogoča dostop do starosti osebe. + +Ključna beseda `new` se uporablja za ustvarjanje novega primerka razreda. V zgornjem primeru smo ustvarili novo osebo, staro 25 let. + +Nastavite lahko tudi privzete vrednosti za parametre konstruktorja, če niso določeni pri ustvarjanju predmeta. Na primer: + +```php +class Person +{ + private $age; + + function __construct($age = 20) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +$person = new Person; // if no argument is passed, parentheses can be omitted +echo $person->howOldAreYou(); // Outputs: 20 +``` + +Če pri ustvarjanju predmeta `Person` ne določite starosti, bo uporabljena privzeta vrednost 20. + +Nazadnje lahko opredelitev lastnosti z njeno inicializacijo prek konstruktorja skrajšate in poenostavite na naslednji način: + +```php +class Person +{ + function __construct( + private $age = 20, + ) { + } +} +``` + + +Prostori imen .[#toc-namespaces] +-------------------------------- + +Prostori imen nam omogočajo organiziranje in združevanje sorodnih razredov, funkcij in konstant, pri čemer se izognemo konfliktom pri poimenovanju. Predstavljamo si jih lahko kot mape v računalniku, kjer vsaka mapa vsebuje datoteke, povezane z določenim projektom ali temo. + +Prostori imen so še posebej uporabni v večjih projektih ali pri uporabi knjižnic tretjih oseb, kjer lahko pride do sporov v poimenovanju razredov. + +Predstavljajte si, da imate v svojem projektu razred z imenom `Car` in ga želite postaviti v imenski prostor z imenom `Transport`. To bi storili takole: + +```php +namespace Transport; + +class Car +{ + function honk() + { + echo 'Beep beep!'; + } +} +``` + +Če želite razred `Car` uporabiti v drugi datoteki, morate navesti, iz katerega imenskega prostora razred izhaja: + +```php +$car = new Transport\Car; +``` + +Za poenostavitev lahko na začetku datoteke navedete, kateri razred iz določenega imenskega prostora želite uporabiti, kar vam omogoča ustvarjanje primerkov brez navajanja celotne poti: + +```php +use Transport\Car; + +$car = new Car; +``` + + +Dedovanje .[#toc-inheritance] +----------------------------- + +Dedovanje je orodje objektno usmerjenega programiranja, ki omogoča ustvarjanje novih razredov na podlagi obstoječih, dedovanje njihovih lastnosti in metod ter njihovo razširitev ali redefiniranje po potrebi. Dedovanje zagotavlja ponovno uporabnost kode in hierarhijo razredov. + +Preprosto povedano, če imamo en razred in želimo ustvariti drugega, ki izhaja iz njega, vendar z nekaterimi spremembami, lahko novi razred "podedujemo" od prvotnega. + +V jeziku PHP se dedovanje izvaja s ključno besedo `extends`. + +Naš razred `Person` shranjuje informacije o starosti. Imamo lahko še en razred, `Student`, ki razširja `Person` in dodaja informacije o področju študija. + +Oglejmo si primer: + +```php +class Person +{ + private $age; + + function __construct($age) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +class Student extends Person +{ + private $fieldOfStudy; + + function __construct($age, $fieldOfStudy) + { + parent::__construct($age); + $this->fieldOfStudy = $fieldOfStudy; + } + + function printInformation() + { + echo 'Age of student: ', $this->howOldAreYou(); + echo 'Field of study: ', $this->fieldOfStudy; + } +} + +$student = new Student(20, 'Computer Science'); +$student->printInformation(); +``` + +Kako deluje ta koda? + +- S ključno besedo `extends` smo razširili razred `Person`, kar pomeni, da razred `Student` podeduje vse metode in lastnosti od razreda `Person`. + +- Ključna beseda `parent::` nam omogoča, da kličemo metode iz nadrejenega razreda. V tem primeru smo poklicali konstruktor iz razreda `Person`, preden smo v razred `Student` dodali svojo funkcionalnost. + +Dedovanje je namenjeno situacijam, v katerih med razredi obstaja razmerje "is a". Na primer, razred `Student` je razred `Person`. Mačka je žival. Omogoča nam, da v primerih, ko v kodi pričakujemo en objekt (npr. "Oseba"), namesto njega uporabimo izpeljani objekt (npr. "Študent"). + +Bistveno se je zavedati, da glavni namen dedovanja **ni** preprečevanje podvajanja kode. Ravno nasprotno, napačna uporaba dedovanja lahko privede do zapletene in težko vzdrževane kode. Če med razredi ni razmerja "je a", moramo namesto dedovanja razmisliti o kompoziciji. + + +Sestavljanje .[#toc-composition] +-------------------------------- + +Kompozicija je tehnika, pri kateri namesto dedovanja lastnosti in metod iz drugega razreda preprosto uporabimo njegov primerek v svojem razredu. Tako lahko združimo funkcionalnosti in lastnosti več razredov, ne da bi ustvarjali zapletene strukture dedovanja. + +Na primer, imamo razred `Engine` in razred `Car`. Namesto da bi rekli "Avto je motor", rečemo "Avto ima motor", kar je tipično kompozicijsko razmerje. + +```php +class Engine +{ + function start() + { + echo "Engine is running."; + } +} + +class Car +{ + private $engine; + + function __construct() + { + $this->engine = new Engine; + } + + function start() + { + $this->engine->start(); + echo "The car is ready to drive!"; + } +} + +$car = new Car; +$car->start(); +``` + +V tem primeru razred `Car` nima vseh lastnosti in metod razreda `Engine`, vendar ima do njih dostop prek lastnosti razreda `$engine`. + +Prednost sestave je večja prilagodljivost načrtovanja in boljša prilagodljivost za prihodnje spremembe. + + +Vidnost .[#toc-visibility] +-------------------------- + +V jeziku PHP lahko za lastnosti, metode in konstante razreda določite vidnost. Vidnost določa, kje lahko dostopate do teh elementov. + +1. **Public:** Če je element označen kot `public`, to pomeni, da lahko do njega dostopate od koder koli, tudi zunaj razreda. + +2. **Zaščiten:** Element, označen kot `protected`, je dostopen le znotraj razreda in vseh njegovih potomcev (razredov, ki dedujejo od njega). + +3. **Zasebno:** Če je element označen kot `private`, lahko do njega dostopate le znotraj razreda, v katerem je bil opredeljen. + +Če ne določite vidnosti, PHP samodejno nastavi vidnost na `public`. + +Oglejmo si vzorec kode: + +```php +class VisibilityExample +{ + public $publicProperty = 'Public'; + protected $protectedProperty = 'Protected'; + private $privateProperty = 'Private'; + + public function printProperties() + { + echo $this->publicProperty; // Works + echo $this->protectedProperty; // Works + echo $this->privateProperty; // Works + } +} + +$object = new VisibilityExample; +$object->printProperties(); +echo $object->publicProperty; // Works +// echo $object->protectedProperty; // Throws an error +// echo $object->privateProperty; // Throws an error +``` + +Nadaljujemo z dedovanjem razredov: + +```php +class ChildClass extends VisibilityExample +{ + public function printProperties() + { + echo $this->publicProperty; // Works + echo $this->protectedProperty; // Works + // echo $this->privateProperty; // Throws an error + } +} +``` + +V tem primeru lahko metoda `printProperties()` v razredu `ChildClass` dostopa do javnih in zaščitenih lastnosti, ne more pa dostopati do zasebnih lastnosti nadrejenega razreda. + +Podatki in metode morajo biti čim bolj skriti in dostopni le prek določenega vmesnika. Tako lahko spremenite notranjo implementacijo razreda, ne da bi to vplivalo na preostalo kodo. + + +Končna ključna beseda .[#toc-final-keyword] +------------------------------------------- + +V jeziku PHP lahko ključno besedo `final` uporabimo, če želimo preprečiti, da bi razred, metodo ali konstanto podedovali ali prepisali. Če je razred označen kot `final`, ga ni mogoče razširiti. Če je metoda označena kot `final`, je ni mogoče prepisati v podrazredu. + +Če se zavedamo, da določenega razreda ali metode ne bomo več spreminjali, lahko lažje izvajamo spremembe, ne da bi nas skrbelo za morebitne konflikte. Tako lahko na primer dodamo novo metodo, ne da bi se bali, da ima potomec že metodo z istim imenom, kar bi povzročilo kolizijo. Ali pa lahko spremenimo parametre metode, spet brez tveganja, da bi povzročili neskladje s prepisano metodo v potomcu. + +```php +final class FinalClass +{ +} + +// The following code will throw an error because we cannot inherit from a final class. +class ChildOfFinalClass extends FinalClass +{ +} +``` + +V tem primeru bo poskus dedovanja iz končnega razreda `FinalClass` povzročil napako. + + +Statične lastnosti in metode .[#toc-static-properties-and-methods] +------------------------------------------------------------------ + +Ko v jeziku PHP govorimo o "statičnih" elementih razreda, imamo v mislih metode in lastnosti, ki pripadajo samemu razredu in ne določenemu primerku razreda. To pomeni, da vam za dostop do njih ni treba ustvariti primerka razreda. Namesto tega jih pokličete ali do njih dostopate neposredno prek imena razreda. + +Upoštevajte, da ker statični elementi pripadajo razredu in ne njegovim instancam, znotraj statičnih metod ne morete uporabljati psevdo-premenljivke `$this`. + +Uporaba statičnih lastnosti vodi v [obskurno kodo, polno pasti |dependency-injection:global-state], zato jih nikoli ne smete uporabljati in tu ne bomo prikazali primera. Po drugi strani pa so statične metode uporabne. Tukaj je primer: + +```php +class Calculator +{ + public static function add($a, $b) + { + return $a + $b; + } + + public static function subtract($a, $b) + { + return $a - $b; + } +} + +// Using the static method without creating an instance of the class +echo Calculator::add(5, 3); // Output: 8 +echo Calculator::subtract(5, 3); // Output: 2 +``` + +V tem primeru smo ustvarili razred `Calculator` z dvema statičnima metodama. Ti metodi lahko pokličemo neposredno, ne da bi ustvarili primerek razreda z uporabo operatorja `::`. Statične metode so še posebej uporabne za operacije, ki niso odvisne od stanja določenega primerka razreda. + + +Konstante razreda .[#toc-class-constants] +----------------------------------------- + +Znotraj razredov lahko določimo konstante. Konstante so vrednosti, ki se med izvajanjem programa nikoli ne spremenijo. V nasprotju s spremenljivkami ostane vrednost konstante enaka. + +```php +class Car +{ + public const NumberOfWheels = 4; + + public function displayNumberOfWheels(): int + { + echo self::NumberOfWheels; + } +} + +echo Car::NumberOfWheels; // Output: 4 +``` + +V tem primeru imamo razred `Car` s konstanto `NumberOfWheels`. Pri dostopu do konstante znotraj razreda lahko namesto imena razreda uporabimo ključno besedo `self`. + + +Objektni vmesniki .[#toc-object-interfaces] +------------------------------------------- + +Objektni vmesniki delujejo kot "pogodbe" za razrede. Če naj razred implementira objektni vmesnik, mora vsebovati vse metode, ki jih vmesnik opredeljuje. To je odličen način za zagotavljanje, da se določeni razredi držijo iste "pogodbe" ali strukture. + +V PHP so vmesniki opredeljeni s ključno besedo `interface`. Vse metode, opredeljene v vmesniku, so javne (`public`). Ko razred implementira vmesnik, uporabi ključno besedo `implements`. + +```php +interface Animal +{ + function makeSound(); +} + +class Cat implements Animal +{ + public function makeSound() + { + echo 'Meow'; + } +} + +$cat = new Cat; +$cat->makeSound(); +``` + +Če razred implementira vmesnik, vendar niso definirane vse pričakovane metode, PHP vrže napako. Razred lahko implementira več vmesnikov hkrati, kar se razlikuje od dedovanja, pri katerem lahko razred deduje samo od enega razreda. + + +Abstraktni razredi .[#toc-abstract-classes] +------------------------------------------- + +Abstraktni razredi služijo kot osnovne predloge za druge razrede, vendar njihovih primerkov ne morete ustvariti neposredno. Vsebujejo mešanico popolnih metod in abstraktnih metod, ki nimajo določene vsebine. Razredi, ki dedujejo od abstraktnih razredov, morajo zagotoviti definicije za vse abstraktne metode iz starševskega razreda. + +Za opredelitev abstraktnega razreda uporabimo ključno besedo `abstract`. + +```php +abstract class AbstractClass +{ + public function regularMethod() + { + echo 'This is a regular method'; + } + + abstract public function abstractMethod(); +} + +class Child extends AbstractClass +{ + public function abstractMethod() + { + echo 'This is the implementation of the abstract method'; + } +} + +$instance = new Child; +$instance->regularMethod(); +$instance->abstractMethod(); +``` + +V tem primeru imamo abstraktni razred z eno redno in eno abstraktno metodo. Nato imamo razred `Child`, ki podeduje od `AbstractClass` in zagotavlja implementacijo abstraktne metode. + + +Preverjanje tipa .[#toc-type-checking] +-------------------------------------- + +Pri programiranju je ključnega pomena, da zagotovimo, da so podatki, s katerimi delamo, pravilnega tipa. V jeziku PHP imamo na voljo orodja, ki to zagotavljajo. Preverjanje, ali so podatki pravilnega tipa, se imenuje "preverjanje tipa". + +Tipi, ki jih lahko srečamo v PHP: + +1. **Osnovne vrste**: To so `int` (cela števila), `float` (števila s plavajočo vejico), `bool` (logične vrednosti), `string` (nizi), `array` (polja) in `null`. +2. **Tredi**: Kadar želimo, da je vrednost primerek določenega razreda. +3. **Vmesniki**: Opredeljuje nabor metod, ki jih mora razred implementirati. Vrednost, ki ustreza vmesniku, mora imeti te metode. +4. **Mešani tipi**: Določimo lahko, da ima lahko spremenljivka več dovoljenih tipov. +5. **Void**: Ta posebni tip označuje, da funkcija ali metoda ne vrača nobene vrednosti. + +Oglejmo si, kako spremeniti kodo, da bo vključevala tipe: + +```php +class Person +{ + private int $age; + + public function __construct(int $age) + { + $this->age = $age; + } + + public function printAge(): void + { + echo "This person is " . $this->age . " years old."; + } +} + +/** + * A function that accepts a Person object and prints the person's age. + */ +function printPersonAge(Person $person): void +{ + $person->printAge(); +} +``` + +Na ta način zagotovimo, da naša koda pričakuje in dela s podatki pravilne vrste, kar nam pomaga preprečiti morebitne napake. + + +Primerjava in identiteta .[#toc-comparison-and-identity] +-------------------------------------------------------- + +V PHP lahko predmete primerjate na dva načina: + +1. Primerjava vrednosti `==`: Preveri, ali sta objekta istega razreda in imata v svojih lastnostih enake vrednosti. +2. Primerjava identitete `===`: Preveri, ali gre za isti primerek objekta. + +```php +class Car +{ + public string $brand; + + public function __construct(string $brand) + { + $this->brand = $brand; + } +} + +$car1 = new Car('Skoda'); +$car2 = new Car('Skoda'); +$car3 = $car1; + +var_dump($car1 == $car2); // true, because they have the same value +var_dump($car1 === $car2); // false, because they are not the same instance +var_dump($car1 === $car3); // true, because $car3 is the same instance as $car1 +``` + + +Upravljavec spletne strani `instanceof` .[#toc-the-instanceof-operator] +----------------------------------------------------------------------- + +Operator `instanceof` omogoča ugotavljanje, ali je dani predmet primerek določenega razreda, potomec tega razreda ali pa implementira določen vmesnik. + +Predstavljajte si, da imamo razred `Person` in še en razred `Student`, ki je potomec razreda `Person`: + +```php +class Person +{ + private int $age; + + public function __construct(int $age) + { + $this->age = $age; + } +} + +class Student extends Person +{ + private string $major; + + public function __construct(int $age, string $major) + { + parent::__construct($age); + $this->major = $major; + } +} + +$student = new Student(20, 'Computer Science'); + +// Check if $student is an instance of the Student class +var_dump($student instanceof Student); // Output: bool(true) + +// Check if $student is an instance of the Person class (because Student is a descendant of Person) +var_dump($student instanceof Person); // Output: bool(true) +``` + +Iz izpisov je razvidno, da objekt `$student` velja za primerek obeh razredov `Student` in `Person`. + + +Fluentni vmesniki .[#toc-fluent-interfaces] +------------------------------------------- + +"Fluentni vmesnik" je tehnika v OOP, ki omogoča veriženje metod v enem samem klicu. To pogosto poenostavi in razjasni kodo. + +Ključni element tekočega vmesnika je, da vsaka metoda v verigi vrne referenco na trenutni objekt. To dosežemo z uporabo `return $this;` na koncu metode. Ta slog programiranja je pogosto povezan z metodami, imenovanimi "nastavljalci", ki nastavljajo vrednosti lastnosti objekta. + +Oglejmo si, kako bi lahko bil videti tekoči vmesnik za pošiljanje e-pošte: + +```php +public function sendMessage() +{ + $email = new Email; + $email->setFrom('sender@example.com') + ->setRecipient('admin@example.com') + ->setMessage('Hello, this is a message.') + ->send(); +} +``` + +V tem primeru so metode `setFrom()`, `setRecipient()` in `setMessage()` uporabljene za nastavitev ustreznih vrednosti (pošiljatelj, prejemnik, vsebina sporočila). Po nastavitvi vsake od teh vrednosti metode vrnejo trenutni objekt (`$email`), kar nam omogoča, da za njo verižno priključimo drugo metodo. Na koncu pokličemo metodo `send()`, ki dejansko pošlje elektronsko sporočilo. + +Zahvaljujoč tekočim vmesnikom lahko pišemo kodo, ki je intuitivna in lahko berljiva. + + +Kopiranje s `clone` .[#toc-copying-with-clone] +---------------------------------------------- + +V jeziku PHP lahko ustvarimo kopijo predmeta z uporabo operatorja `clone`. Tako dobimo nov primerek z enako vsebino. + +Če moramo pri kopiranju objekta spremeniti nekatere njegove lastnosti, lahko v razredu definiramo posebno metodo `__clone()`. Ta metoda se samodejno pokliče, ko je objekt kloniran. + +```php +class Sheep +{ + public string $name; + + public function __construct(string $name) + { + $this->name = $name; + } + + public function __clone() + { + $this->name = 'Clone of ' . $this->name; + } +} + +$original = new Sheep('Dolly'); +echo $original->name . "\n"; // Outputs: Dolly + +$clone = clone $original; +echo $clone->name . "\n"; // Outputs: Clone of Dolly +``` + +V tem primeru imamo razred `Sheep` z eno lastnostjo `$name`. Ko kloniramo primerek tega razreda, metoda `__clone()` poskrbi, da ime klonirane ovce dobi predpono "Clone of". + + +Lastnosti .[#toc-traits] +------------------------ + +Značilnosti v PHP so orodje, ki omogoča souporabo metod, lastnosti in konstant med razredi ter preprečuje podvajanje kode. Lahko si jih predstavljate kot mehanizem "kopiraj in prilepi" (Ctrl-C in Ctrl-V), pri katerem se vsebina lastnosti "prilepi" v razrede. To vam omogoča ponovno uporabo kode, ne da bi morali ustvarjati zapletene hierarhije razredov. + +Oglejmo si preprost primer uporabe lastnosti v jeziku PHP: + +```php +trait Honking +{ + public function honk() + { + echo 'Beep beep!'; + } +} + +class Car +{ + use Honking; +} + +class Truck +{ + use Honking; +} + +$car = new Car; +$car->honk(); // Outputs 'Beep beep!' + +$truck = new Truck; +$truck->honk(); // Also outputs 'Beep beep!' +``` + +V tem primeru imamo lastnost z imenom `Honking`, ki vsebuje eno metodo `honk()`. Nato imamo dva razreda: `Car` in `Truck`, ki oba uporabljata lastnost `Honking`. Posledično oba razreda "imata" metodo `honk()` in jo lahko kličemo na predmetih obeh razredov. + +Značilnosti omogočajo enostavno in učinkovito izmenjavo kode med razredi. Ne vstopajo v hierarhijo dedovanja, tj. `$car instanceof Honking` bo vrnil `false`. + + +Izjeme +------ + +Izjeme v OOP nam omogočajo obravnavo in upravljanje napak, ki se lahko pojavijo med izvajanjem naše kode. V bistvu so predmeti, namenjeni beleženju napak ali nepričakovanih situacij v vašem programu. + +V PHP je za te predmete vgrajen razred `Exception`. Ima več metod, ki nam omogočajo, da pridobimo več informacij o izjemi, kot so sporočilo o napaki, datoteka in vrstica, v kateri se je napaka pojavila, itd. + +Ko se pojavi težava, lahko "vržemo" izjemo (z uporabo razreda `throw`). Če želimo to izjemo "ujeti" in obdelati, uporabimo bloka `try` in `catch`. + +Oglejmo si, kako to deluje: + +```php +try { + throw new Exception('Message explaining the reason for the exception'); + + // This code won't execute + echo 'I am a message that nobody will read'; + +} catch (Exception $e) { + echo 'Exception caught: '. $e->getMessage(); +} +``` + +Pomembno je opozoriti, da se izjema lahko vrže globlje, med klicem drugih metod. + +Za en blok `try` lahko določite več blokov `catch`, če pričakujete različne vrste izjem. + +Ustvarimo lahko tudi hierarhijo izjem, kjer vsak razred izjem podeduje od prejšnjega. Kot primer si oglejmo preprosto bančno aplikacijo, ki omogoča vplačila in izplačila: + +```php +class BankingException extends Exception {} +class InsufficientFundsException extends BankingException {} +class ExceededLimitException extends BankingException {} + +class BankAccount +{ + private int $balance = 0; + private int $dailyLimit = 1000; + + public function deposit(int $amount): int + { + $this->balance += $amount; + return $this->balance; + } + + public function withdraw(int $amount): int + { + if ($amount > $this->balance) { + throw new InsufficientFundsException('Not enough funds in the account.'); + } + + if ($amount > $this->dailyLimit) { + throw new ExceededLimitException('Daily withdrawal limit exceeded.'); + } + + $this->balance -= $amount; + return $this->balance; + } +} + +$account = new BankAccount; +$account->deposit(500); + +try { + $account->withdraw(1500); +} catch (ExceededLimitException $e) { + echo $e->getMessage(); +} catch (InsufficientFundsException $e) { + echo $e->getMessage(); +} catch (BankingException $e) { + echo 'An error occurred during the operation.'; +} +``` + +V tem primeru je pomembno upoštevati vrstni red blokov `catch`. Ker vse izjeme dedujejo od `BankingException`, bi se, če bi imeli ta blok prvi, vse izjeme ujele v njem, ne da bi koda dosegla naslednje bloke `catch`. Zato je pomembno, da so bolj specifične izjeme (tj. tiste, ki dedujejo od drugih) višje v vrstnem redu blokov `catch` kot njihove nadrejene izjeme. + + +Najboljše prakse .[#toc-best-practices] +--------------------------------------- + +Ko obvladate osnovna načela objektno usmerjenega programiranja, se je treba osredotočiti na najboljše prakse v OOP. Te vam bodo pomagale pri pisanju kode, ki ni le funkcionalna, temveč tudi berljiva, razumljiva in jo je mogoče zlahka vzdrževati. + +1) **Oddelitev interesov**: Vsak razred mora imeti jasno opredeljeno odgovornost in mora obravnavati le eno primarno nalogo. Če razred počne preveč stvari, je morda primerno, da ga razdelite na manjše, specializirane razrede. +2) **Enkapsulacija**: Podatki in metode morajo biti čim bolj skriti in dostopni le prek opredeljenega vmesnika. To omogoča spreminjanje notranje implementacije razreda, ne da bi to vplivalo na preostalo kodo. +3) **Vključevanje odvisnosti**: Namesto da bi odvisnosti ustvarjali neposredno v razredu, bi jih morali "vbrizgati" od zunaj. Za globlje razumevanje tega načela priporočamo [poglavja o vbrizgavanju odvisnosti |dependency-injection:introduction]. diff --git a/nette/tr/introduction-to-object-oriented-programming.texy b/nette/tr/introduction-to-object-oriented-programming.texy new file mode 100644 index 0000000000..68c194847c --- /dev/null +++ b/nette/tr/introduction-to-object-oriented-programming.texy @@ -0,0 +1,725 @@ +Nesne Yönelimli Programlamaya Giriş +*********************************** + +.[perex] +"OOP" terimi, kodu organize etmenin ve yapılandırmanın bir yolu olan Nesne Yönelimli Programlama anlamına gelir. OOP, bir programı bir dizi komut ve işlev yerine birbirleriyle iletişim kuran nesneler topluluğu olarak görmemizi sağlar. + +OOP'de "nesne", veri ve bu veri üzerinde çalışan fonksiyonları içeren bir birimdir. Nesneler, nesneler için planlar veya şablonlar olarak anlaşılabilecek "sınıflar" temelinde oluşturulur. Bir sınıfa sahip olduğumuzda, o sınıftan yapılmış belirli bir nesne olan "örneğini" oluşturabiliriz. + +PHP'de basit bir sınıfı nasıl oluşturabileceğimize bakalım. Bir sınıfı tanımlarken, "class" anahtar sözcüğünü, ardından sınıf adını ve ardından sınıfın işlevlerini ("yöntemler" olarak adlandırılır) ve sınıf değişkenlerini ("özellikler" veya "nitelikler" olarak adlandırılır) çevreleyen küme parantezlerini kullanırız: + +```php +class Car +{ + function honk() + { + echo 'Beep beep!'; + } +} +``` + +Bu örnekte, `honk` adında bir işlevi (veya "yöntemi") olan `Car` adında bir sınıf oluşturduk. + +Her sınıf sadece bir ana görevi çözmelidir. Bir sınıf çok fazla şey yapıyorsa, onu daha küçük, uzmanlaşmış sınıflara bölmek uygun olabilir. + +Sınıflar, kodu düzenli tutmak ve gezinmeyi kolaylaştırmak için genellikle ayrı dosyalarda saklanır. Dosya adı sınıf adıyla eşleşmelidir, bu nedenle `Car` sınıfı için dosya adı `Car.php` olacaktır. + +Sınıfları adlandırırken, "PascalCase" kuralını takip etmek iyidir, yani isimdeki her kelime büyük harfle başlar ve alt çizgi veya başka ayırıcılar yoktur. Yöntemler ve özellikler "camelCase" kuralını takip eder, yani küçük harfle başlarlar. + +PHP'de bazı yöntemlerin özel rolleri vardır ve ön ekleri `__` (iki alt çizgi) ile gösterilir. En önemli özel yöntemlerden biri `__construct` olarak etiketlenen "kurucu "dur. Yapıcı, bir sınıfın yeni bir örneğini oluştururken otomatik olarak çağrılan bir yöntemdir. + +Yapıcıyı genellikle bir nesnenin başlangıç durumunu ayarlamak için kullanırız. Örneğin, bir kişiyi temsil eden bir nesne oluştururken, yaşı, adı veya diğer nitelikleri ayarlamak için kurucuyu kullanabilirsiniz. + +PHP'de bir yapıcının nasıl kullanılacağını görelim: + +```php +class Person +{ + private $age; + + function __construct($age) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +$person = new Person(25); +echo $person->howOldAreYou(); // Outputs: 25 +``` + +Bu örnekte, `Person` sınıfının bir `$age` özelliği ve bu özelliği ayarlayan bir kurucusu vardır. Daha sonra `howOldAreYou()` yöntemi kişinin yaşına erişim sağlar. + + `new` anahtar sözcüğü bir sınıfın yeni bir örneğini oluşturmak için kullanılır. Yukarıdaki örnekte, 25 yaşında yeni bir kişi oluşturduk. + +Bir nesne oluştururken belirtilmemişlerse, kurucu parametreleri için varsayılan değerler de ayarlayabilirsiniz. Örneğin: + +```php +class Person +{ + private $age; + + function __construct($age = 20) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +$person = new Person; // if no argument is passed, parentheses can be omitted +echo $person->howOldAreYou(); // Outputs: 20 +``` + +Bu örnekte, bir `Person` nesnesi oluştururken bir yaş belirtmezseniz, varsayılan değer olan 20 kullanılacaktır. + +Son olarak, yapıcı aracılığıyla başlatılmasıyla birlikte özellik tanımı şu şekilde kısaltılabilir ve basitleştirilebilir: + +```php +class Person +{ + function __construct( + private $age = 20, + ) { + } +} +``` + + +İsim Alanları .[#toc-namespaces] +-------------------------------- + +Ad alanları, adlandırma çakışmalarını önlerken ilgili sınıfları, işlevleri ve sabitleri düzenlememize ve gruplandırmamıza olanak tanır. Bunları, her klasörün belirli bir proje veya konuyla ilgili dosyaları içerdiği bir bilgisayardaki klasörler gibi düşünebilirsiniz. + +Ad alanları özellikle büyük projelerde veya sınıf adlandırma çakışmalarının ortaya çıkabileceği üçüncü taraf kütüphaneleri kullanırken kullanışlıdır. + +Projenizde `Car` adında bir sınıfınız olduğunu ve bunu `Transport` adında bir ad alanına yerleştirmek istediğinizi düşünün. Bunu şu şekilde yaparsınız: + +```php +namespace Transport; + +class Car +{ + function honk() + { + echo 'Beep beep!'; + } +} +``` + + `Car` sınıfını başka bir dosyada kullanmak istiyorsanız, sınıfın hangi ad alanından geldiğini belirtmeniz gerekir: + +```php +$car = new Transport\Car; +``` + +Basitleştirmek için, dosyanın başında belirli bir ad alanından hangi sınıfı kullanmak istediğinizi belirtebilir, böylece tam yolu belirtmeden örnekler oluşturabilirsiniz: + +```php +use Transport\Car; + +$car = new Car; +``` + + +Kalıtım .[#toc-inheritance] +--------------------------- + +Kalıtım, mevcut sınıflara dayalı olarak yeni sınıfların oluşturulmasına, özelliklerinin ve yöntemlerinin miras alınmasına ve gerektiğinde genişletilmesine veya yeniden tanımlanmasına olanak tanıyan bir nesne yönelimli programlama aracıdır. Kalıtım, kodun yeniden kullanılabilirliğini ve sınıf hiyerarşisini sağlar. + +Basitçe söylemek gerekirse, bir sınıfımız varsa ve ondan türetilmiş ancak bazı değişikliklerle başka bir sınıf oluşturmak istiyorsak, yeni sınıfı orijinal sınıftan "miras" alabiliriz. + +PHP'de kalıtım `extends` anahtar sözcüğü kullanılarak gerçekleştirilir. + + `Person` sınıfımız yaş bilgisini saklar. `Person` 'i genişleten ve çalışma alanı hakkında bilgi ekleyen `Student` adlı başka bir sınıfımız olabilir. + +Bir örneğe bakalım: + +```php +class Person +{ + private $age; + + function __construct($age) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +class Student extends Person +{ + private $fieldOfStudy; + + function __construct($age, $fieldOfStudy) + { + parent::__construct($age); + $this->fieldOfStudy = $fieldOfStudy; + } + + function printInformation() + { + echo 'Age of student: ', $this->howOldAreYou(); + echo 'Field of study: ', $this->fieldOfStudy; + } +} + +$student = new Student(20, 'Computer Science'); +$student->printInformation(); +``` + +Bu kod nasıl çalışıyor? + +- `Person` sınıfını genişletmek için `extends` anahtar sözcüğünü kullandık, yani `Student` sınıfı tüm yöntemleri ve özellikleri `Person` sınıfından devralır. + +- `parent::` anahtar sözcüğü, üst sınıftaki yöntemleri çağırmamızı sağlar. Bu durumda, `Student` sınıfına kendi işlevselliğimizi eklemeden önce `Person` sınıfından kurucuyu çağırdık. + +Kalıtım, sınıflar arasında "is a" ilişkisinin olduğu durumlar içindir. Örneğin, bir `Student` bir `Person`. Bir kedi bir hayvandır. Kodda bir nesne (örn. "Kişi") beklediğimiz durumlarda bunun yerine türetilmiş bir nesne (örn. "Öğrenci") kullanmamızı sağlar. + +Kalıtımın birincil amacının **kod tekrarını önlemek** olmadığının farkına varmak çok önemlidir. Aksine, kalıtımın yanlış kullanımı karmaşık ve bakımı zor kodlara yol açabilir. Sınıflar arasında "is a" ilişkisi yoksa, kalıtım yerine bileşimi düşünmeliyiz. + + +Kompozisyon .[#toc-composition] +------------------------------- + +Kompozisyon, başka bir sınıftan özellikleri ve yöntemleri miras almak yerine, sınıfımızda onun örneğini kullandığımız bir tekniktir. Bu, karmaşık kalıtım yapıları oluşturmadan birden fazla sınıfın işlevlerini ve özelliklerini birleştirmemizi sağlar. + +Örneğin, bir `Engine` sınıfımız ve bir `Car` sınıfımız var. "Bir araba bir motordur" demek yerine, tipik bir bileşim ilişkisi olan "Bir arabanın motoru vardır" deriz. + +```php +class Engine +{ + function start() + { + echo "Engine is running."; + } +} + +class Car +{ + private $engine; + + function __construct() + { + $this->engine = new Engine; + } + + function start() + { + $this->engine->start(); + echo "The car is ready to drive!"; + } +} + +$car = new Car; +$car->start(); +``` + +Burada, `Car`, `Engine`'un tüm özelliklerine ve yöntemlerine sahip değildir, ancak `$engine` özelliği aracılığıyla bunlara erişebilir. + +Kompozisyonun avantajı, daha fazla tasarım esnekliği ve gelecekteki değişiklikler için daha iyi uyarlanabilirliktir. + + +Görünürlük .[#toc-visibility] +----------------------------- + +PHP'de sınıf özellikleri, yöntemleri ve sabitleri için "görünürlük" tanımlayabilirsiniz. Görünürlük, bu öğelere nereden erişebileceğinizi belirler. + +1. **Public:** Eğer bir eleman `public` olarak işaretlenmişse, bu ona her yerden, hatta sınıf dışından bile erişebileceğiniz anlamına gelir. + +2. **Korumalı:** `protected` olarak işaretlenmiş bir öğeye yalnızca sınıf ve tüm torunları (ondan miras alan sınıflar) içinde erişilebilir. + +3. **Özel:** Bir eleman `private` ise, ona yalnızca tanımlandığı sınıf içinden erişebilirsiniz. + +Görünürlük belirtmezseniz, PHP bunu otomatik olarak `public` olarak ayarlayacaktır. + +Örnek bir koda bakalım: + +```php +class VisibilityExample +{ + public $publicProperty = 'Public'; + protected $protectedProperty = 'Protected'; + private $privateProperty = 'Private'; + + public function printProperties() + { + echo $this->publicProperty; // Works + echo $this->protectedProperty; // Works + echo $this->privateProperty; // Works + } +} + +$object = new VisibilityExample; +$object->printProperties(); +echo $object->publicProperty; // Works +// echo $object->protectedProperty; // Throws an error +// echo $object->privateProperty; // Throws an error +``` + +Sınıf kalıtımına devam ediyoruz: + +```php +class ChildClass extends VisibilityExample +{ + public function printProperties() + { + echo $this->publicProperty; // Works + echo $this->protectedProperty; // Works + // echo $this->privateProperty; // Throws an error + } +} +``` + +Bu durumda, `ChildClass` adresindeki `printProperties()` yöntemi public ve protected özelliklere erişebilir ancak ana sınıfın private özelliklerine erişemez. + +Veri ve yöntemler mümkün olduğunca gizli olmalı ve sadece tanımlanmış bir arayüz üzerinden erişilebilir olmalıdır. Bu, kodun geri kalanını etkilemeden sınıfın dahili uygulamasını değiştirmenize olanak tanır. + + +Son Anahtar Kelime .[#toc-final-keyword] +---------------------------------------- + +PHP'de, bir sınıfın, yöntemin veya sabitin miras alınmasını veya geçersiz kılınmasını önlemek istiyorsak `final` anahtar sözcüğünü kullanabiliriz. Bir sınıf `final` olarak işaretlendiğinde genişletilemez. Bir yöntem `final` olarak işaretlendiğinde, bir alt sınıfta geçersiz kılınamaz. + +Belirli bir sınıf veya yöntemin artık değiştirilmeyeceğinin farkında olmak, olası çakışmalar konusunda endişelenmeden daha kolay değişiklik yapmamızı sağlar. Örneğin, bir alt sınıfın zaten aynı isimde bir metoda sahip olmasından ve bunun bir çakışmaya yol açmasından korkmadan yeni bir metot ekleyebiliriz. Ya da bir yöntemin parametrelerini, yine alttaki bir yöntemde geçersiz kılınmış bir yöntemle tutarsızlığa neden olma riski olmadan değiştirebiliriz. + +```php +final class FinalClass +{ +} + +// The following code will throw an error because we cannot inherit from a final class. +class ChildOfFinalClass extends FinalClass +{ +} +``` + +Bu örnekte, `FinalClass` nihai sınıfından miras almaya çalışmak bir hatayla sonuçlanacaktır. + + +Statik Özellikler ve Yöntemler .[#toc-static-properties-and-methods] +-------------------------------------------------------------------- + +PHP'de bir sınıfın "statik" öğelerinden bahsettiğimizde, sınıfın belirli bir örneğine değil, sınıfın kendisine ait olan yöntemleri ve özellikleri kastediyoruz. Bu, onlara erişmek için sınıfın bir örneğini oluşturmanız gerekmediği anlamına gelir. Bunun yerine, bunları doğrudan sınıf adı üzerinden çağırır veya bunlara erişirsiniz. + +Statik öğeler örneklere değil sınıfa ait olduğundan, statik yöntemlerin içinde `$this` sözde değişkenini kullanamayacağınızı unutmayın. + +Statik özelliklerin kullanılması [tuzaklarla dolu karmaşık kodlara |dependency-injection:global-state] yol açar, bu nedenle bunları asla kullanmamalısınız ve burada bir örnek göstermeyeceğiz. Öte yandan, statik yöntemler kullanışlıdır. İşte bir örnek: + +```php +class Calculator +{ + public static function add($a, $b) + { + return $a + $b; + } + + public static function subtract($a, $b) + { + return $a - $b; + } +} + +// Using the static method without creating an instance of the class +echo Calculator::add(5, 3); // Output: 8 +echo Calculator::subtract(5, 3); // Output: 2 +``` + +Bu örnekte, iki statik yöntemi olan bir `Calculator` sınıfı oluşturduk. Bu yöntemleri, `::` operatörünü kullanarak sınıfın bir örneğini oluşturmadan doğrudan çağırabiliriz. Statik yöntemler özellikle belirli bir sınıf örneğinin durumuna bağlı olmayan işlemler için kullanışlıdır. + + +Sınıf Sabitleri .[#toc-class-constants] +--------------------------------------- + +Sınıflar içinde sabitler tanımlama seçeneğimiz vardır. Sabitler, programın yürütülmesi sırasında asla değişmeyen değerlerdir. Değişkenlerin aksine, bir sabitin değeri aynı kalır. + +```php +class Car +{ + public const NumberOfWheels = 4; + + public function displayNumberOfWheels(): int + { + echo self::NumberOfWheels; + } +} + +echo Car::NumberOfWheels; // Output: 4 +``` + +Bu örnekte, `NumberOfWheels` sabitine sahip bir `Car` sınıfımız var. Sınıf içindeki sabite erişirken, sınıf adı yerine `self` anahtar sözcüğünü kullanabiliriz. + + +Nesne Arayüzleri .[#toc-object-interfaces] +------------------------------------------ + +Nesne arayüzleri sınıflar için "sözleşme" görevi görür. Bir sınıf bir nesne arayüzünü uygulayacaksa, arayüzün tanımladığı tüm yöntemleri içermelidir. Bu, belirli sınıfların aynı "sözleşmeye" veya yapıya bağlı kalmasını sağlamanın harika bir yoludur. + +PHP'de arayüzler `interface` anahtar sözcüğü kullanılarak tanımlanır. Bir arayüzde tanımlanan tüm yöntemler public'tir (`public`). Bir sınıf bir arayüzü uyguladığında, `implements` anahtar sözcüğünü kullanır. + +```php +interface Animal +{ + function makeSound(); +} + +class Cat implements Animal +{ + public function makeSound() + { + echo 'Meow'; + } +} + +$cat = new Cat; +$cat->makeSound(); +``` + +Bir sınıf bir arayüzü uygular, ancak beklenen tüm yöntemler tanımlanmamışsa, PHP bir hata verir. Bir sınıf aynı anda birden fazla arayüzü uygulayabilir; bu, bir sınıfın yalnızca bir sınıftan miras alabildiği kalıtımdan farklıdır. + + +Soyut Sınıflar .[#toc-abstract-classes] +--------------------------------------- + +Soyut sınıflar diğer sınıflar için temel şablon görevi görür, ancak örneklerini doğrudan oluşturamazsınız. Tam yöntemler ve tanımlanmış bir içeriği olmayan soyut yöntemlerin bir karışımını içerirler. Soyut sınıflardan miras alan sınıflar, üst sınıftaki tüm soyut yöntemler için tanımlar sağlamalıdır. + +Soyut bir sınıf tanımlamak için `abstract` anahtar sözcüğünü kullanırız. + +```php +abstract class AbstractClass +{ + public function regularMethod() + { + echo 'This is a regular method'; + } + + abstract public function abstractMethod(); +} + +class Child extends AbstractClass +{ + public function abstractMethod() + { + echo 'This is the implementation of the abstract method'; + } +} + +$instance = new Child; +$instance->regularMethod(); +$instance->abstractMethod(); +``` + +Bu örnekte, bir normal ve bir soyut yöntemi olan soyut bir sınıfımız var. Ardından, `AbstractClass` adresinden miras alan ve soyut yöntem için bir uygulama sağlayan bir `Child` sınıfımız var. + + +Tip Kontrolü .[#toc-type-checking] +---------------------------------- + +Programlamada, birlikte çalıştığımız verilerin doğru türde olduğundan emin olmak çok önemlidir. PHP'de bu güvenceyi sağlayan araçlarımız vardır. Verilerin doğru türde olduğunu doğrulamaya "tür denetimi" denir. + +PHP'de karşılaşabileceğimiz türler: + +1. **Temel tipler**: Bunlar `int` (tam sayılar), `float` (kayan noktalı sayılar), `bool` (boolean değerler), `string` (dizeler), `array` (diziler) ve `null` içerir. +2. **Sınıflar**: Bir değerin belirli bir sınıfın örneği olmasını istediğimizde. +3. **Arayüzler**: Bir sınıfın uygulaması gereken bir dizi yöntemi tanımlar. Bir arayüzü karşılayan bir değer bu yöntemlere sahip olmalıdır. +4. **Karışık tipler**: Bir değişkenin birden fazla izin verilen türe sahip olabileceğini belirtebiliriz. +5. **Void**: Bu özel tip, bir fonksiyon veya metodun herhangi bir değer döndürmediğini belirtir. + +Türleri dahil etmek için kodu nasıl değiştireceğimizi görelim: + +```php +class Person +{ + private int $age; + + public function __construct(int $age) + { + $this->age = $age; + } + + public function printAge(): void + { + echo "This person is " . $this->age . " years old."; + } +} + +/** + * A function that accepts a Person object and prints the person's age. + */ +function printPersonAge(Person $person): void +{ + $person->printAge(); +} +``` + +Bu şekilde, kodumuzun doğru türdeki verileri beklediğinden ve bunlarla çalıştığından emin olarak olası hataları önlememize yardımcı oluruz. + + +Karşılaştırma ve Kimlik .[#toc-comparison-and-identity] +------------------------------------------------------- + +PHP'de nesneleri iki şekilde karşılaştırabilirsiniz: + +1. Değer karşılaştırması `==`: Nesnelerin aynı sınıftan olup olmadığını ve özelliklerinde aynı değerlere sahip olup olmadığını kontrol eder. +2. Kimlik `===`: Nesnenin aynı örneği olup olmadığını kontrol eder. + +```php +class Car +{ + public string $brand; + + public function __construct(string $brand) + { + $this->brand = $brand; + } +} + +$car1 = new Car('Skoda'); +$car2 = new Car('Skoda'); +$car3 = $car1; + +var_dump($car1 == $car2); // true, because they have the same value +var_dump($car1 === $car2); // false, because they are not the same instance +var_dump($car1 === $car3); // true, because $car3 is the same instance as $car1 +``` + + + + `instanceof` Operatör .[#toc-the-instanceof-operator] +------------------------- + + `instanceof` operatörü, belirli bir nesnenin belirli bir sınıfın örneği olup olmadığını, bu sınıfın soyundan gelip gelmediğini veya belirli bir arayüzü uygulayıp uygulamadığını belirlemenizi sağlar. + +Bir `Person` sınıfımız ve `Person` sınıfının soyundan gelen başka bir `Student` sınıfımız olduğunu düşünün: + +```php +class Person +{ + private int $age; + + public function __construct(int $age) + { + $this->age = $age; + } +} + +class Student extends Person +{ + private string $major; + + public function __construct(int $age, string $major) + { + parent::__construct($age); + $this->major = $major; + } +} + +$student = new Student(20, 'Computer Science'); + +// Check if $student is an instance of the Student class +var_dump($student instanceof Student); // Output: bool(true) + +// Check if $student is an instance of the Person class (because Student is a descendant of Person) +var_dump($student instanceof Person); // Output: bool(true) +``` + +Çıktılardan, `$student` nesnesinin hem `Student` hem de `Person` sınıflarının bir örneği olarak kabul edildiği açıktır. + + +Akıcı Arayüzler .[#toc-fluent-interfaces] +----------------------------------------- + +"Akıcı Arayüz", OOP'de yöntemlerin tek bir çağrıda bir araya getirilmesini sağlayan bir tekniktir. Bu genellikle kodu basitleştirir ve netleştirir. + +Akıcı bir arayüzün temel unsuru, zincirdeki her yöntemin geçerli nesneye bir referans döndürmesidir. Bu, yöntemin sonunda `return $this;` kullanılarak gerçekleştirilir. Bu programlama tarzı genellikle bir nesnenin özelliklerinin değerlerini ayarlayan "setter" adı verilen yöntemlerle ilişkilendirilir. + +E-posta göndermek için akıcı bir arayüzün nasıl görünebileceğini görelim: + +```php +public function sendMessage() +{ + $email = new Email; + $email->setFrom('sender@example.com') + ->setRecipient('admin@example.com') + ->setMessage('Hello, this is a message.') + ->send(); +} +``` + +Bu örnekte, `setFrom()`, `setRecipient()`, ve `setMessage()` yöntemleri ilgili değerleri (gönderen, alıcı, mesaj içeriği) ayarlamak için kullanılır. Bu değerlerin her birini ayarladıktan sonra, yöntemler geçerli nesneyi (`$email`) döndürür, böylece ondan sonra başka bir yöntemi zincirlememize izin verir. Son olarak, e-postayı gerçekten gönderen `send()` yöntemini çağırıyoruz. + +Akıcı arayüzler sayesinde sezgisel ve kolay okunabilir kodlar yazabiliyoruz. + + + + `clone` ile kopyalama .[#toc-copying-with-clone] +-------------------- + +PHP'de `clone` operatörünü kullanarak bir nesnenin kopyasını oluşturabiliriz. Bu şekilde, aynı içeriğe sahip yeni bir örnek elde ederiz. + +Bir nesneyi kopyalarken bazı özelliklerini değiştirmemiz gerekiyorsa, sınıfta özel bir `__clone()` yöntemi tanımlayabiliriz. Nesne klonlandığında bu yöntem otomatik olarak çağrılır. + +```php +class Sheep +{ + public string $name; + + public function __construct(string $name) + { + $this->name = $name; + } + + public function __clone() + { + $this->name = 'Clone of ' . $this->name; + } +} + +$original = new Sheep('Dolly'); +echo $original->name . "\n"; // Outputs: Dolly + +$clone = clone $original; +echo $clone->name . "\n"; // Outputs: Clone of Dolly +``` + +Bu örnekte, bir özelliği `$name` olan bir `Sheep` sınıfımız var. Bu sınıfın bir örneğini klonladığımızda, `__clone()` yöntemi klonlanan koyunun adının "Clone of" ön ekini almasını sağlar. + + +Özellikler .[#toc-traits] +PHP'deki özellikler, sınıflar arasında yöntemlerin, özelliklerin ve sabitlerin paylaşılmasını sağlayan ve kod tekrarını önleyen bir araçtır. Bunları, bir özelliğin içeriğinin sınıflara "yapıştırıldığı" bir "kopyala ve yapıştır" mekanizması (Ctrl-C ve Ctrl-V) olarak düşünebilirsiniz. Bu, karmaşık sınıf hiyerarşileri oluşturmak zorunda kalmadan kodu yeniden kullanmanıza olanak tanır. + +PHP'deki özellikler, sınıflar arasında yöntemlerin paylaşılmasını sağlayan ve kod tekrarını önleyen bir araçtır. Bunları, bir özelliğin içeriğinin sınıflara "yapıştırıldığı" bir "kopyala ve yapıştır" mekanizması (Ctrl-C ve Ctrl-V) olarak düşünebilirsiniz. Bu, karmaşık sınıf hiyerarşileri oluşturmak zorunda kalmadan kodu yeniden kullanmanıza olanak tanır. + +PHP'de özelliklerin nasıl kullanılacağına dair basit bir örneğe göz atalım: + +```php +trait Honking +{ + public function honk() + { + echo 'Beep beep!'; + } +} + +class Car +{ + use Honking; +} + +class Truck +{ + use Honking; +} + +$car = new Car; +$car->honk(); // Outputs 'Beep beep!' + +$truck = new Truck; +$truck->honk(); // Also outputs 'Beep beep!' +``` + +Bu örnekte, bir yöntem içeren `Honking` adlı bir özelliğimiz var `honk()`. Sonra iki sınıfımız var: `Car` ve `Truck`, her ikisi de `Honking` özelliğini kullanıyor. Sonuç olarak, her iki sınıf da `honk()` yöntemine "sahiptir" ve bu yöntemi her iki sınıfın nesneleri üzerinde çağırabiliriz. + +Özellikler, sınıflar arasında kolay ve verimli bir şekilde kod paylaşımı yapmanızı sağlar. Kalıtım hiyerarşisine girmezler, yani `$car instanceof Honking`, `false` döndürür. + + +İstisnalar +---------- + + +OOP'de İstisnalar .[#toc-exceptions-in-oop] +------------------------------------------- + +OOP'deki istisnalar, kodumuzun yürütülmesi sırasında ortaya çıkabilecek hataları ele almamızı ve yönetmemizi sağlar. Bunlar esasen programınızdaki hataları veya beklenmedik durumları kaydetmek için tasarlanmış nesnelerdir. + +PHP'de, bu nesneler için yerleşik `Exception` sınıfına sahibiz. Hata mesajı, dosya ve hatanın oluştuğu satır gibi istisna hakkında daha fazla bilgi almamızı sağlayan birkaç yöntemi vardır. + +Bir sorun ortaya çıktığında, bir istisna "atabiliriz" ( `throw` kullanarak). Bu istisnayı "yakalamak" ve işlemek istiyorsak, `try` ve `catch` bloklarını kullanırız. + +Nasıl çalıştığını görelim: + +```php +try { + throw new Exception('Message explaining the reason for the exception'); + + // This code won't execute + echo 'I am a message that nobody will read'; + +} catch (Exception $e) { + echo 'Exception caught: '. $e->getMessage(); +} +``` + +Bir istisnanın daha derinde, diğer yöntemlere çağrı sırasında atılabileceğine dikkat etmek önemlidir. + +Bir `try` bloğu için, farklı türde istisnalar bekliyorsanız birden fazla `catch` bloğu belirtilebilir. + +Her istisna sınıfının bir öncekinden miras aldığı bir istisna hiyerarşisi de oluşturabiliriz. Örnek olarak, para yatırma ve çekme işlemlerine izin veren basit bir bankacılık uygulaması düşünün: + +```php +class BankingException extends Exception {} +class InsufficientFundsException extends BankingException {} +class ExceededLimitException extends BankingException {} + +class BankAccount +{ + private int $balance = 0; + private int $dailyLimit = 1000; + + public function deposit(int $amount): int + { + $this->balance += $amount; + return $this->balance; + } + + public function withdraw(int $amount): int + { + if ($amount > $this->balance) { + throw new InsufficientFundsException('Not enough funds in the account.'); + } + + if ($amount > $this->dailyLimit) { + throw new ExceededLimitException('Daily withdrawal limit exceeded.'); + } + + $this->balance -= $amount; + return $this->balance; + } +} + +$account = new BankAccount; +$account->deposit(500); + +try { + $account->withdraw(1500); +} catch (ExceededLimitException $e) { + echo $e->getMessage(); +} catch (InsufficientFundsException $e) { + echo $e->getMessage(); +} catch (BankingException $e) { + echo 'An error occurred during the operation.'; +} +``` + + +En İyi Uygulamalar .[#toc-best-practices] +----------------------------------------- + +Nesne yönelimli programlamanın temel ilkelerini öğrendikten sonra, OOP'deki en iyi uygulamalara odaklanmak çok önemlidir. Bunlar yalnızca işlevsel değil aynı zamanda okunabilir, anlaşılabilir ve bakımı kolay kodlar yazmanıza yardımcı olacaktır. + +1) **İlgilerin Ayrılması**: Her sınıfın açıkça tanımlanmış bir sorumluluğu olmalı ve yalnızca bir birincil görevi ele almalıdır. Bir sınıf çok fazla şey yapıyorsa, onu daha küçük, uzmanlaşmış sınıflara bölmek uygun olabilir. +2) **Kapsülleme**: Veri ve yöntemler mümkün olduğunca gizli olmalı ve yalnızca tanımlanmış bir arayüz aracılığıyla erişilebilir olmalıdır. Bu, kodun geri kalanını etkilemeden bir sınıfın dahili uygulamasını değiştirmenize olanak tanır. +3) **Dependency Injection**: Bağımlılıkları doğrudan bir sınıfın içinde oluşturmak yerine, onları dışarıdan "enjekte etmelisiniz". Bu prensibi daha iyi anlamak için [Bağımlılık Enjeksiyonu bölümünü |dependency-injection:introduction] okumanızı tavsiye ederiz. + +Bu örnekte, `catch` bloklarının sırasına dikkat etmek önemlidir. Tüm istisnalar `BankingException` adresinden miras alındığından, bu bloğu ilk olarak kullansaydık, kod sonraki `catch` bloklarına ulaşmadan tüm istisnalar bu blokta yakalanırdı. Bu nedenle, daha spesifik istisnaların (yani diğerlerinden miras kalanların) `catch` blok sıralamasında ana istisnalardan daha yukarıda olması önemlidir. diff --git a/nette/uk/introduction-to-object-oriented-programming.texy b/nette/uk/introduction-to-object-oriented-programming.texy new file mode 100644 index 0000000000..4416380652 --- /dev/null +++ b/nette/uk/introduction-to-object-oriented-programming.texy @@ -0,0 +1,719 @@ +Вступ до об'єктно-орієнтованого програмування +********************************************* + +.[perex] +Термін "ООП" розшифровується як об'єктно-орієнтоване програмування - спосіб організації та структурування коду. ООП дозволяє розглядати програму як набір об'єктів, які взаємодіють між собою, а не як послідовність команд і функцій. + +В ООП "об'єкт" - це одиниця, яка містить дані та функції, що оперують цими даними. Об'єкти створюються на основі "класів", які можна розуміти як схеми або шаблони для об'єктів. Маючи клас, ми можемо створити його "екземпляр", тобто конкретний об'єкт, створений на основі цього класу. + +Давайте розглянемо, як можна створити простий клас в PHP. При визначенні класу ми використовуємо ключове слово "class", за яким слідує ім'я класу, а потім фігурні дужки, в які вкладаються функції класу (звані "методами") і змінні класу (звані "властивостями" або "атрибутами"): + +```php +class Car +{ + function honk() + { + echo 'Beep beep!'; + } +} +``` + +У цьому прикладі ми створили клас з іменем `Car` з однією функцією (або "методом") `honk`. + +Кожен клас повинен вирішувати лише одне основне завдання. Якщо клас виконує занадто багато завдань, може бути доцільно розділити його на менші, спеціалізовані класи. + +Класи зазвичай зберігаються в окремих файлах, щоб упорядкувати код і полегшити навігацію по ньому. Ім'я файлу має відповідати імені класу, тому для класу `Car` ім'я файлу буде `Car.php`. + +Називаючи класи, варто дотримуватися конвенції "PascalCase", тобто кожне слово в назві починається з великої літери, без підкреслень або інших роздільників. Методи та властивості слідують конвенції "camelCase", тобто починаються з малої літери. + +Деякі методи в PHP відіграють особливу роль і мають префікс `__` (два підкреслення). Одним з найважливіших спеціальних методів є "конструктор", позначений як `__construct`. Конструктор - це метод, який автоматично викликається при створенні нового екземпляра класу. + +Ми часто використовуємо конструктор для встановлення початкового стану об'єкта. Наприклад, при створенні об'єкта, що представляє людину, ви можете використовувати конструктор, щоб встановити її вік, ім'я або інші атрибути. + +Давайте подивимося, як використовувати конструктор в PHP: + +```php +class Person +{ + private $age; + + function __construct($age) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +$person = new Person(25); +echo $person->howOldAreYou(); // Outputs: 25 +``` + +У цьому прикладі клас `Person` має властивість `$age` і конструктор, який встановлює цю властивість. Метод `howOldAreYou()` надає доступ до віку людини. + +Ключове слово `new` використовується для створення нового екземпляра класу. У наведеному вище прикладі ми створили нову особу віком 25 років. + +Ви також можете встановити значення за замовчуванням для параметрів конструктора, якщо вони не вказані при створенні об'єкта. Наприклад: + +```php +class Person +{ + private $age; + + function __construct($age = 20) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +$person = new Person; // if no argument is passed, parentheses can be omitted +echo $person->howOldAreYou(); // Outputs: 20 +``` + +У цьому прикладі, якщо не вказати вік при створенні об'єкта `Person`, буде використано значення за замовчуванням 20. + +Нарешті, визначення властивості з її ініціалізацією через конструктор можна скоротити і спростити таким чином: + +```php +class Person +{ + function __construct( + private $age = 20, + ) { + } +} +``` + + +Простори імен .[#toc-namespaces] +-------------------------------- + +Простори імен дозволяють нам організовувати і групувати пов'язані класи, функції і константи, уникаючи конфліктів імен. Ви можете уявити їх як папки на комп'ютері, де кожна папка містить файли, пов'язані з певним проектом або темою. + +Простори імен особливо корисні у великих проектах або при використанні сторонніх бібліотек, де можуть виникати конфлікти імен класів. + +Уявіть, що у вашому проекті є клас з іменем `Car`, і ви хочете розмістити його у просторі імен `Transport`. Ви можете зробити це таким чином: + +```php +namespace Transport; + +class Car +{ + function honk() + { + echo 'Beep beep!'; + } +} +``` + +Якщо ви хочете використати клас `Car` в іншому файлі, вам потрібно вказати, з якого простору імен походить клас: + +```php +$car = new Transport\Car; +``` + +Для спрощення ви можете вказати на початку файлу, який саме клас з певного простору імен ви хочете використовувати, що дозволить вам створювати екземпляри без зазначення повного шляху: + +```php +use Transport\Car; + +$car = new Car; +``` + + +Спадщина .[#toc-inheritance] +---------------------------- + +Спадкування - це інструмент об'єктно-орієнтованого програмування, який дозволяє створювати нові класи на основі існуючих, успадковувати їх властивості та методи, а також розширювати або перевизначати їх за потреби. Спадкування забезпечує повторне використання коду та ієрархію класів. + +Простіше кажучи, якщо ми маємо один клас і хочемо створити інший, похідний від нього, але з деякими змінами, ми можемо "успадкувати" новий клас від початкового. + +У PHP успадкування реалізується за допомогою ключового слова `extends`. + +Наш клас `Person` зберігає інформацію про вік. Ми можемо створити ще один клас, `Student`, який розширює `Person` і додає інформацію про галузь навчання. + +Давайте розглянемо приклад: + +```php +class Person +{ + private $age; + + function __construct($age) + { + $this->age = $age; + } + + function howOldAreYou() + { + return $this->age; + } +} + +class Student extends Person +{ + private $fieldOfStudy; + + function __construct($age, $fieldOfStudy) + { + parent::__construct($age); + $this->fieldOfStudy = $fieldOfStudy; + } + + function printInformation() + { + echo 'Age of student: ', $this->howOldAreYou(); + echo 'Field of study: ', $this->fieldOfStudy; + } +} + +$student = new Student(20, 'Computer Science'); +$student->printInformation(); +``` + +Як працює цей код? + +- Ми використали ключове слово `extends` для розширення класу `Person`, тобто клас `Student` успадковує всі методи та властивості від `Person`. + +- Ключове слово `parent::` дозволяє нам викликати методи з батьківського класу. У цьому випадку ми викликали конструктор з класу `Person` перед тим, як додати власну функціональність до класу `Student`. + +Спадкування призначене для ситуацій, коли між класами існує відношення "є". Наприклад, `Student` є `Person`. Кіт - це тварина. Це дозволяє нам у випадках, коли ми очікуємо один об'єкт (наприклад, "Людина") в коді, використовувати замість нього похідний об'єкт (наприклад, "Студент"). + +Важливо розуміти, що основною метою успадкування **не є** запобігання дублюванню коду. Навпаки, зловживання успадкуванням може призвести до створення складного і важкого для супроводу коду. Якщо між класами немає відношення "є", то замість успадкування слід розглядати композицію. + + +Композиція .[#toc-composition] +------------------------------ + +Композиція - це техніка, коли замість того, щоб успадковувати властивості та методи з іншого класу, ми просто використовуємо його екземпляр у своєму класі. Це дозволяє об'єднати функціональність і властивості декількох класів без створення складних структур успадкування. + +Наприклад, у нас є клас `Engine` і клас `Car`. Замість того, щоб сказати "Автомобіль - це двигун", ми скажемо "Автомобіль має двигун", що є типовим відношенням композиції. + +```php +class Engine +{ + function start() + { + echo "Engine is running."; + } +} + +class Car +{ + private $engine; + + function __construct() + { + $this->engine = new Engine; + } + + function start() + { + $this->engine->start(); + echo "The car is ready to drive!"; + } +} + +$car = new Car; +$car->start(); +``` + +Тут `Car` не має всіх властивостей і методів класу `Engine`, але має доступ до нього через властивість `$engine`. + +Перевагою композиції є більша гнучкість дизайну та краща адаптивність до майбутніх змін. + + +Видимість .[#toc-visibility] +---------------------------- + +У PHP ви можете визначити "видимість" для властивостей, методів і констант класу. Видимість визначає, де ви можете отримати доступ до цих елементів. + +1. **Публічний:** Якщо елемент позначено як `public`, це означає, що ви можете отримати до нього доступ з будь-якого місця, навіть за межами класу. + +2. **Protected:** Елемент, позначений як `protected`, доступний тільки в межах класу та всіх його нащадків (класів, що успадковуються від нього). + +3. **Приватний:** Якщо елемент позначено як `private`, ви можете отримати доступ до нього лише з класу, в якому його було визначено. + +Якщо ви не вкажете видимість, PHP автоматично встановить її на `public`. + +Давайте розглянемо приклад коду: + +```php +class VisibilityExample +{ + public $publicProperty = 'Public'; + protected $protectedProperty = 'Protected'; + private $privateProperty = 'Private'; + + public function printProperties() + { + echo $this->publicProperty; // Works + echo $this->protectedProperty; // Works + echo $this->privateProperty; // Works + } +} + +$object = new VisibilityExample; +$object->printProperties(); +echo $object->publicProperty; // Works +// echo $object->protectedProperty; // Throws an error +// echo $object->privateProperty; // Throws an error +``` + +Продовження успадкування класів: + +```php +class ChildClass extends VisibilityExample +{ + public function printProperties() + { + echo $this->publicProperty; // Works + echo $this->protectedProperty; // Works + // echo $this->privateProperty; // Throws an error + } +} +``` + +У цьому випадку метод `printProperties()` у класі `ChildClass` може отримати доступ до загальнодоступних та захищених властивостей, але не може отримати доступ до приватних властивостей батьківського класу. + +Дані та методи повинні бути максимально прихованими і доступними лише через визначений інтерфейс. Це дозволяє змінювати внутрішню реалізацію класу, не впливаючи на решту коду. + + +Заключне ключове слово .[#toc-final-keyword] +-------------------------------------------- + +У PHP ми можемо використовувати ключове слово `final`, якщо ми хочемо запобігти успадкуванню або перевизначенню класу, методу або константи. Коли клас позначено як `final`, він не може бути розширений. Коли метод позначено як `final`, його не можна перевизначити в підкласі. + +Усвідомлення того, що певний клас або метод більше не буде модифіковано, дозволяє нам легше вносити зміни, не турбуючись про потенційні конфлікти. Наприклад, ми можемо додати новий метод, не боячись, що у нащадка вже може бути метод з такою ж назвою, що призведе до колізії. Або ми можемо змінити параметри методу, знову ж таки без ризику спричинити неузгодженість з перевизначеним методом у нащадка. + +```php +final class FinalClass +{ +} + +// The following code will throw an error because we cannot inherit from a final class. +class ChildOfFinalClass extends FinalClass +{ +} +``` + +У цьому прикладі спроба успадкувати від кінцевого класу `FinalClass` призведе до помилки. + + +Статичні властивості та методи .[#toc-static-properties-and-methods] +-------------------------------------------------------------------- + +Коли ми говоримо про "статичні" елементи класу в PHP, ми маємо на увазі методи і властивості, які належать самому класу, а не конкретному екземпляру класу. Це означає, що вам не потрібно створювати екземпляр класу, щоб отримати до них доступ. Замість цього ви викликаєте або отримуєте доступ до них безпосередньо через ім'я класу. + +Майте на увазі, що оскільки статичні елементи належать класу, а не його екземплярам, ви не можете використовувати псевдо-змінну `$this` всередині статичних методів. + +Використання статичних властивостей призводить до [заплутаного коду, повного підводних каменів |dependency-injection:global-state], тому ви ніколи не повинні використовувати їх, і ми не будемо показувати приклад тут. З іншого боку, статичні методи корисні. Ось приклад: + +```php +class Calculator +{ + public static function add($a, $b) + { + return $a + $b; + } + + public static function subtract($a, $b) + { + return $a - $b; + } +} + +// Using the static method without creating an instance of the class +echo Calculator::add(5, 3); // Output: 8 +echo Calculator::subtract(5, 3); // Output: 2 +``` + +У цьому прикладі ми створили клас `Calculator` з двома статичними методами. Ми можемо викликати ці методи безпосередньо, не створюючи екземпляр класу за допомогою оператора `::`. Статичні методи особливо корисні для операцій, які не залежать від стану конкретного екземпляра класу. + + +Константи класу .[#toc-class-constants] +--------------------------------------- + +У класах ми маємо можливість визначати константи. Константи - це значення, які ніколи не змінюються під час виконання програми. На відміну від змінних, значення константи залишається незмінним. + +```php +class Car +{ + public const NumberOfWheels = 4; + + public function displayNumberOfWheels(): int + { + echo self::NumberOfWheels; + } +} + +echo Car::NumberOfWheels; // Output: 4 +``` + +У цьому прикладі ми маємо клас `Car` з константою `NumberOfWheels`. При зверненні до константи всередині класу ми можемо використовувати ключове слово `self` замість імені класу. + + +Інтерфейси об'єктів .[#toc-object-interfaces] +--------------------------------------------- + +Об'єктні інтерфейси діють як "контракти" для класів. Якщо клас реалізує об'єктний інтерфейс, він повинен містити всі методи, які визначає інтерфейс. Це чудовий спосіб гарантувати, що певні класи дотримуються одного "контракту" або структури. + +У PHP інтерфейси визначаються за допомогою ключового слова `interface`. Всі методи, визначені в інтерфейсі, є загальнодоступними (`public`). Коли клас реалізує інтерфейс, він використовує ключове слово `implements`. + +```php +interface Animal +{ + function makeSound(); +} + +class Cat implements Animal +{ + public function makeSound() + { + echo 'Meow'; + } +} + +$cat = new Cat; +$cat->makeSound(); +``` + +Якщо клас реалізує інтерфейс, але не всі очікувані методи визначені, PHP видасть помилку. Клас може реалізовувати декілька інтерфейсів одночасно, що відрізняється від успадкування, де клас може успадковувати тільки від одного класу. + + +Абстрактні класи .[#toc-abstract-classes] +----------------------------------------- + +Абстрактні класи слугують базовими шаблонами для інших класів, але ви не можете створювати їхні екземпляри безпосередньо. Вони містять суміш повних методів та абстрактних методів, які не мають визначеного змісту. Класи, які успадковують абстрактні класи, повинні надавати визначення для всіх абстрактних методів батьківського класу. + +Ми використовуємо ключове слово `abstract` для визначення абстрактного класу. + +```php +abstract class AbstractClass +{ + public function regularMethod() + { + echo 'This is a regular method'; + } + + abstract public function abstractMethod(); +} + +class Child extends AbstractClass +{ + public function abstractMethod() + { + echo 'This is the implementation of the abstract method'; + } +} + +$instance = new Child; +$instance->regularMethod(); +$instance->abstractMethod(); +``` + +У цьому прикладі ми маємо абстрактний клас з одним звичайним і одним абстрактним методом. Потім у нас є клас `Child`, який успадковується від `AbstractClass` і надає реалізацію для абстрактного методу. + + +Перевірка типів .[#toc-type-checking] +------------------------------------- + +У програмуванні дуже важливо переконатися, що дані, з якими ми працюємо, мають правильний тип. У PHP є інструменти, які забезпечують таку впевненість. Перевірка того, що дані мають правильний тип, називається "перевіркою типу". + +Типи, з якими ми можемо зіткнутися в PHP: + +1. **Базові типи**: До них відносяться `int` (цілі числа), `float` (числа з плаваючою комою), `bool` (логічні значення), `string` (рядки), `array` (масиви) і `null`. +2. **Класи**: Коли ми хочемо, щоб значення було екземпляром певного класу. +3. **Інтерфейси**: Визначає набір методів, які клас повинен реалізувати. Значення, яке відповідає інтерфейсу, повинно мати ці методи. +4. **Змішані типи**: Ми можемо вказати, що змінна може мати декілька дозволених типів. +5. **Немає значення**: Цей спеціальний тип вказує на те, що функція або метод не повертає жодного значення. + +Давайте подивимося, як модифікувати код для включення типів: + +```php +class Person +{ + private int $age; + + public function __construct(int $age) + { + $this->age = $age; + } + + public function printAge(): void + { + echo "This person is " . $this->age . " years old."; + } +} + +/** + * A function that accepts a Person object and prints the person's age. + */ +function printPersonAge(Person $person): void +{ + $person->printAge(); +} +``` + +Таким чином, ми гарантуємо, що наш код очікує і працює з даними правильного типу, що допоможе нам запобігти потенційним помилкам. + + +Порівняння та ідентифікація .[#toc-comparison-and-identity] +----------------------------------------------------------- + +У PHP ви можете порівнювати об'єкти двома способами: + +1. Порівняння значень `==`: Перевіряє, чи об'єкти належать до одного класу і мають однакові значення у своїх властивостях. +2. Ідентифікація `===`: Перевіряє, чи це той самий екземпляр об'єкта. + +```php +class Car +{ + public string $brand; + + public function __construct(string $brand) + { + $this->brand = $brand; + } +} + +$car1 = new Car('Skoda'); +$car2 = new Car('Skoda'); +$car3 = $car1; + +var_dump($car1 == $car2); // true, because they have the same value +var_dump($car1 === $car2); // false, because they are not the same instance +var_dump($car1 === $car3); // true, because $car3 is the same instance as $car1 +``` + + +Оператор `instanceof` .[#toc-the-instanceof-operator] +----------------------------------------------------- + +Оператор `instanceof` дозволяє визначити, чи є даний об'єкт екземпляром певного класу, нащадком цього класу або чи реалізує він певний інтерфейс. + +Уявімо, що у нас є клас `Person` і ще один клас `Student`, який є нащадком класу `Person`: + +```php +class Person +{ + private int $age; + + public function __construct(int $age) + { + $this->age = $age; + } +} + +class Student extends Person +{ + private string $major; + + public function __construct(int $age, string $major) + { + parent::__construct($age); + $this->major = $major; + } +} + +$student = new Student(20, 'Computer Science'); + +// Check if $student is an instance of the Student class +var_dump($student instanceof Student); // Output: bool(true) + +// Check if $student is an instance of the Person class (because Student is a descendant of Person) +var_dump($student instanceof Person); // Output: bool(true) +``` + +З результатів видно, що об'єкт `$student` вважається екземпляром класів `Student` та `Person`. + + +Зручні інтерфейси .[#toc-fluent-interfaces] +------------------------------------------- + +"Вільний інтерфейс" - це техніка в ООП, яка дозволяє об'єднувати методи в ланцюжок в одному виклику. Це часто спрощує і робить код зрозумілішим. + +Ключовим елементом вільного інтерфейсу є те, що кожен метод у ланцюжку повертає посилання на поточний об'єкт. Це досягається за рахунок використання `return $this;` в кінці методу. Цей стиль програмування часто асоціюється з методами, що називаються "сеттерами", які встановлюють значення властивостей об'єкта. + +Давайте подивимося, як може виглядати зручний інтерфейс для надсилання електронних листів: + +```php +public function sendMessage() +{ + $email = new Email; + $email->setFrom('sender@example.com') + ->setRecipient('admin@example.com') + ->setMessage('Hello, this is a message.') + ->send(); +} +``` + +У цьому прикладі методи `setFrom()`, `setRecipient()` і `setMessage()` використовуються для встановлення відповідних значень (відправник, одержувач, зміст повідомлення). Після встановлення кожного з цих значень методи повертають поточний об'єкт (`$email`), що дозволяє нам підключити інший метод після нього. Нарешті, ми викликаємо метод `send()`, який власне і надсилає лист. + +Завдяки вільним інтерфейсам ми можемо писати код, який є інтуїтивно зрозумілим і легко читається. + + +Копіювання за допомогою `clone` .[#toc-copying-with-clone] +---------------------------------------------------------- + +У PHP ми можемо створити копію об'єкта за допомогою оператора `clone`. Таким чином, ми отримуємо новий екземпляр з ідентичним вмістом. + +Якщо при копіюванні об'єкта нам потрібно змінити деякі його властивості, ми можемо визначити в класі спеціальний метод `__clone()`. Цей метод автоматично викликається при клонуванні об'єкта. + +```php +class Sheep +{ + public string $name; + + public function __construct(string $name) + { + $this->name = $name; + } + + public function __clone() + { + $this->name = 'Clone of ' . $this->name; + } +} + +$original = new Sheep('Dolly'); +echo $original->name . "\n"; // Outputs: Dolly + +$clone = clone $original; +echo $clone->name . "\n"; // Outputs: Clone of Dolly +``` + +У нашому прикладі є клас `Sheep` з однією властивістю `$name`. Коли ми клонуємо екземпляр цього класу, метод `__clone()` гарантує, що ім'я клонованої вівці отримає префікс "Clone of". + + +Властивості .[#toc-traits] +-------------------------- + +Риси в PHP - це інструмент, який дозволяє обмінюватися методами, властивостями і константами між класами і запобігає дублюванню коду. Ви можете думати про них як про механізм "копіювання і вставки" (Ctrl-C і Ctrl-V), де вміст трейту "вставляється" в класи. Це дозволяє повторно використовувати код без необхідності створювати складні ієрархії класів. + +Давайте розглянемо простий приклад використання трейтів в PHP: + +```php +trait Honking +{ + public function honk() + { + echo 'Beep beep!'; + } +} + +class Car +{ + use Honking; +} + +class Truck +{ + use Honking; +} + +$car = new Car; +$car->honk(); // Outputs 'Beep beep!' + +$truck = new Truck; +$truck->honk(); // Also outputs 'Beep beep!' +``` + +У цьому прикладі у нас є трейт з іменем `Honking`, який містить один метод `honk()`. Потім у нас є два класи: `Car` і `Truck`, обидва з яких використовують трейта `Honking`. У результаті обидва класи "мають" метод `honk()`, і ми можемо викликати його в об'єктах обох класів. + +Трейти дозволяють легко і ефективно обмінюватися кодом між класами. Вони не входять в ієрархію успадкування, тобто `$car instanceof Honking` поверне `false`. + + +Винятки +------- + +Винятки в ООП дозволяють нам обробляти та керувати помилками, які можуть виникнути під час виконання нашого коду. По суті, це об'єкти, призначені для запису помилок або неочікуваних ситуацій у вашій програмі. + +У PHP для цих об'єктів є вбудований клас `Exception`. Він має кілька методів, які дозволяють отримати більше інформації про виняток, наприклад, повідомлення про помилку, файл, рядок, в якому виникла помилка, тощо. + +Коли виникає проблема, ми можемо "згенерувати" виключення (використовуючи `throw`). Якщо ми хочемо "перехопити" і обробити цей виняток, ми використовуємо блоки `try` і `catch`. + +Давайте подивимося, як це працює: + +```php +try { + throw new Exception('Message explaining the reason for the exception'); + + // This code won't execute + echo 'I am a message that nobody will read'; + +} catch (Exception $e) { + echo 'Exception caught: '. $e->getMessage(); +} +``` + +Важливо зазначити, що виключення може бути згенероване і глибше, під час виклику інших методів. + +Для одного блоку `try` можна вказати декілька блоків `catch`, якщо ви очікуєте різні типи винятків. + +Ми також можемо створити ієрархію винятків, де кожен клас винятків успадковує попередній. Як приклад, розглянемо простий банківський додаток, який дозволяє вносити та знімати кошти: + +```php +class BankingException extends Exception {} +class InsufficientFundsException extends BankingException {} +class ExceededLimitException extends BankingException {} + +class BankAccount +{ + private int $balance = 0; + private int $dailyLimit = 1000; + + public function deposit(int $amount): int + { + $this->balance += $amount; + return $this->balance; + } + + public function withdraw(int $amount): int + { + if ($amount > $this->balance) { + throw new InsufficientFundsException('Not enough funds in the account.'); + } + + if ($amount > $this->dailyLimit) { + throw new ExceededLimitException('Daily withdrawal limit exceeded.'); + } + + $this->balance -= $amount; + return $this->balance; + } +} + +$account = new BankAccount; +$account->deposit(500); + +try { + $account->withdraw(1500); +} catch (ExceededLimitException $e) { + echo $e->getMessage(); +} catch (InsufficientFundsException $e) { + echo $e->getMessage(); +} catch (BankingException $e) { + echo 'An error occurred during the operation.'; +} +``` + +У цьому прикладі важливо звернути увагу на порядок розташування блоків `catch`. Оскільки всі винятки успадковуються від `BankingException`, якби цей блок був першим, то всі винятки були б перехоплені в ньому без того, щоб код дійшов до наступних блоків `catch`. Тому важливо, щоб більш специфічні винятки (тобто ті, що успадковуються від інших) були вище в порядку блоків `catch`, ніж їхні батьківські винятки. + + +Кращі практики .[#toc-best-practices] +------------------------------------- + +Після того, як ви засвоїли основні принципи об'єктно-орієнтованого програмування, дуже важливо зосередитися на найкращих практиках ООП. Вони допоможуть вам писати код, який буде не лише функціональним, але й читабельним, зрозумілим та легко підтримуваним. + +1) **Розподіл обов'язків: Кожен клас повинен мати чітко визначену відповідальність і вирішувати лише одну основну задачу. Якщо клас робить занадто багато речей, може бути доцільно розділити його на менші, спеціалізовані класи. +2) **Інкапсуляція**: Дані та методи повинні бути максимально приховані і доступні лише через визначений інтерфейс. Це дозволяє змінювати внутрішню реалізацію класу, не впливаючи на решту коду. +3) **Ін'єкція залежностей**: Замість того, щоб створювати залежності безпосередньо всередині класу, ви повинні "впорскувати" їх ззовні. Для більш глибокого розуміння цього принципу ми рекомендуємо прочитати [главу про |dependency-injection:introduction] ін'єкцію залежностей. From 470c6137d41987562b7977db33f81496dea57cf9 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 25 Oct 2023 10:19:03 +0200 Subject: [PATCH 028/137] links to oop --- best-practices/bg/@home.texy | 1 + best-practices/bg/form-reuse.texy | 4 ++-- best-practices/bg/presenter-traits.texy | 2 +- best-practices/cs/@home.texy | 1 + best-practices/cs/form-reuse.texy | 4 ++-- best-practices/cs/presenter-traits.texy | 2 +- best-practices/de/@home.texy | 1 + best-practices/de/form-reuse.texy | 4 ++-- best-practices/de/presenter-traits.texy | 2 +- best-practices/el/@home.texy | 1 + best-practices/el/form-reuse.texy | 4 ++-- best-practices/el/presenter-traits.texy | 2 +- best-practices/en/@home.texy | 1 + best-practices/en/form-reuse.texy | 4 ++-- best-practices/en/presenter-traits.texy | 2 +- best-practices/es/@home.texy | 1 + best-practices/es/form-reuse.texy | 4 ++-- best-practices/es/presenter-traits.texy | 2 +- best-practices/fr/@home.texy | 1 + best-practices/fr/form-reuse.texy | 4 ++-- best-practices/fr/presenter-traits.texy | 2 +- best-practices/hu/@home.texy | 1 + best-practices/hu/form-reuse.texy | 4 ++-- best-practices/hu/presenter-traits.texy | 2 +- best-practices/it/@home.texy | 1 + best-practices/it/form-reuse.texy | 4 ++-- best-practices/it/presenter-traits.texy | 2 +- best-practices/pl/@home.texy | 1 + best-practices/pl/form-reuse.texy | 4 ++-- best-practices/pl/presenter-traits.texy | 2 +- best-practices/pt/@home.texy | 1 + best-practices/pt/form-reuse.texy | 4 ++-- best-practices/pt/presenter-traits.texy | 2 +- best-practices/ro/@home.texy | 1 + best-practices/ro/form-reuse.texy | 4 ++-- best-practices/ro/presenter-traits.texy | 2 +- best-practices/ru/@home.texy | 1 + best-practices/ru/form-reuse.texy | 4 ++-- best-practices/ru/presenter-traits.texy | 2 +- best-practices/sl/@home.texy | 1 + best-practices/sl/form-reuse.texy | 4 ++-- best-practices/sl/presenter-traits.texy | 2 +- best-practices/tr/@home.texy | 1 + best-practices/tr/form-reuse.texy | 4 ++-- best-practices/tr/presenter-traits.texy | 2 +- best-practices/uk/@home.texy | 1 + best-practices/uk/form-reuse.texy | 4 ++-- best-practices/uk/presenter-traits.texy | 2 +- database/bg/explorer.texy | 2 +- database/cs/explorer.texy | 2 +- database/de/explorer.texy | 2 +- database/el/explorer.texy | 2 +- database/en/explorer.texy | 2 +- database/es/explorer.texy | 2 +- database/fr/explorer.texy | 2 +- database/hu/explorer.texy | 2 +- database/it/explorer.texy | 2 +- database/pl/explorer.texy | 2 +- database/pt/explorer.texy | 2 +- database/ro/explorer.texy | 2 +- database/ru/explorer.texy | 2 +- database/sl/explorer.texy | 2 +- database/tr/explorer.texy | 2 +- database/uk/explorer.texy | 2 +- dependency-injection/bg/faq.texy | 2 +- dependency-injection/bg/passing-dependencies.texy | 4 ++-- dependency-injection/cs/faq.texy | 2 +- dependency-injection/cs/passing-dependencies.texy | 4 ++-- dependency-injection/de/faq.texy | 2 +- dependency-injection/de/passing-dependencies.texy | 4 ++-- dependency-injection/el/faq.texy | 2 +- dependency-injection/el/passing-dependencies.texy | 4 ++-- dependency-injection/en/faq.texy | 2 +- dependency-injection/en/passing-dependencies.texy | 4 ++-- dependency-injection/es/faq.texy | 2 +- dependency-injection/es/passing-dependencies.texy | 4 ++-- dependency-injection/fr/faq.texy | 2 +- dependency-injection/fr/passing-dependencies.texy | 4 ++-- dependency-injection/hu/faq.texy | 2 +- dependency-injection/hu/passing-dependencies.texy | 4 ++-- dependency-injection/it/faq.texy | 2 +- dependency-injection/it/passing-dependencies.texy | 4 ++-- dependency-injection/ja/faq.texy | 2 +- dependency-injection/ja/passing-dependencies.texy | 4 ++-- dependency-injection/pl/faq.texy | 2 +- dependency-injection/pl/passing-dependencies.texy | 4 ++-- dependency-injection/pt/faq.texy | 2 +- dependency-injection/pt/passing-dependencies.texy | 4 ++-- dependency-injection/ro/faq.texy | 2 +- dependency-injection/ro/passing-dependencies.texy | 4 ++-- dependency-injection/ru/faq.texy | 2 +- dependency-injection/ru/passing-dependencies.texy | 4 ++-- dependency-injection/sl/faq.texy | 2 +- dependency-injection/sl/passing-dependencies.texy | 4 ++-- dependency-injection/tr/faq.texy | 2 +- dependency-injection/tr/passing-dependencies.texy | 4 ++-- dependency-injection/uk/faq.texy | 2 +- dependency-injection/uk/passing-dependencies.texy | 4 ++-- quickstart/bg/@home.texy | 2 +- quickstart/cs/@home.texy | 2 +- quickstart/de/@home.texy | 2 +- quickstart/el/@home.texy | 2 +- quickstart/en/@home.texy | 2 +- quickstart/es/@home.texy | 2 +- quickstart/fr/@home.texy | 2 +- quickstart/hu/@home.texy | 2 +- quickstart/it/@home.texy | 2 +- quickstart/pl/@home.texy | 2 +- quickstart/pt/@home.texy | 2 +- quickstart/ro/@home.texy | 2 +- quickstart/ru/@home.texy | 2 +- quickstart/sl/@home.texy | 2 +- quickstart/tr/@home.texy | 2 +- quickstart/uk/@home.texy | 2 +- 114 files changed, 147 insertions(+), 131 deletions(-) diff --git a/best-practices/bg/@home.texy b/best-practices/bg/@home.texy index d8d9850d9b..2fc7fff5c7 100644 --- a/best-practices/bg/@home.texy +++ b/best-practices/bg/@home.texy @@ -41,6 +41,7 @@ - [Защо Nette не използва суфикса Interface? |https://blog.nette.org/bg/prefiksite-i-sufiksite-ne-prinadlezat-na-imenata-na-interfejsite] - [Съвети за използване на Composer |composer] - [Съвети за редактори и инструменти |editors-and-tools] +- [Въведение в обектно-ориентираното програмиране |nette:introduction-to-object-oriented-programming]
    diff --git a/best-practices/bg/form-reuse.texy b/best-practices/bg/form-reuse.texy index 9470a63875..43a4554915 100644 --- a/best-practices/bg/form-reuse.texy +++ b/best-practices/bg/form-reuse.texy @@ -152,7 +152,7 @@ class EditFormFactory } ``` -Много е важно обвързването между класовете `FormFactory` и `EditFormFactory` да се реализира чрез композиция, а не чрез наследяване на обекти: +Много е важно връзката между класовете `FormFactory` и `EditFormFactory` да се осъществява [чрез композиция |nette:introduction-to-object-oriented-programming#composition], а не [чрез |nette:introduction-to-object-oriented-programming#composition] [наследяване на обекти |https://doc.nette.org/en/introduction-to-object-oriented-programming#inheritance]: ```php // ⛔ НЕ! НАСЛЕДСТВОТО НЕ ПРИНАДЛЕЖИ ТУК @@ -172,7 +172,7 @@ class EditFormFactory extends FormFactory Използването на наследяване в този случай би било напълно непродуктивно. Много бързо ще се сблъскате с проблеми. Например, ако искате да добавите параметри към метода `create()`; PHP ще отчете грешка, че сигнатурата му е различна от тази на родителя. Или при предаване на зависимост на класа `EditFormFactory` чрез конструктора. Това би довело до това, което наричаме " [ад на конструкторите" |dependency-injection:passing-dependencies#Constructor hell]. -Като цяло е по-добре да се предпочита композицията пред наследяването. +Като цяло е по-добре да се предпочита [композицията пред наследяването |dependency-injection:faq#Why composition is preferred over inheritance]. Обработка на формуляри .[#toc-form-handling] diff --git a/best-practices/bg/presenter-traits.texy b/best-practices/bg/presenter-traits.texy index 0c4c5e8fed..54d39734cc 100644 --- a/best-practices/bg/presenter-traits.texy +++ b/best-practices/bg/presenter-traits.texy @@ -2,7 +2,7 @@ **************************** .[perex] -Ако трябва да приложим един и същ код в няколко презентатора (например проверка дали потребителят е влязъл в системата), изкушаващо е да поставим този код в общ предшественик. Вторият вариант е да се създадат едноцелеви признаци. +Ако трябва да приложим един и същ код в няколко презентатора (например проверка дали потребителят е влязъл в системата), изкушаващо е да поставим кода в общ предшественик. Втората възможност е да се създадат едноцелеви [черти |nette:introduction-to-object-oriented-programming#traits]. Предимството на това решение е, че всеки презентатор може да използва само чертите, от които действително се нуждае, докато в PHP не е възможно многократно наследяване. diff --git a/best-practices/cs/@home.texy b/best-practices/cs/@home.texy index b6fdd39ffc..d73d685a15 100644 --- a/best-practices/cs/@home.texy +++ b/best-practices/cs/@home.texy @@ -41,6 +41,7 @@ Obecné - [Proč Nette nepoužívá příponu Interface? |https://blog.nette.org/cs/predpony-a-pripony-do-nazvu-rozhrani-nepatri] - [Composer: tipy pro použití |composer] - [Tipy na editory & nástroje |editors-and-tools] +- [Úvod do objektově orientovaného programování |nette:introduction-to-object-oriented-programming]
    diff --git a/best-practices/cs/form-reuse.texy b/best-practices/cs/form-reuse.texy index c659b8bcb4..35a4b1dc04 100644 --- a/best-practices/cs/form-reuse.texy +++ b/best-practices/cs/form-reuse.texy @@ -152,7 +152,7 @@ class EditFormFactory } ``` -Velmi důležité je, aby vazba mezi třídami `FormFactory` a `EditFormFactory` byla realizována kompozicí, nikoliv objektovou dědičností: +Velmi důležité je, aby vazba mezi třídami `FormFactory` a `EditFormFactory` byla realizována [kompozicí|nette:introduction-to-object-oriented-programming#kompozice], nikoliv [objektovou dědičností|https://doc.nette.org/cs/introduction-to-object-oriented-programming#dedicnost]: ```php // ⛔ TAKHLE NE! SEM DĚDIČNOST NEPATŘÍ @@ -172,7 +172,7 @@ class EditFormFactory extends FormFactory Použití dedičnosti by bylo v tomto případě zcela kontraproduktivní. Na problémy byste narazili velmi rychle. Třeba ve chvíli, kdybyste chtěli přidat metodě `create()` parametry; PHP by zahlásilo chybu, že se její signatura liší od rodičovské. Nebo při předávání závislosti do třídy `EditFormFactory` přes konstruktor. Nastala by situace, které říkáme [constructor hell |dependency-injection:passing-dependencies#Constructor hell]. -Obecně je lepší dávat přednost kompozici před dědičností. +Obecně je lepší dávat přednost [kompozici před dědičností|dependency-injection:faq#Proč se upřednostňuje kompozice před dědičností]. Obsluha formuláře diff --git a/best-practices/cs/presenter-traits.texy b/best-practices/cs/presenter-traits.texy index 56c6ba8dfd..06ff9b3063 100644 --- a/best-practices/cs/presenter-traits.texy +++ b/best-practices/cs/presenter-traits.texy @@ -2,7 +2,7 @@ Skládání presenterů z trait *************************** .[perex] -Pokud potřebujeme ve více presenterech implementovat stejný kód (např. ověření, že je uživatel přihlášen), nabízí se umístit kód do společného předka. Druhou možností je vytvoření jednoúčelových trait. +Pokud potřebujeme ve více presenterech implementovat stejný kód (např. ověření, že je uživatel přihlášen), nabízí se umístit kód do společného předka. Druhou možností je vytvoření jednoúčelových [trait|nette:introduction-to-object-oriented-programming#traity]. Výhoda tohoto řešení je, že každý z presenterů může použít právě ty traity, které skutečně potřebuje, zatímco vícenásobná dědičnost není v PHP možná. diff --git a/best-practices/de/@home.texy b/best-practices/de/@home.texy index 20b2d44538..e5441f840e 100644 --- a/best-practices/de/@home.texy +++ b/best-practices/de/@home.texy @@ -41,6 +41,7 @@ Allgemein - [Warum verwendet Nette nicht das Suffix Interface? |https://blog.nette.org/de/praefixe-und-suffixe-gehoeren-nicht-in-schnittstellennamen] - [Tipps zur Verwendung des Composers |composer] - [Tipps zu Editoren und Tools |editors-and-tools] +- [Einführung in die objektorientierte Programmierung |nette:introduction-to-object-oriented-programming]
    diff --git a/best-practices/de/form-reuse.texy b/best-practices/de/form-reuse.texy index 08cc17d64f..c37f954138 100644 --- a/best-practices/de/form-reuse.texy +++ b/best-practices/de/form-reuse.texy @@ -152,7 +152,7 @@ class EditFormFactory } ``` -Es ist sehr wichtig, dass die Bindung zwischen den Klassen `FormFactory` und `EditFormFactory` durch Komposition und nicht durch Objektvererbung implementiert wird: +Es ist sehr wichtig, dass die Bindung zwischen den Klassen `FormFactory` und `EditFormFactory` [durch Komposition |nette:introduction-to-object-oriented-programming#composition] und nicht [durch |nette:introduction-to-object-oriented-programming#composition] [Objektvererbung |https://doc.nette.org/en/introduction-to-object-oriented-programming#inheritance] implementiert wird: ```php // ⛔ NEIN! VERERBUNG GEHÖRT HIER NICHT HIN @@ -172,7 +172,7 @@ class EditFormFactory extends FormFactory Die Verwendung von Vererbung wäre in diesem Fall völlig kontraproduktiv. Sie würden sehr schnell auf Probleme stoßen. Wenn Sie z.B. der Methode `create()` Parameter hinzufügen wollten, würde PHP einen Fehler melden, dass sich die Signatur der Methode von der des Elternteils unterscheidet. Oder bei der Übergabe einer Abhängigkeit an die Klasse `EditFormFactory` über den Konstruktor. Dies würde zu dem führen, was wir [Konstruktorhölle |dependency-injection:passing-dependencies#Constructor hell] nennen. -Im Allgemeinen ist es besser, Komposition der Vererbung vorzuziehen. +Im Allgemeinen ist es besser, die [Komposition der Vererbung |dependency-injection:faq#Why composition is preferred over inheritance] vorzuziehen. Handhabung von Formularen .[#toc-form-handling] diff --git a/best-practices/de/presenter-traits.texy b/best-practices/de/presenter-traits.texy index 41b4d98037..807e21e31f 100644 --- a/best-practices/de/presenter-traits.texy +++ b/best-practices/de/presenter-traits.texy @@ -2,7 +2,7 @@ Zusammenstellung von Moderatoren aus Merkmalen ********************************************** .[perex] -Wenn wir denselben Code in mehreren Presentern implementieren müssen (z. B. die Überprüfung, ob der Benutzer angemeldet ist), ist es verlockend, den Code in einem gemeinsamen Vorgänger zu platzieren. Die zweite Möglichkeit ist die Erstellung von Single-Purpose-Traits. +Wenn wir denselben Code in mehreren Presentern implementieren müssen (z. B. die Überprüfung, ob der Benutzer angemeldet ist), ist es verlockend, den Code in einem gemeinsamen Vorgänger zu platzieren. Die zweite Möglichkeit besteht darin, [Einzweck-Traits |nette:introduction-to-object-oriented-programming#traits] zu erstellen. Der Vorteil dieser Lösung ist, dass jeder Präsentator nur die Traits verwenden kann, die er tatsächlich benötigt, während Mehrfachvererbung in PHP nicht möglich ist. diff --git a/best-practices/el/@home.texy b/best-practices/el/@home.texy index e3df7ffbb0..2bd3ed9000 100644 --- a/best-practices/el/@home.texy +++ b/best-practices/el/@home.texy @@ -41,6 +41,7 @@ - [Γιατί η Nette δεν χρησιμοποιεί την κατάληξη Interface; |https://blog.nette.org/el/ta-prothemata-kai-ta-epithemata-den-anekoun-sta-onomata-diasyndeses] - [Συμβουλές χρήσης του Composer |composer] - [Συμβουλές για επεξεργαστές & εργαλεία |editors-and-tools] +- [Εισαγωγή στον αντικειμενοστραφή προγραμματισμό |nette:introduction-to-object-oriented-programming]
    diff --git a/best-practices/el/form-reuse.texy b/best-practices/el/form-reuse.texy index ec91ec79e1..afc0397dff 100644 --- a/best-practices/el/form-reuse.texy +++ b/best-practices/el/form-reuse.texy @@ -152,7 +152,7 @@ class EditFormFactory } ``` -Είναι πολύ σημαντικό ότι η σύνδεση μεταξύ των κλάσεων `FormFactory` και `EditFormFactory` υλοποιείται με σύνθεση και όχι με κληρονομικότητα αντικειμένων: +Είναι πολύ σημαντικό ότι η σύνδεση μεταξύ των κλάσεων `FormFactory` και `EditFormFactory` υλοποιείται [με σύνθεση |nette:introduction-to-object-oriented-programming#composition] και όχι με [κληρονομικότητα αντικειμένων |https://doc.nette.org/en/introduction-to-object-oriented-programming#inheritance]: ```php // ⛔ ΟΧΙ! Η ΚΛΗΡΟΝΟΜΙΆ ΔΕΝ ΑΝΉΚΕΙ ΕΔΏ @@ -172,7 +172,7 @@ class EditFormFactory extends FormFactory Η χρήση κληρονομικότητας σε αυτή την περίπτωση θα ήταν εντελώς αντιπαραγωγική. Θα αντιμετωπίζατε προβλήματα πολύ γρήγορα. Για παράδειγμα, αν θέλατε να προσθέσετε παραμέτρους στη μέθοδο `create()`, η PHP θα ανέφερε ένα σφάλμα ότι η υπογραφή της ήταν διαφορετική από την υπογραφή του γονέα. Ή όταν περνούσατε μια εξάρτηση στην κλάση `EditFormFactory` μέσω του κατασκευαστή. Αυτό θα προκαλούσε αυτό που ονομάζουμε [κόλαση του κατασκευαστή |dependency-injection:passing-dependencies#Constructor hell]. -Γενικά, είναι προτιμότερο να προτιμάτε τη σύνθεση από την κληρονομικότητα. +Είναι γενικά προτιμότερο να προτιμάτε τη [σύνθεση από την κληρονομικότητα |dependency-injection:faq#Why composition is preferred over inheritance]. Χειρισμός φόρμας .[#toc-form-handling] diff --git a/best-practices/el/presenter-traits.texy b/best-practices/el/presenter-traits.texy index dcfda68d36..fad19dba1f 100644 --- a/best-practices/el/presenter-traits.texy +++ b/best-practices/el/presenter-traits.texy @@ -2,7 +2,7 @@ *********************************** .[perex] -Αν πρέπει να υλοποιήσουμε τον ίδιο κώδικα σε πολλούς παρουσιαστές (π.χ. επαλήθευση ότι ο χρήστης είναι συνδεδεμένος), είναι δελεαστικό να τοποθετήσουμε τον κώδικα σε έναν κοινό πρόγονο. Η δεύτερη επιλογή είναι να δημιουργήσουμε γνωρίσματα ενός σκοπού. +Εάν πρέπει να υλοποιήσουμε τον ίδιο κώδικα σε πολλούς παρουσιαστές (π.χ. επαλήθευση ότι ο χρήστης είναι συνδεδεμένος), είναι δελεαστικό να τοποθετήσουμε τον κώδικα σε έναν κοινό πρόγονο. Η δεύτερη επιλογή είναι η δημιουργία [χαρακτηριστικών |nette:introduction-to-object-oriented-programming#traits] ενός μόνο σκοπού. Το πλεονέκτημα αυτής της λύσης είναι ότι κάθε παρουσιαστής μπορεί να χρησιμοποιήσει μόνο τα γνωρίσματα που πραγματικά χρειάζεται, ενώ η πολλαπλή κληρονομικότητα δεν είναι δυνατή στην PHP. diff --git a/best-practices/en/@home.texy b/best-practices/en/@home.texy index a83fdeb24e..ce571c17e7 100644 --- a/best-practices/en/@home.texy +++ b/best-practices/en/@home.texy @@ -41,6 +41,7 @@ Common - [Why Nette doesn't use the Interface suffix? |https://blog.nette.org/en/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer usage tips |composer] - [Tips on editors & tools |editors-and-tools] +- [Introduction to object-oriented programming |nette:introduction-to-object-oriented-programming]
    diff --git a/best-practices/en/form-reuse.texy b/best-practices/en/form-reuse.texy index 176a6cb783..e78e11f1ee 100644 --- a/best-practices/en/form-reuse.texy +++ b/best-practices/en/form-reuse.texy @@ -152,7 +152,7 @@ class EditFormFactory } ``` -It is very important that the binding between the `FormFactory` and `EditFormFactory` classes is implemented by composition, not object inheritance: +It is very important that the binding between the `FormFactory` and `EditFormFactory` classes is implemented [by composition |nette:introduction-to-object-oriented-programming#composition], not [object inheritance |https://doc.nette.org/en/introduction-to-object-oriented-programming#inheritance]: ```php // ⛔ NO! INHERITANCE DOESN'T BELONG HERE @@ -172,7 +172,7 @@ class EditFormFactory extends FormFactory Using inheritance in this case would be completely counterproductive. You would run into problems very quickly. For example, if you wanted to add parameters to the `create()` method; PHP would report an error that its signature was different from the parent. Or when passing a dependency to the `EditFormFactory` class via the constructor. This would cause what we call [constructor hell |dependency-injection:passing-dependencies#Constructor hell]. -In general, it is better to prefer composition over inheritance. +It is generally better to prefer [composition over inheritance |dependency-injection:faq#Why composition is preferred over inheritance]. Form Handling diff --git a/best-practices/en/presenter-traits.texy b/best-practices/en/presenter-traits.texy index 15edbdb7bd..051c3c0a7e 100644 --- a/best-practices/en/presenter-traits.texy +++ b/best-practices/en/presenter-traits.texy @@ -2,7 +2,7 @@ Composing Presenters from Traits ******************************** .[perex] -If we need to implement the same code in multiple presenters (e.g. verification that the user is logged in), it is tempting to place the code in a common ancestor. The second option is to create single-purpose traits. +If we need to implement the same code in multiple presenters (e.g. verification that the user is logged in), it is tempting to place the code in a common ancestor. The second option is to create single-purpose [traits |nette:introduction-to-object-oriented-programming#traits]. The advantage of this solution is that each presenter can use just the traits it actually needs, while multiple inheritance is not possible in PHP. diff --git a/best-practices/es/@home.texy b/best-practices/es/@home.texy index 2b8c641620..af06cd4c02 100644 --- a/best-practices/es/@home.texy +++ b/best-practices/es/@home.texy @@ -41,6 +41,7 @@ Común - [¿Por qué Nette no utiliza el sufijo Interface? |https://blog.nette.org/es/los-prefijos-y-sufijos-no-pertenecen-a-los-nombres-de-interfaz] - [Consejos de uso de Composer |composer] - [Consejos sobre editores y herramientas |editors-and-tools] +- [Introducción a la programación orientada a objetos |nette:introduction-to-object-oriented-programming]
    diff --git a/best-practices/es/form-reuse.texy b/best-practices/es/form-reuse.texy index 12e62fa802..ae9c25920a 100644 --- a/best-practices/es/form-reuse.texy +++ b/best-practices/es/form-reuse.texy @@ -152,7 +152,7 @@ class EditFormFactory } ``` -Es muy importante que la unión entre las clases `FormFactory` y `EditFormFactory` se implemente por composición, no por herencia de objetos: +Es muy importante que la unión entre las clases `FormFactory` y `EditFormFactory` se implemente [por composición |nette:introduction-to-object-oriented-programming#composition], no por [herencia de objetos |https://doc.nette.org/en/introduction-to-object-oriented-programming#inheritance]: ```php // ⛔ ¡NO! LA HERENCIA NO PERTENECE AQUÍ @@ -172,7 +172,7 @@ class EditFormFactory extends FormFactory Utilizar la herencia en este caso sería totalmente contraproducente. Se encontraría con problemas muy rápidamente. Por ejemplo, si quisiera agregar parámetros al método `create()`; PHP reportaría un error de que su firma es diferente a la del padre. O al pasar una dependencia a la clase `EditFormFactory` a través del constructor. Esto causaría lo que llamamos el infierno del [constructor |dependency-injection:passing-dependencies#Constructor hell]. -En general, es mejor preferir la composición a la herencia. +En general, es mejor preferir la [composición a la herencia |dependency-injection:faq#Why composition is preferred over inheritance]. Manejo de Formularios .[#toc-form-handling] diff --git a/best-practices/es/presenter-traits.texy b/best-practices/es/presenter-traits.texy index a50e8ec4e1..edcde6568c 100644 --- a/best-practices/es/presenter-traits.texy +++ b/best-practices/es/presenter-traits.texy @@ -2,7 +2,7 @@ Composición de presentadores a partir de rasgos *********************************************** .[perex] -Si necesitamos implementar el mismo código en varios presentadores (por ejemplo, verificar que el usuario ha iniciado sesión), resulta tentador colocar el código en un ancestro común. La segunda opción es crear rasgos de propósito único. +Si necesitamos implementar el mismo código en varios presentadores (por ejemplo, la verificación de que el usuario ha iniciado sesión), resulta tentador colocar el código en un ancestro común. La segunda opción es crear [rasgos |nette:introduction-to-object-oriented-programming#traits] de propósito único. La ventaja de esta solución es que cada presentador puede utilizar sólo los rasgos que realmente necesita, mientras que la herencia múltiple no es posible en PHP. diff --git a/best-practices/fr/@home.texy b/best-practices/fr/@home.texy index 2721f09ca9..e1d47f5c05 100644 --- a/best-practices/fr/@home.texy +++ b/best-practices/fr/@home.texy @@ -41,6 +41,7 @@ Commun - [Pourquoi Nette n'utilise pas le suffixe Interface ? |https://blog.nette.org/fr/les-prefixes-et-les-suffixes-n-ont-pas-leur-place-dans-les-noms-d-interface] - [Conseils d'utilisation de Composer |composer] - [Conseils sur les éditeurs et les outils |editors-and-tools] +- [Introduction à la programmation orientée objet |nette:introduction-to-object-oriented-programming]
    diff --git a/best-practices/fr/form-reuse.texy b/best-practices/fr/form-reuse.texy index a5a2829f81..4589e497c0 100644 --- a/best-practices/fr/form-reuse.texy +++ b/best-practices/fr/form-reuse.texy @@ -152,7 +152,7 @@ class EditFormFactory } ``` -Il est très important que la liaison entre les classes `FormFactory` et `EditFormFactory` soit mise en œuvre par composition et non par héritage d'objets : +Il est très important que la liaison entre les classes `FormFactory` et `EditFormFactory` soit mise en œuvre [par composition |nette:introduction-to-object-oriented-programming#composition] et non par [héritage d'objets |https://doc.nette.org/en/introduction-to-object-oriented-programming#inheritance]: ```php // ⛔ NO ! L'HÉRITAGE N'A PAS SA PLACE ICI @@ -172,7 +172,7 @@ class EditFormFactory extends FormFactory L'utilisation de l'héritage dans ce cas serait totalement contre-productive. Vous rencontreriez des problèmes très rapidement. Par exemple, si vous vouliez ajouter des paramètres à la méthode `create()`, PHP signalerait une erreur parce que sa signature est différente de celle du parent. Ou lorsque vous passez une dépendance à la classe `EditFormFactory` via le constructeur. Cela provoquerait ce que nous appelons l'[enfer du constructeur |dependency-injection:passing-dependencies#Constructor hell]. -En général, il est préférable de préférer la composition à l'héritage. +Il est généralement préférable de préférer la [composition à l'héritage |dependency-injection:faq#Why composition is preferred over inheritance]. Traitement des formulaires .[#toc-form-handling] diff --git a/best-practices/fr/presenter-traits.texy b/best-practices/fr/presenter-traits.texy index ad30804c3c..ccc278ef83 100644 --- a/best-practices/fr/presenter-traits.texy +++ b/best-practices/fr/presenter-traits.texy @@ -2,7 +2,7 @@ Composer des présentateurs à partir de traits ********************************************* .[perex] -Si nous devons implémenter le même code dans plusieurs présentateurs (par exemple, vérifier que l'utilisateur est connecté), il est tentant de placer le code dans un ancêtre commun. La deuxième option consiste à créer des traits à usage unique. +Si nous devons mettre en œuvre le même code dans plusieurs présentateurs (par exemple, vérifier que l'utilisateur est connecté), il est tentant de placer le code dans un ancêtre commun. La deuxième option consiste à créer des [traits |nette:introduction-to-object-oriented-programming#traits] à usage unique. L'avantage de cette solution est que chaque présentateur peut utiliser uniquement les traits dont il a réellement besoin, alors que l'héritage multiple n'est pas possible en PHP. diff --git a/best-practices/hu/@home.texy b/best-practices/hu/@home.texy index b647c32f9f..b1ebc4d490 100644 --- a/best-practices/hu/@home.texy +++ b/best-practices/hu/@home.texy @@ -41,6 +41,7 @@ Közös - [Miért nem használja a Nette az Interface utótagot? |https://blog.nette.org/hu/az-elotagok-es-utotagok-nem-tartoznak-az-interfesznevekbe] - [Composer használati tippek |composer] - [Tippek a szerkesztőkhöz és eszközökhöz |editors-and-tools] +- [Bevezetés az objektumorientált programozásba |nette:introduction-to-object-oriented-programming]
    diff --git a/best-practices/hu/form-reuse.texy b/best-practices/hu/form-reuse.texy index 9245624d97..1c4b0fbeb8 100644 --- a/best-practices/hu/form-reuse.texy +++ b/best-practices/hu/form-reuse.texy @@ -152,7 +152,7 @@ class EditFormFactory } ``` -Nagyon fontos, hogy a `FormFactory` és a `EditFormFactory` osztályok közötti kötés kompozícióval, nem pedig objektumörökléssel valósuljon meg: +Nagyon fontos, hogy a `FormFactory` és a `EditFormFactory` osztályok közötti kötés [kompozícióval |nette:introduction-to-object-oriented-programming#composition], nem pedig [objektumörökléssel |https://doc.nette.org/en/introduction-to-object-oriented-programming#inheritance] valósul meg: ```php // ⛔ NO! AZ ÖRÖKSÉG NEM TARTOZIK IDE @@ -172,7 +172,7 @@ class EditFormFactory extends FormFactory Az öröklés használata ebben az esetben teljesen kontraproduktív lenne. Nagyon gyorsan problémákba ütközne. Például, ha paramétereket akarnánk hozzáadni a `create()` metódushoz; a PHP hibát jelezne, hogy a metódus aláírása eltér a szülőétől. Vagy ha a konstruktoron keresztül átadnánk egy függőséget a `EditFormFactory` osztálynak. Ez azt okozná, amit mi [konstruktor pokolnak |dependency-injection:passing-dependencies#Constructor hell] hívunk. -Általánosságban elmondható, hogy jobb a kompozíciót előnyben részesíteni az örökléssel szemben. +Általában jobb, ha a [kompozíciót |dependency-injection:faq#Why composition is preferred over inheritance] előnyben részesítjük az [örökléssel szemben |dependency-injection:faq#Why composition is preferred over inheritance]. Form kezelés .[#toc-form-handling] diff --git a/best-practices/hu/presenter-traits.texy b/best-practices/hu/presenter-traits.texy index 15a65bf31f..7e1c996e54 100644 --- a/best-practices/hu/presenter-traits.texy +++ b/best-practices/hu/presenter-traits.texy @@ -2,7 +2,7 @@ Előadók összeállítása tulajdonságokból ************************************** .[perex] -Ha ugyanazt a kódot több prezenterben kell implementálnunk (pl. annak ellenőrzése, hogy a felhasználó be van-e jelentkezve), akkor csábító, hogy a kódot egy közös ősben helyezzük el. A második lehetőség az egycélú tulajdonságok létrehozása. +Ha ugyanazt a kódot több prezenterben kell implementálnunk (pl. annak ellenőrzése, hogy a felhasználó be van-e jelentkezve), akkor csábító, hogy a kódot egy közös ősben helyezzük el. A második lehetőség az egycélú [tulajdonságok |nette:introduction-to-object-oriented-programming#traits] létrehozása. Ennek a megoldásnak az az előnye, hogy minden egyes prezenter csak azokat a tulajdonságokat használhatja, amelyekre ténylegesen szüksége van, míg a többszörös öröklés nem lehetséges a PHP-ben. diff --git a/best-practices/it/@home.texy b/best-practices/it/@home.texy index bb15638c9d..8e5ea66057 100644 --- a/best-practices/it/@home.texy +++ b/best-practices/it/@home.texy @@ -41,6 +41,7 @@ Comune - [Perché Nette non usa il suffisso Interface? |https://blog.nette.org/it/i-prefissi-e-i-suffissi-non-appartengono-ai-nomi-delle-interfacce] - [Suggerimenti per l'uso di Composer |composer] - [Suggerimenti su editor e strumenti |editors-and-tools] +- [Introduzione alla programmazione orientata agli oggetti |nette:introduction-to-object-oriented-programming]
    diff --git a/best-practices/it/form-reuse.texy b/best-practices/it/form-reuse.texy index 26e0e30dbb..10cdc42fce 100644 --- a/best-practices/it/form-reuse.texy +++ b/best-practices/it/form-reuse.texy @@ -152,7 +152,7 @@ class EditFormFactory } ``` -È molto importante che il legame tra le classi `FormFactory` e `EditFormFactory` sia implementato tramite composizione, non tramite ereditarietà degli oggetti: +È molto importante che il legame tra le classi `FormFactory` e `EditFormFactory` sia implementato [tramite composizione |nette:introduction-to-object-oriented-programming#composition] e non tramite [ereditarietà degli oggetti |https://doc.nette.org/en/introduction-to-object-oriented-programming#inheritance]: ```php // NO! L'EREDITÀ NON È QUI @@ -172,7 +172,7 @@ class EditFormFactory extends FormFactory L'uso dell'ereditarietà in questo caso sarebbe completamente controproducente. Si incorrerebbe in problemi molto rapidamente. Per esempio, se si volessero aggiungere parametri al metodo `create()`, PHP segnalerebbe un errore perché la sua firma è diversa da quella del genitore. Oppure quando si passa una dipendenza alla classe `EditFormFactory` tramite il costruttore. Questo causerebbe quello che chiamiamo l'[inferno dei costruttori |dependency-injection:passing-dependencies#Constructor hell]. -In generale, è meglio preferire la composizione all'ereditarietà. +In genere è meglio preferire la [composizione all'ereditarietà |dependency-injection:faq#Why composition is preferred over inheritance]. Gestione dei moduli .[#toc-form-handling] diff --git a/best-practices/it/presenter-traits.texy b/best-practices/it/presenter-traits.texy index 4837d5769c..9e10beab70 100644 --- a/best-practices/it/presenter-traits.texy +++ b/best-practices/it/presenter-traits.texy @@ -2,7 +2,7 @@ Comporre i presentatori dai tratti ********************************** .[perex] -Se occorre implementare lo stesso codice in più presentatori (ad esempio, la verifica che l'utente sia loggato), si è tentati di collocare il codice in un antenato comune. La seconda opzione è quella di creare tratti a scopo singolo. +Se abbiamo bisogno di implementare lo stesso codice in più presentatori (ad esempio, la verifica che l'utente sia connesso), siamo tentati di collocare il codice in un antenato comune. La seconda opzione è quella di creare [tratti |nette:introduction-to-object-oriented-programming#traits] a scopo singolo. Il vantaggio di questa soluzione è che ogni presentatore può utilizzare solo i tratti di cui ha effettivamente bisogno, mentre l'ereditarietà multipla non è possibile in PHP. diff --git a/best-practices/pl/@home.texy b/best-practices/pl/@home.texy index 71e32b1075..0b27f218c9 100644 --- a/best-practices/pl/@home.texy +++ b/best-practices/pl/@home.texy @@ -41,6 +41,7 @@ Wspólne - [Dlaczego Nette nie używa przyrostka Interface? |https://blog.nette.org/pl/przedrostki-i-przyrostki-nie-sa-czescia-nazw-interfejsow] - [Kompozytor: wskazówki dotyczące użytkowania |composer] - [Porady dotyczące edytorów i narzędzi |editors-and-tools] +- [Wprowadzenie do programowania obiektowego |nette:introduction-to-object-oriented-programming]
    diff --git a/best-practices/pl/form-reuse.texy b/best-practices/pl/form-reuse.texy index 46ee665dec..28412b73b6 100644 --- a/best-practices/pl/form-reuse.texy +++ b/best-practices/pl/form-reuse.texy @@ -152,7 +152,7 @@ class EditFormFactory } ``` -Bardzo ważne jest, że wiązanie między klasami `FormFactory` i `EditFormFactory` jest realizowane przez kompozycję, a nie dziedziczenie obiektów: +Bardzo ważne jest, aby powiązanie między klasami `FormFactory` i `EditFormFactory` było realizowane [przez kompozycję |nette:introduction-to-object-oriented-programming#composition], a nie [dziedziczenie obiektów |https://doc.nette.org/en/introduction-to-object-oriented-programming#inheritance]: ```php // ⛔ NIE! DZIEDZICZENIE NIE NALEŻY DO TEGO MIEJSCA @@ -172,7 +172,7 @@ class EditFormFactory extends FormFactory Używanie dziedziczenia w tym przypadku byłoby całkowicie przeciwne do zamierzonego. Bardzo szybko napotkałbyś problemy. Na przykład, gdybyś chciał dodać parametry do metody `create()`; PHP zgłosiłoby błąd, że jej podpis jest inny niż rodzica. Albo podczas przekazywania zależności do klasy `EditFormFactory` poprzez konstruktor. To spowodowałoby coś, co nazywamy [piekłem konstru |dependency-injection:passing-dependencies#Constructor hell]ktora. -Ogólnie rzecz biorąc, lepiej jest preferować kompozycję niż dziedziczenie. +Ogólnie rzecz biorąc, lepiej jest preferować [kompozycję niż dziedziczenie |dependency-injection:faq#Why composition is preferred over inheritance]. Obsługa formularzy .[#toc-form-handling] diff --git a/best-practices/pl/presenter-traits.texy b/best-practices/pl/presenter-traits.texy index 577763646c..9a5976a811 100644 --- a/best-practices/pl/presenter-traits.texy +++ b/best-practices/pl/presenter-traits.texy @@ -2,7 +2,7 @@ Komponowanie prezenterów z cech ******************************* .[perex] -Jeśli potrzebujemy zaimplementować ten sam kod w wielu prezenterach (np. w celu sprawdzenia, czy użytkownik jest zalogowany), sugeruje się umieszczenie kodu we wspólnym przodku. Inną opcją jest tworzenie cech jednozadaniowych. +Jeśli musimy zaimplementować ten sam kod w wielu prezenterach (np. weryfikacja, czy użytkownik jest zalogowany), kuszące jest umieszczenie kodu we wspólnym przodku. Drugą opcją jest stworzenie [cech |nette:introduction-to-object-oriented-programming#traits] jednego przeznaczenia. Zaletą tego rozwiązania jest to, że każdy prezenter może używać tylko cech, których faktycznie potrzebuje, podczas gdy wielokrotne dziedziczenie nie jest możliwe w PHP. diff --git a/best-practices/pt/@home.texy b/best-practices/pt/@home.texy index 6eba10e4ea..d7f8866044 100644 --- a/best-practices/pt/@home.texy +++ b/best-practices/pt/@home.texy @@ -41,6 +41,7 @@ Comum - [Por que Nette não usa o sufixo Interface? |https://blog.nette.org/pt/prefixos-e-sufixos-nao-pertencem-a-nomes-de-interface] - [Dicas de uso do compositor |composer] - [Dicas sobre editores e ferramentas |editors-and-tools] +- [Introdução à programação orientada a objetos |nette:introduction-to-object-oriented-programming]
    diff --git a/best-practices/pt/form-reuse.texy b/best-practices/pt/form-reuse.texy index 90da87b3c5..1f15cd5dd6 100644 --- a/best-practices/pt/form-reuse.texy +++ b/best-practices/pt/form-reuse.texy @@ -152,7 +152,7 @@ class EditFormFactory } ``` -É muito importante que a ligação entre as classes `FormFactory` e `EditFormFactory` seja implementada por composição e não por herança de objetos: +É muito importante que a vinculação entre as classes `FormFactory` e `EditFormFactory` seja implementada [por composição |nette:introduction-to-object-oriented-programming#composition], e não por [herança de objetos |https://doc.nette.org/en/introduction-to-object-oriented-programming#inheritance]: ```php // ⛔ NÃO! A HERANÇA NÃO PERTENCE AQUI @@ -172,7 +172,7 @@ class EditFormFactory extends FormFactory Usar a herança neste caso seria completamente contraproducente. Você se depararia com problemas muito rapidamente. Por exemplo, se você quisesse adicionar parâmetros ao método `create()`; o PHP relataria um erro de que sua assinatura era diferente da dos pais. Ou ao passar uma dependência para a classe `EditFormFactory` através do construtor. Isto causaria o que chamamos de [inferno do construtor |dependency-injection:passing-dependencies#Constructor hell]. -Em geral, é melhor preferir a composição do que a herança. +Em geral, é melhor preferir a [composição à herança |dependency-injection:faq#Why composition is preferred over inheritance]. Manuseio de formulários .[#toc-form-handling] diff --git a/best-practices/pt/presenter-traits.texy b/best-practices/pt/presenter-traits.texy index 65834541f8..d65e2304a4 100644 --- a/best-practices/pt/presenter-traits.texy +++ b/best-practices/pt/presenter-traits.texy @@ -2,7 +2,7 @@ Composição dos apresentadores a partir de traços ************************************************ .[perex] -Se precisarmos implementar o mesmo código em vários apresentadores (por exemplo, verificação de que o usuário está logado), é tentador colocar o código em um ancestral comum. A segunda opção é criar características de uso único. +Se precisarmos implementar o mesmo código em vários apresentadores (por exemplo, verificação de que o usuário está conectado), é tentador colocar o código em um ancestral comum. A segunda opção é criar [características |nette:introduction-to-object-oriented-programming#traits] de finalidade única. A vantagem desta solução é que cada apresentador pode usar apenas os traços de que realmente precisa, enquanto a herança múltipla não é possível em PHP. diff --git a/best-practices/ro/@home.texy b/best-practices/ro/@home.texy index 5a2a254154..c4f7e32395 100644 --- a/best-practices/ro/@home.texy +++ b/best-practices/ro/@home.texy @@ -41,6 +41,7 @@ Comună - [De ce Nette nu folosește sufixul Interface? |https://blog.nette.org/ro/prefixele-si-sufixele-nu-se-regasesc-in-numele-interfetelor] - [Sfaturi pentru utilizarea Composer |composer] - [Sfaturi privind editorii și instrumentele |editors-and-tools] +- [Introducere în programarea orientată pe obiecte |nette:introduction-to-object-oriented-programming]
    diff --git a/best-practices/ro/form-reuse.texy b/best-practices/ro/form-reuse.texy index 0f1e60600b..e9ec5c7abc 100644 --- a/best-practices/ro/form-reuse.texy +++ b/best-practices/ro/form-reuse.texy @@ -152,7 +152,7 @@ class EditFormFactory } ``` -Este foarte important ca legătura dintre clasele `FormFactory` și `EditFormFactory` să fie implementată prin compoziție, nu prin moștenirea obiectelor: +Este foarte important ca legătura dintre clasele `FormFactory` și `EditFormFactory` să fie implementată [prin compoziție |nette:introduction-to-object-oriented-programming#composition], nu prin [moștenirea obiectelor |https://doc.nette.org/en/introduction-to-object-oriented-programming#inheritance]: ```php // ⛔ NU! MOȘTENIREA NU ARE CE CĂUTA AICI @@ -172,7 +172,7 @@ class EditFormFactory extends FormFactory Utilizarea moștenirii în acest caz ar fi complet contraproductivă. Ați întâmpina foarte repede probleme. De exemplu, dacă ați dori să adăugați parametri la metoda `create()`, PHP ar raporta o eroare deoarece semnătura acesteia este diferită de cea a metodei părinte. Sau atunci când treceți o dependență clasei `EditFormFactory` prin intermediul constructorului. Acest lucru ar cauza ceea ce numim " [iadul constructorilor |dependency-injection:passing-dependencies#Constructor hell]". -În general, este mai bine să preferați compoziția decât moștenirea. +În general, este mai bine să se prefere [compoziția decât moștenirea |dependency-injection:faq#Why composition is preferred over inheritance]. Gestionarea formularelor .[#toc-form-handling] diff --git a/best-practices/ro/presenter-traits.texy b/best-practices/ro/presenter-traits.texy index 496296a400..a3c77846b7 100644 --- a/best-practices/ro/presenter-traits.texy +++ b/best-practices/ro/presenter-traits.texy @@ -2,7 +2,7 @@ Compunerea prezentatorilor din trăsături **************************************** .[perex] -Dacă trebuie să implementăm același cod în mai multe prezentări (de exemplu, verificarea faptului că utilizatorul este conectat), este tentant să plasăm codul într-un strămoș comun. A doua opțiune este crearea unor trăsături cu scop unic. +Dacă trebuie să implementăm același cod în mai multe prezentări (de exemplu, verificarea faptului că utilizatorul este conectat), este tentant să plasăm codul într-un strămoș comun. A doua opțiune este de a crea [trăsături |nette:introduction-to-object-oriented-programming#traits] cu scop unic. Avantajul acestei soluții este că fiecare prezentator poate utiliza doar trăsăturile de care are nevoie efectiv, în timp ce moștenirea multiplă nu este posibilă în PHP. diff --git a/best-practices/ru/@home.texy b/best-practices/ru/@home.texy index 69eed2aa87..3a0eeb1ece 100644 --- a/best-practices/ru/@home.texy +++ b/best-practices/ru/@home.texy @@ -41,6 +41,7 @@ - [Почему Nette не использует суффикс Interface? |https://blog.nette.org/ru/prefiksy-i-suffiksy-ne-dolzny-prisutstvovat-v-imenah-interfejsov] - [Советы по использованию Composer |composer] - [Советы по редакторам и инструментам |editors-and-tools] +- [Введение в объектно-ориентированное программирование |nette:introduction-to-object-oriented-programming]
    diff --git a/best-practices/ru/form-reuse.texy b/best-practices/ru/form-reuse.texy index 534ce944d8..06214c2241 100644 --- a/best-practices/ru/form-reuse.texy +++ b/best-practices/ru/form-reuse.texy @@ -152,7 +152,7 @@ class EditFormFactory } ``` -Очень важно, чтобы связь между классами `FormFactory` и `EditFormFactory` была реализована композицией, а не наследованием объектов: +Очень важно, что привязка между классами `FormFactory` и `EditFormFactory` осуществляется [путем композиции |nette:introduction-to-object-oriented-programming#composition], а не [наследования объектов |https://doc.nette.org/en/introduction-to-object-oriented-programming#inheritance]: ```php // ⛔ НЕТ! НАСЛЕДСТВУ ЗДЕСЬ НЕ МЕСТО @@ -172,7 +172,7 @@ class EditFormFactory extends FormFactory Использование наследования в этом случае было бы совершенно непродуктивным. Вы бы очень быстро столкнулись с проблемами. Например, если бы вы захотели добавить параметры в метод `create()`, PHP выдал бы ошибку, что его сигнатура отличается от родительской. Или при передаче зависимости классу `EditFormFactory` через конструктор. Это привело бы к тому, что мы называем " [ад конструктора |dependency-injection:passing-dependencies#Constructor hell]". -В целом, лучше предпочесть композицию наследованию. +В целом лучше отдать предпочтение [композиции, а не наследованию |dependency-injection:faq#Why composition is preferred over inheritance]. Работа с формами .[#toc-form-handling] diff --git a/best-practices/ru/presenter-traits.texy b/best-practices/ru/presenter-traits.texy index 91ec5df365..9c95a17890 100644 --- a/best-practices/ru/presenter-traits.texy +++ b/best-practices/ru/presenter-traits.texy @@ -2,7 +2,7 @@ ************************************ .[perex] -Если нам нужно реализовать один и тот же код в нескольких презентерах (например, проверка того, что пользователь вошел в систему), заманчиво поместить этот код в общего предка. Второй вариант - создать одноцелевые трейты. +Если нам необходимо реализовать один и тот же код в нескольких презентаторах (например, проверку того, что пользователь вошел в систему), то заманчиво поместить этот код в общего предка. Второй вариант - создание одноцелевых [трейтов |nette:introduction-to-object-oriented-programming#traits]. Преимущество этого решения заключается в том, что каждый ведущий может использовать только те признаки, которые ему действительно нужны, в то время как множественное наследование в PHP невозможно. diff --git a/best-practices/sl/@home.texy b/best-practices/sl/@home.texy index f89b8a74a1..5bd44d01af 100644 --- a/best-practices/sl/@home.texy +++ b/best-practices/sl/@home.texy @@ -41,6 +41,7 @@ Skupna spletna stran - [Zakaj Nette ne uporablja končnice Interface |https://blog.nette.org/sl/predpone-in-pripone-ne-sodijo-v-imena-vmesnikov]? - [Nasveti za uporabo programa Composer |composer] - [Nasveti o urejevalnikih in orodjih |editors-and-tools] +- [Uvod v objektno usmerjeno programiranje |nette:introduction-to-object-oriented-programming]
    diff --git a/best-practices/sl/form-reuse.texy b/best-practices/sl/form-reuse.texy index 398e4490b0..8c185009bc 100644 --- a/best-practices/sl/form-reuse.texy +++ b/best-practices/sl/form-reuse.texy @@ -152,7 +152,7 @@ class EditFormFactory } ``` -Zelo pomembno je, da se vezava med razredoma `FormFactory` in `EditFormFactory` izvaja s kompozicijo in ne z dedovanjem objektov: +Zelo pomembno je, da se povezava med razredoma `FormFactory` in `EditFormFactory` izvaja [s kompozicijo |nette:introduction-to-object-oriented-programming#composition] in ne z [dedovanjem objektov |https://doc.nette.org/en/introduction-to-object-oriented-programming#inheritance]: ```php // ⛔ NE! DEDIŠČINA NE SPADA SEM @@ -172,7 +172,7 @@ class EditFormFactory extends FormFactory Uporaba dedovanja bi bila v tem primeru popolnoma neproduktivna. Zelo hitro bi naleteli na težave. Na primer, če bi želeli metodi `create()` dodati parametre; PHP bi sporočil napako, ker se njen podpis razlikuje od podpisa nadrejene metode. Ali pa pri posredovanju odvisnosti razredu `EditFormFactory` prek konstruktorja. To bi povzročilo tako imenovani [konstruktorski pekel |dependency-injection:passing-dependencies#Constructor hell]. -Na splošno je bolje dati prednost kompoziciji pred dedovanjem. +Na splošno je bolje dati prednost [sestavi pred dedovanjem |dependency-injection:faq#Why composition is preferred over inheritance]. Ravnanje z obrazci .[#toc-form-handling] diff --git a/best-practices/sl/presenter-traits.texy b/best-practices/sl/presenter-traits.texy index e20064a8e4..61924099ae 100644 --- a/best-practices/sl/presenter-traits.texy +++ b/best-practices/sl/presenter-traits.texy @@ -2,7 +2,7 @@ Sestavljanje predavateljev iz lastnosti *************************************** .[perex] -Če moramo isto kodo implementirati v več predstavitvah (npr. preverjanje, ali je uporabnik prijavljen), je skušnjava, da kodo postavimo v skupnega prednika. Druga možnost je, da ustvarimo enonamenske lastnosti. +Če moramo isto kodo implementirati v več prikazovalnikih (npr. preverjanje, ali je uporabnik prijavljen), je skušnjava, da bi kodo prenesli v skupnega prednika. Druga možnost je, da ustvarimo enonamenske [lastnosti |nette:introduction-to-object-oriented-programming#traits]. Prednost te rešitve je, da lahko vsak predstavnik uporablja samo lastnosti, ki jih dejansko potrebuje, medtem ko večkratno dedovanje v PHP ni mogoče. diff --git a/best-practices/tr/@home.texy b/best-practices/tr/@home.texy index f773189fcb..9e191ff6ff 100644 --- a/best-practices/tr/@home.texy +++ b/best-practices/tr/@home.texy @@ -41,6 +41,7 @@ Ortak - [Nette neden Interface son ekini kullanmıyor? |https://blog.nette.org/tr/oenek-ve-sonekler-arayuez-adlarina-ait-degildir] - [Composer kullanım ipuçları |composer] - [Editörler ve araçlar hakkında ipuçları |editors-and-tools] +- [Nesne yönelimli programlamaya giriş |nette:introduction-to-object-oriented-programming]
    diff --git a/best-practices/tr/form-reuse.texy b/best-practices/tr/form-reuse.texy index 338dee09ef..fd80cf39ef 100644 --- a/best-practices/tr/form-reuse.texy +++ b/best-practices/tr/form-reuse.texy @@ -152,7 +152,7 @@ class EditFormFactory } ``` - `FormFactory` ve `EditFormFactory` sınıfları arasındaki bağın nesne kalıtımı ile değil, bileşim ile uygulanması çok önemlidir: +`FormFactory` ve `EditFormFactory` sınıfları arasındaki bağın [nesne kalıtımı |https://doc.nette.org/en/introduction-to-object-oriented-programming#inheritance] ile değil, [bileşim |nette:introduction-to-object-oriented-programming#composition] ile uygulanması çok önemlidir: ```php // ⛔ HAYIR! MİRAS BURAYA AİT DEĞİL @@ -172,7 +172,7 @@ class EditFormFactory extends FormFactory Bu durumda kalıtım kullanmak tamamen ters etki yaratacaktır. Çok hızlı bir şekilde sorunlarla karşılaşırsınız. Örneğin, `create()` yöntemine parametre eklemek isterseniz; PHP, imzasının ebeveynden farklı olduğuna dair bir hata bildirecektir. Ya da `EditFormFactory` sınıfına yapıcı aracılığıyla bir bağımlılık aktarırken. Bu, yapıcı [cehennemi |dependency-injection:passing-dependencies#Constructor hell] dediğimiz şeye neden olur. -Genel olarak, kalıtım yerine bileşimi tercih etmek daha iyidir. +Genellikle [kalıtım yerine bileşimi |dependency-injection:faq#Why composition is preferred over inheritance] tercih etmek daha iyidir. Form İşleme .[#toc-form-handling] diff --git a/best-practices/tr/presenter-traits.texy b/best-practices/tr/presenter-traits.texy index 1ef3223f6e..c568a8bb9d 100644 --- a/best-practices/tr/presenter-traits.texy +++ b/best-practices/tr/presenter-traits.texy @@ -2,7 +2,7 @@ ****************************** .[perex] -Aynı kodu birden fazla sunucuda uygulamamız gerekiyorsa (örneğin, kullanıcının oturum açtığının doğrulanması), kodu ortak bir ataya yerleştirmek caziptir. İkinci seçenek ise tek amaçlı özellikler oluşturmaktır. +Aynı kodu birden fazla sunucuda uygulamamız gerekiyorsa (örneğin, kullanıcının oturum açtığının doğrulanması), kodu ortak bir ataya yerleştirmek caziptir. İkinci seçenek ise tek amaçlı [özellikler |nette:introduction-to-object-oriented-programming#traits] oluşturmaktır. Bu çözümün avantajı, PHP'de çoklu kalıtım mümkün değilken, her sunucunun yalnızca gerçekten ihtiyaç duyduğu özellikleri kullanabilmesidir. diff --git a/best-practices/uk/@home.texy b/best-practices/uk/@home.texy index cfbe213cbd..67d239888e 100644 --- a/best-practices/uk/@home.texy +++ b/best-practices/uk/@home.texy @@ -41,6 +41,7 @@ - [Чому Nette не використовує суфікс Interface? |https://blog.nette.org/uk/prefiksi-ta-sufiksi-ne-potribni-v-nazvah-interfejsiv] - [Поради щодо використання Composer |composer] - [Поради щодо редакторів та інструментів |editors-and-tools] +- [Вступ до об'єктно-орієнтованого програмування |nette:introduction-to-object-oriented-programming]
    diff --git a/best-practices/uk/form-reuse.texy b/best-practices/uk/form-reuse.texy index 7993290a51..b1e0418b47 100644 --- a/best-practices/uk/form-reuse.texy +++ b/best-practices/uk/form-reuse.texy @@ -152,7 +152,7 @@ class EditFormFactory } ``` -Дуже важливо, щоб зв'язок між класами `FormFactory` і `EditFormFactory` був реалізований за допомогою композиції, а не успадкування об'єктів: +Дуже важливо, що зв'язування між класами `FormFactory` та `EditFormFactory` реалізовано [за допомогою композиції |nette:introduction-to-object-oriented-programming#composition], а не [успадкування об'єктів |https://doc.nette.org/en/introduction-to-object-oriented-programming#inheritance]: ```php // НІ! СПАДЩИНА ТУТ НЕ МАЄ ЗНАЧЕННЯ @@ -172,7 +172,7 @@ class EditFormFactory extends FormFactory Використання успадкування в цьому випадку було б абсолютно контрпродуктивним. Ви б дуже швидко зіткнулися з проблемами. Наприклад, якщо ви захочете додати параметри до методу `create()`; PHP повідомить про помилку, що його сигнатура відрізняється від батьківської. Або при передачі залежності класу `EditFormFactory` через конструктор. Це призведе до того, що ми називаємо пеклом [конструктора |dependency-injection:passing-dependencies#Constructor hell]. -Загалом, краще надавати перевагу композиції, а не успадкуванню. +Як правило, краще віддавати перевагу [композиції, а не успадкуванню |dependency-injection:faq#Why composition is preferred over inheritance]. Обробка форм .[#toc-form-handling] diff --git a/best-practices/uk/presenter-traits.texy b/best-practices/uk/presenter-traits.texy index 9530556a56..edc2530464 100644 --- a/best-practices/uk/presenter-traits.texy +++ b/best-practices/uk/presenter-traits.texy @@ -2,7 +2,7 @@ ***************************** .[perex] -Якщо нам потрібно реалізувати один і той самий код у кількох презентерах (наприклад, перевірка того, що користувач увійшов у систему), заманливо помістити цей код у спільного предка. Другий варіант - створити одноцільові трейти. +Якщо нам потрібно реалізувати один і той самий код у декількох презентерах (наприклад, перевірка того, що користувач увійшов до системи), виникає спокуса помістити код у спільного предка. Другий варіант - створення одноцільових [ознак |nette:introduction-to-object-oriented-programming#traits]. Перевага цього рішення полягає в тому, що кожен ведучий може використовувати тільки ті ознаки, які йому справді потрібні, тоді як множинне успадкування в PHP неможливе. diff --git a/database/bg/explorer.texy b/database/bg/explorer.texy index 28fc39699a..e358a1ab6a 100644 --- a/database/bg/explorer.texy +++ b/database/bg/explorer.texy @@ -92,7 +92,7 @@ SELECT `id`, `name` FROM `tag` WHERE (`tag`.`id` IN (21, 22, 23)) | `$table->group($columns)` | set GROUP BY | `$table->having($having)` | set HAVING -Можете да използвате Fluent, например `$table->where(...)->order(...)->limit(...)`. Няколко условия `where` или `whereOr` се свързват с помощта на оператора `AND`. +Можем да използваме т.нар. [флуентен интерфейс |nette:introduction-to-object-oriented-programming#fluent-interfaces], например `$table->where(...)->order(...)->limit(...)`. Няколко условия `where` или `whereOr` се свързват чрез оператора `AND`. където() .[#toc-where] diff --git a/database/cs/explorer.texy b/database/cs/explorer.texy index 1ed2cf95a5..591a489c6c 100644 --- a/database/cs/explorer.texy +++ b/database/cs/explorer.texy @@ -92,7 +92,7 @@ Podívejme se na možnosti filtrování a omezování výběru pomocí třídy [ | `$table->group($columns)` | Nastaví GROUP BY | `$table->having($having)` | Nastaví HAVING -Můžeme použít tzv. fluent interface, například `$table->where(...)->order(...)->limit(...)`. Vícenásobné `where` nebo `whereOr` podmínky je spojeny operátorem `AND`. +Můžeme použít tzv. [fluent interface|nette:introduction-to-object-oriented-programming#fluent-interfaces], například `$table->where(...)->order(...)->limit(...)`. Vícenásobné `where` nebo `whereOr` podmínky je spojeny operátorem `AND`. where() diff --git a/database/de/explorer.texy b/database/de/explorer.texy index f1adf4fb40..4afda54696 100644 --- a/database/de/explorer.texy +++ b/database/de/explorer.texy @@ -92,7 +92,7 @@ Siehe Möglichkeiten zum Filtern und Einschränken von Zeilen [api:Nette\Databas | `$table->group($columns)` | GROUP BY einstellen | `$table->having($having)` | HAVING einstellen -Es kann eine fließende Schnittstelle verwendet werden, z. B. `$table->where(...)->order(...)->limit(...)`. Mehrere `where` oder `whereOr` Bedingungen werden mit dem Operator `AND` verbunden. +Wir können eine sogenannte [fließende Schnittstelle |nette:introduction-to-object-oriented-programming#fluent-interfaces] verwenden, zum Beispiel `$table->where(...)->order(...)->limit(...)`. Mehrere `where` oder `whereOr` Bedingungen werden mit dem Operator `AND` verknüpft. wo() .[#toc-where] diff --git a/database/el/explorer.texy b/database/el/explorer.texy index 8b1cace70a..02dce7f83b 100644 --- a/database/el/explorer.texy +++ b/database/el/explorer.texy @@ -92,7 +92,7 @@ SELECT `id`, `name` FROM `tag` WHERE (`tag`.`id` IN (21, 22, 23)) | `$table->group($columns)` | Ορισμός GROUP BY | `$table->having($having)` | Ορισμός HAVING -Μπορεί να χρησιμοποιηθεί διεπαφή Fluent, για παράδειγμα `$table->where(...)->order(...)->limit(...)`. Πολλαπλές συνθήκες `where` ή `whereOr` συνδέονται με τον τελεστή `AND`. +Μπορούμε να χρησιμοποιήσουμε μια λεγόμενη [ρευστή διεπαφή |nette:introduction-to-object-oriented-programming#fluent-interfaces], για παράδειγμα `$table->where(...)->order(...)->limit(...)`. Πολλαπλές συνθήκες `where` ή `whereOr` συνδέονται με τον τελεστή `AND`. where() .[#toc-where] diff --git a/database/en/explorer.texy b/database/en/explorer.texy index 77e8f5a91c..09ae998fbf 100644 --- a/database/en/explorer.texy +++ b/database/en/explorer.texy @@ -92,7 +92,7 @@ See possibilities how to filter and restrict rows [api:Nette\Database\Table\Sele | `$table->group($columns)` | Set GROUP BY | `$table->having($having)` | Set HAVING -Fluent interface can be used, for example `$table->where(...)->order(...)->limit(...)`. Multiple `where` or `whereOr` conditions are connected with the `AND` operator. +We can use a so-called [fluent interface |nette:introduction-to-object-oriented-programming#fluent-interfaces], for example `$table->where(...)->order(...)->limit(...)`. Multiple `where` or `whereOr` conditions are linked by the `AND` operator. where() diff --git a/database/es/explorer.texy b/database/es/explorer.texy index 444c32521d..5ce5aca8c7 100644 --- a/database/es/explorer.texy +++ b/database/es/explorer.texy @@ -92,7 +92,7 @@ Ver posibilidades cómo filtrar y restringir filas [api:Nette\Database\Table\Sel | `$table->group($columns)` Establecer GROUP BY | `$table->having($having)` Establecer HAVING -Se puede utilizar una interfaz fluida, por ejemplo `$table->where(...)->order(...)->limit(...)`. Las condiciones múltiples `where` o `whereOr` se conectan con el operador `AND`. +Podemos utilizar una [interfaz fluida |nette:introduction-to-object-oriented-programming#fluent-interfaces], por ejemplo `$table->where(...)->order(...)->limit(...)`. Varias condiciones `where` o `whereOr` se enlazan mediante el operador `AND`. donde() .[#toc-where] diff --git a/database/fr/explorer.texy b/database/fr/explorer.texy index 7d4796d7f8..d8a7eca2ed 100644 --- a/database/fr/explorer.texy +++ b/database/fr/explorer.texy @@ -92,7 +92,7 @@ Voir les possibilités de filtrer et de restreindre les lignes [api:Nette\Databa | `$table->group($columns)` | Définir GROUP BY | `$table->having($having)` | Définir HAVING -Une interface fluide peut être utilisée, par exemple `$table->where(...)->order(...)->limit(...)`. Les conditions multiples de `where` ou `whereOr` sont connectées avec l'opérateur `AND`. +Nous pouvons utiliser ce que l'on appelle une [interface fluide |nette:introduction-to-object-oriented-programming#fluent-interfaces], par exemple `$table->where(...)->order(...)->limit(...)`. Plusieurs conditions `where` ou `whereOr` sont liées par l'opérateur `AND`. où() .[#toc-where] diff --git a/database/hu/explorer.texy b/database/hu/explorer.texy index 55b2296755..7cb0e16c06 100644 --- a/database/hu/explorer.texy +++ b/database/hu/explorer.texy @@ -92,7 +92,7 @@ Lásd a sorok szűrésének és korlátozásának lehetőségeit [api:Nette\Data | `$table->group($columns)` | GROUP BY beállítása | `$table->having($having)` | HAVING beállítása -Fluent interfész használható, például `$table->where(...)->order(...)->limit(...)`. Több `where` vagy `whereOr` feltétel a `AND` operátorral kapcsolódik. +Használhatunk egy úgynevezett [folyékony felületet |nette:introduction-to-object-oriented-programming#fluent-interfaces], például a `$table->where(...)->order(...)->limit(...)`. Több `where` vagy `whereOr` feltételt a `AND` operátorral kapcsolunk össze. where() .[#toc-where] diff --git a/database/it/explorer.texy b/database/it/explorer.texy index c462381ac0..6828388d35 100644 --- a/database/it/explorer.texy +++ b/database/it/explorer.texy @@ -92,7 +92,7 @@ Vedere le possibilità di filtrare e limitare le righe [api:Nette\Database\Table | `$table->group($columns)` | Impostare GROUP BY | `$table->having($having)` | Imposta HAVING -È possibile utilizzare l'interfaccia Fluent, ad esempio `$table->where(...)->order(...)->limit(...)`. Le condizioni multiple `where` o `whereOr` sono collegate con l'operatore `AND`. +Possiamo utilizzare una cosiddetta [interfaccia fluente |nette:introduction-to-object-oriented-programming#fluent-interfaces], ad esempio `$table->where(...)->order(...)->limit(...)`. Più condizioni `where` o `whereOr` sono collegate dall'operatore `AND`. dove() .[#toc-where] diff --git a/database/pl/explorer.texy b/database/pl/explorer.texy index e479bb49aa..2739bc413b 100644 --- a/database/pl/explorer.texy +++ b/database/pl/explorer.texy @@ -92,7 +92,7 @@ Przyjrzyjmy się opcjom filtrowania i ograniczania selekcji przy użyciu klasy [ | `$table->group($columns)` | Set GROUP BY | `$table->having($having)` | Set HAVING -Możemy użyć tzw. interfejsu fluent, na przykład `$table->where(...)->order(...)->limit(...)`. Wiele warunków `where` lub `whereOr` łączy się za pomocą operatora `AND`. +Możemy użyć tak zwanego [płynnego interfejsu |nette:introduction-to-object-oriented-programming#fluent-interfaces], na przykład `$table->where(...)->order(...)->limit(...)`. Wiele warunków `where` lub `whereOr` jest połączonych operatorem `AND`. gdzie() .[#toc-where] diff --git a/database/pt/explorer.texy b/database/pt/explorer.texy index 7e6205c677..b5e4badd65 100644 --- a/database/pt/explorer.texy +++ b/database/pt/explorer.texy @@ -92,7 +92,7 @@ Veja as possibilidades de filtragem e restrição de linhas [api:Nette\Database\ | `$table->group($columns)` | Set GROUP BY | `$table->having($having)` | Set HAVING -A interface fluente pode ser utilizada, por exemplo `$table->where(...)->order(...)->limit(...)`. Múltiplas condições `where` ou `whereOr` são conectadas com o operador `AND`. +Podemos usar a chamada [interface fluente |nette:introduction-to-object-oriented-programming#fluent-interfaces], por exemplo, `$table->where(...)->order(...)->limit(...)`. Várias condições `where` ou `whereOr` são vinculadas pelo operador `AND`. onde() .[#toc-where] diff --git a/database/ro/explorer.texy b/database/ro/explorer.texy index ab5ffa2031..f85f91d7de 100644 --- a/database/ro/explorer.texy +++ b/database/ro/explorer.texy @@ -92,7 +92,7 @@ Vedeți posibilitățile de filtrare și restricționare a rândurilor [api:Nett | `$table->group($columns)` | Setează GROUP BY | `$table->having($having)` | Setează HAVING -Se poate utiliza o interfață fluidă, de exemplu `$table->where(...)->order(...)->limit(...)`. Mai multe condiții `where` sau `whereOr` sunt conectate cu ajutorul operatorului `AND`. +Putem folosi o așa-numită [interfață fluentă |nette:introduction-to-object-oriented-programming#fluent-interfaces], de exemplu `$table->where(...)->order(...)->limit(...)`. Mai multe condiții `where` sau `whereOr` sunt legate între ele prin intermediul operatorului `AND`. unde() .[#toc-where] diff --git a/database/ru/explorer.texy b/database/ru/explorer.texy index a3f91ad8f7..71bc36135c 100644 --- a/database/ru/explorer.texy +++ b/database/ru/explorer.texy @@ -92,7 +92,7 @@ SELECT `id`, `name` FROM `tag` WHERE (`tag`.`id` IN (21, 22, 23)) | `$table->group($columns)` | Устанавливаем GROUP BY | `$table->having($having)` | Устанавливаем HAVING -Можно использовать текучий интерфейс (Fluent), например `$table->where(...)->order(...)->limit(...)`. Несколько условий `where` или `whereOr` соединяются с помощью оператора `AND`. +Мы можем использовать так называемый [флюентный интерфейс |nette:introduction-to-object-oriented-programming#fluent-interfaces], например `$table->where(...)->order(...)->limit(...)`. Несколько условий `where` или `whereOr` связываются оператором `AND`. where() diff --git a/database/sl/explorer.texy b/database/sl/explorer.texy index 0763f4711c..f2e5381533 100644 --- a/database/sl/explorer.texy +++ b/database/sl/explorer.texy @@ -92,7 +92,7 @@ Oglejte si možnosti za filtriranje in omejevanje vrstic [api:Nette\Database\Tab | `$table->group($columns)` | Nastavitev GROUP BY | `$table->having($having)` | Nastavitev HAVING -Uporabi se lahko vmesnik Fluent, na primer `$table->where(...)->order(...)->limit(...)`. Več pogojev `where` ali `whereOr` je povezanih z operatorjem `AND`. +Uporabimo lahko tako imenovani [tekoči vmesnik |nette:introduction-to-object-oriented-programming#fluent-interfaces], na primer `$table->where(...)->order(...)->limit(...)`. Več pogojev `where` ali `whereOr` povežemo z operatorjem `AND`. kjer() .[#toc-where] diff --git a/database/tr/explorer.texy b/database/tr/explorer.texy index cda960249c..2728dda94b 100644 --- a/database/tr/explorer.texy +++ b/database/tr/explorer.texy @@ -92,7 +92,7 @@ Satırların nasıl filtreleneceği ve kısıtlanacağı ile ilgili olasılıkla | `$table->group($columns)` | GROUP BY ayarla | `$table->having($having)` | Set HAVING -Fluent arayüzü kullanılabilir, örneğin `$table->where(...)->order(...)->limit(...)`. Birden fazla `where` veya `whereOr` koşulu `AND` operatörü ile bağlanır. +[Akıcı arayüz |nette:introduction-to-object-oriented-programming#fluent-interfaces] olarak adlandırılan bir [arayüz |nette:introduction-to-object-oriented-programming#fluent-interfaces] kullanabiliriz, örneğin `$table->where(...)->order(...)->limit(...)`. Birden fazla `where` veya `whereOr` koşulu `AND` operatörü ile birbirine bağlanır. nerede() .[#toc-where] diff --git a/database/uk/explorer.texy b/database/uk/explorer.texy index 8c04ec8f5d..2604e6e6ee 100644 --- a/database/uk/explorer.texy +++ b/database/uk/explorer.texy @@ -92,7 +92,7 @@ SELECT `id`, `name` FROM `tag` WHERE (`tag`.`id` IN (21, 22, 23)) | `$table->group($columns)` | Встановлюємо GROUP BY | `$table->having($having)` | Встановлюємо HAVING -Можна використовувати поточний інтерфейс (Fluent), наприклад `$table->where(...)->order(...)->limit(...)`. Кілька умов `where` або `whereOr` з'єднуються за допомогою оператора `AND`. +Ми можемо використовувати так званий вільний [інтерфейс |nette:introduction-to-object-oriented-programming#fluent-interfaces], наприклад `$table->where(...)->order(...)->limit(...)`. Кілька умов `where` або `whereOr` зв'язуються оператором `AND`. where() .[#toc-where] diff --git a/dependency-injection/bg/faq.texy b/dependency-injection/bg/faq.texy index 392c71c995..e09adb33a2 100644 --- a/dependency-injection/bg/faq.texy +++ b/dependency-injection/bg/faq.texy @@ -61,7 +61,7 @@ DI не оказва влияние върху производителност Защо композицията е за предпочитане пред наследяването? .[#toc-why-composition-is-preferred-over-inheritance] ------------------------------------------------------------------------------------------------------------- -За предпочитане е да се използва композиция, а не наследяване, тъй като тя служи за целите на повторната употреба на кода, без да е необходимо да се притеснявате за ефекта от промяната. По този начин се осигурява по-свободно свързване, при което не е необходимо да се притесняваме, че промяната на някакъв код ще доведе до промяна на друг зависим код. Типичен пример за това е ситуацията, наречена [ад на конструкторите |passing-dependencies#Constructor hell]. +За предпочитане е да се използва [композиция |nette:introduction-to-object-oriented-programming#composition] вместо [наследяване |nette:introduction-to-object-oriented-programming#inheritance], тъй като тя служи за повторно използване на кода, без да се налага да се притеснявате за последствията от промените. По този начин се осигурява по-хлабава връзка, при която не е необходимо да се притесняваме, че промяната на някакъв код ще доведе до необходимостта от промяна на друг зависим код. Типичен пример за това е ситуацията, наречена " [ад на конструкторите" |passing-dependencies#Constructor hell]. Може ли Nette DI Container да се използва извън Nette? .[#toc-can-nette-di-container-be-used-outside-of-nette] diff --git a/dependency-injection/bg/passing-dependencies.texy b/dependency-injection/bg/passing-dependencies.texy index d4761752a3..8dbca62c01 100644 --- a/dependency-injection/bg/passing-dependencies.texy +++ b/dependency-injection/bg/passing-dependencies.texy @@ -96,9 +96,9 @@ final class MyClass extends BaseClass Проблемът възниква, когато искаме да променим конструктора на класа `BaseClass`, например когато се добави нова зависимост. Тогава трябва да променим и всички конструктори на децата. Което превръща подобна модификация в ад. -Как да предотвратим това? Решението е да се даде **приоритет на композицията пред наследяването**. +Как да предотвратим това? Решението е да се даде предимство на [композицията пред наследяването** |faq#Why composition is preferred over inheritance]. -Така че нека да проектираме кода по различен начин. Ще избягваме абстрактните класове `Base*`. Вместо `MyClass` да получава някаква функционалност, наследявайки я от `BaseClass`, тя ще има тази функционалност, предадена като зависимост: +Затова нека да проектираме кода по различен начин. Ще избягваме [абстрактните |nette:introduction-to-object-oriented-programming#abstract-classes] класове `Base*`. Вместо `MyClass` да получи някаква функционалност, наследявайки я от `BaseClass`, тя ще бъде предадена като зависимост: ```php final class SomeFunctionality diff --git a/dependency-injection/cs/faq.texy b/dependency-injection/cs/faq.texy index 31f26903b0..7d5e4b199b 100644 --- a/dependency-injection/cs/faq.texy +++ b/dependency-injection/cs/faq.texy @@ -61,7 +61,7 @@ Pamatujte, že přechod na Dependency Injection je investice do kvality kódu a Proč se upřednostňuje kompozice před dědičností? ------------------------------------------------ -Je vhodnější používat kompozici místo dědičnosti, protože slouží k opětovnému použití kódu, aniž bychom se museli starat o důsledky změn. Poskytuje tedy volnější vazbu, kdy nemusíme mít obavy, že změna nějakého kódu způsobí potřebu změny jiného závislého kódu. Typickým příkladem je situace označovaná jako [constructor hell |passing-dependencies#Constructor hell]. +Je vhodnější používat [kompozici|nette:introduction-to-object-oriented-programming#kompozice] místo [dědičnosti|nette:introduction-to-object-oriented-programming#dedicnost], protože slouží k opětovnému použití kódu, aniž bychom se museli starat o důsledky změn. Poskytuje tedy volnější vazbu, kdy nemusíme mít obavy, že změna nějakého kódu způsobí potřebu změny jiného závislého kódu. Typickým příkladem je situace označovaná jako [constructor hell |passing-dependencies#Constructor hell]. Lze použít Nette DI Container mimo Nette? diff --git a/dependency-injection/cs/passing-dependencies.texy b/dependency-injection/cs/passing-dependencies.texy index bb32928a73..88d0cd63f7 100644 --- a/dependency-injection/cs/passing-dependencies.texy +++ b/dependency-injection/cs/passing-dependencies.texy @@ -96,9 +96,9 @@ final class MyClass extends BaseClass Problém nastane v okamžiku, kdy budeme chtít změnit kontruktor třídy `BaseClass`, třeba když přibude nová závislost. Pak je totiž nutné upravit také všechny konstruktory potomků. Což z takové úpravy dělá peklo. -Jak tomu předcházet? Řešením je **dávat přednost kompozici před dědičností.** +Jak tomu předcházet? Řešením je **dávat přednost [kompozici před dědičností|faq#Proč se upřednostňuje kompozice před dědičností]**. -Tedy navrhneme kód jinak. Budeme se vyhýbat abstraktním `Base*` třídám. Místo toho, aby `MyClass` získávala určitou funkčnost tím, že dědí od `BaseClass`, si tuto funkčnost nechá předat jako závislost: +Tedy navrhneme kód jinak. Budeme se vyhýbat [abstraktním|nette:introduction-to-object-oriented-programming#abstraktni-tridy] `Base*` třídám. Místo toho, aby `MyClass` získávala určitou funkčnost tím, že dědí od `BaseClass`, si tuto funkčnost nechá předat jako závislost: ```php final class SomeFunctionality diff --git a/dependency-injection/de/faq.texy b/dependency-injection/de/faq.texy index 0a4279f61e..088c073489 100644 --- a/dependency-injection/de/faq.texy +++ b/dependency-injection/de/faq.texy @@ -61,7 +61,7 @@ Denken Sie daran, dass der Wechsel zu Dependency Injection eine Investition in d Warum ist Komposition der Vererbung vorzuziehen? .[#toc-why-composition-is-preferred-over-inheritance] ------------------------------------------------------------------------------------------------------ -Die Komposition ist der Vererbung vorzuziehen, da sie die Wiederverwendbarkeit des Codes ermöglicht, ohne dass man sich um die Auswirkungen von Änderungen sorgen muss. Dadurch wird eine lockerere Kopplung erreicht, bei der wir uns keine Sorgen machen müssen, dass die Änderung eines Codes dazu führt, dass ein anderer abhängiger Code geändert werden muss. Ein typisches Beispiel ist die Situation, die als [Konstruktorhölle |passing-dependencies#Constructor hell] bezeichnet wird. +Die [Komposition |nette:introduction-to-object-oriented-programming#composition] ist der [Vererbung |nette:introduction-to-object-oriented-programming#inheritance] vorzuziehen, da sie die Wiederverwendung von Code ermöglicht, ohne dass man sich über die Folgen von Änderungen Gedanken machen muss. Sie bietet also eine lockerere Kopplung, bei der wir uns keine Sorgen machen müssen, dass die Änderung eines Codes die Notwendigkeit mit sich bringt, anderen abhängigen Code zu ändern. Ein typisches Beispiel ist eine Situation, die als [Konstruktorhölle |passing-dependencies#Constructor hell] bezeichnet wird. Kann Nette DI Container auch außerhalb von Nette verwendet werden? .[#toc-can-nette-di-container-be-used-outside-of-nette] diff --git a/dependency-injection/de/passing-dependencies.texy b/dependency-injection/de/passing-dependencies.texy index 5ed4db6b6e..0a1208ca75 100644 --- a/dependency-injection/de/passing-dependencies.texy +++ b/dependency-injection/de/passing-dependencies.texy @@ -96,9 +96,9 @@ final class MyClass extends BaseClass Das Problem tritt auf, wenn wir den Konstruktor der Klasse `BaseClass` ändern wollen, zum Beispiel wenn eine neue Abhängigkeit hinzugefügt wird. Dann müssen wir auch alle Konstruktoren der Kinder ändern. Das macht eine solche Änderung zur Hölle. -Wie lässt sich das verhindern? Die Lösung besteht darin, **Komposition gegenüber Vererbung** zu bevorzugen. +Wie kann man dies verhindern? Die Lösung besteht darin, [**Zusammensetzung gegenüber Vererbung** |faq#Why composition is preferred over inheritance] zu bevorzugen. -Lassen Sie uns also den Code anders gestalten. Wir werden abstrakte `Base*` Klassen vermeiden. Anstatt dass `MyClass` eine bestimmte Funktionalität durch Vererbung von `BaseClass` erhält, wird diese Funktionalität als Abhängigkeit übergeben: +Lassen Sie uns also den Code anders gestalten. Wir werden [abstrakte |nette:introduction-to-object-oriented-programming#abstract-classes] `Base*` Klassen vermeiden. Anstatt dass `MyClass` einige Funktionen durch Vererbung von `BaseClass` erhält, wird diese Funktionalität als Abhängigkeit übergeben: ```php final class SomeFunctionality diff --git a/dependency-injection/el/faq.texy b/dependency-injection/el/faq.texy index 0ee71b6c73..43f2cd3e23 100644 --- a/dependency-injection/el/faq.texy +++ b/dependency-injection/el/faq.texy @@ -61,7 +61,7 @@ Γιατί η σύνθεση προτιμάται από την κληρονομικότητα; .[#toc-why-composition-is-preferred-over-inheritance] --------------------------------------------------------------------------------------------------------- -Είναι προτιμότερο να χρησιμοποιείται η σύνθεση παρά η κληρονομικότητα, καθώς εξυπηρετεί τον σκοπό της δυνατότητας επαναχρησιμοποίησης του κώδικα χωρίς να χρειάζεται να ανησυχείτε για την επίδραση της αλλαγής. Έτσι, παρέχει πιο χαλαρή σύζευξη όπου δεν χρειάζεται να ανησυχούμε για το αν η αλλαγή κάποιου κώδικα προκαλεί την αλλαγή κάποιου άλλου εξαρτημένου κώδικα που απαιτεί αλλαγή. Ένα τυπικό παράδειγμα είναι η κατάσταση που προσδιορίζεται ως [κόλαση των κατασκευαστών |passing-dependencies#Constructor hell]. +Είναι προτιμότερο να χρησιμοποιείται η [σύνθεση |nette:introduction-to-object-oriented-programming#composition] αντί για [την κληρονομικότητα |nette:introduction-to-object-oriented-programming#inheritance], επειδή χρησιμεύει στην επαναχρησιμοποίηση του κώδικα χωρίς να χρειάζεται να ανησυχείτε για τις συνέπειες των αλλαγών. Έτσι, παρέχει μια πιο χαλαρή σύζευξη, όπου δεν χρειάζεται να ανησυχούμε ότι η αλλαγή κάποιου κώδικα θα προκαλέσει την ανάγκη αλλαγής άλλου εξαρτημένου κώδικα. Ένα τυπικό παράδειγμα είναι μια κατάσταση που αναφέρεται ως [κόλαση των κατασκευαστών |passing-dependencies#Constructor hell]. Μπορεί το Nette DI Container να χρησιμοποιηθεί εκτός της Nette; .[#toc-can-nette-di-container-be-used-outside-of-nette] diff --git a/dependency-injection/el/passing-dependencies.texy b/dependency-injection/el/passing-dependencies.texy index 7d9171faaa..29863c21af 100644 --- a/dependency-injection/el/passing-dependencies.texy +++ b/dependency-injection/el/passing-dependencies.texy @@ -96,9 +96,9 @@ final class MyClass extends BaseClass Το πρόβλημα εμφανίζεται όταν θέλουμε να αλλάξουμε τον κατασκευαστή της κλάσης `BaseClass`, για παράδειγμα όταν προστίθεται μια νέα εξάρτηση. Τότε πρέπει να τροποποιήσουμε και όλους τους κατασκευαστές των παιδιών. Το οποίο κάνει μια τέτοια τροποποίηση κόλαση. -Πώς μπορεί να αποφευχθεί αυτό; Η λύση είναι η **προτεραιότητα της σύνθεσης έναντι της κληρονομικότητας**. +Πώς να το αποτρέψετε αυτό; Η λύση είναι η **προτεραιότητα της [σύνθεσης έναντι της κληρονομικότητας** |faq#Why composition is preferred over inheritance]. -Ας σχεδιάσουμε λοιπόν τον κώδικα με διαφορετικό τρόπο. Θα αποφύγουμε τις αφηρημένες κλάσεις `Base*`. Αντί το `MyClass` να παίρνει κάποια λειτουργικότητα κληρονομώντας από το `BaseClass`, θα έχει αυτή τη λειτουργικότητα περασμένη ως εξάρτηση: +Ας σχεδιάσουμε λοιπόν τον κώδικα με διαφορετικό τρόπο. Θα αποφύγουμε τις [αφηρημένες |nette:introduction-to-object-oriented-programming#abstract-classes] κλάσεις `Base*`. Αντί το `MyClass` να παίρνει κάποια λειτουργικότητα κληρονομώντας από το `BaseClass`, θα έχει αυτή τη λειτουργικότητα περασμένη ως εξάρτηση: ```php final class SomeFunctionality diff --git a/dependency-injection/en/faq.texy b/dependency-injection/en/faq.texy index ecf0ee0df0..0bfecefd8c 100644 --- a/dependency-injection/en/faq.texy +++ b/dependency-injection/en/faq.texy @@ -61,7 +61,7 @@ Remember that moving to Dependency Injection is an investment in code quality an Why composition is preferred over inheritance? ---------------------------------------------- -It is preferable to use composition rather then inheritance as it serves the purpose of code reuse-ability without having the need to worry about the trickle down effect of change. Thus it provides more loosely coupling where we do not have to worry about changing some code causing some other dependent code requiring change. A typical example is the situation identified as [constructor hell |passing-dependencies#Constructor hell]. +It is preferable to use [composition |nette:introduction-to-object-oriented-programming#composition] instead of [inheritance |nette:introduction-to-object-oriented-programming#inheritance] because it serves to reuse code without having to worry about the consequences of changes. Thus, it provides a looser coupling where we don't have to worry that changing some code will cause the need to change other dependent code. A typical example is a situation referred to as [constructor hell |passing-dependencies#Constructor hell]. Can Nette DI Container be used outside of Nette? diff --git a/dependency-injection/en/passing-dependencies.texy b/dependency-injection/en/passing-dependencies.texy index afb5dea3dc..bff2e4746f 100644 --- a/dependency-injection/en/passing-dependencies.texy +++ b/dependency-injection/en/passing-dependencies.texy @@ -96,9 +96,9 @@ final class MyClass extends BaseClass The problem occurs when we want to change the constructor of the `BaseClass` class, for example when a new dependency is added. Then we have to modify all the constructors of the children as well. Which makes such a modification hell. -How to prevent this? The solution is to **prioritize composition over inheritance**. +How to prevent this? The solution is to **prioritize [composition over inheritance |faq#Why composition is preferred over inheritance]**. -So let's design the code differently. We'll avoid abstract `Base*` classes. Instead of `MyClass` getting some functionality by inheriting from `BaseClass`, it will have that functionality passed as a dependency: +So let's design the code differently. We will avoid [abstract |nette:introduction-to-object-oriented-programming#abstract-classes] `Base*` classes. Instead of `MyClass` getting some functionality by inheriting from `BaseClass`, it will have that functionality passed as a dependency: ```php final class SomeFunctionality diff --git a/dependency-injection/es/faq.texy b/dependency-injection/es/faq.texy index ae21869cfa..40f35d038e 100644 --- a/dependency-injection/es/faq.texy +++ b/dependency-injection/es/faq.texy @@ -61,7 +61,7 @@ Recuerde que pasar a la inyección de dependencias es una inversión en la calid ¿Por qué se prefiere la composición a la herencia? .[#toc-why-composition-is-preferred-over-inheritance] -------------------------------------------------------------------------------------------------------- -Es preferible utilizar la composición en lugar de la herencia, ya que sirve al propósito de la reutilización del código sin tener que preocuparse por el efecto de goteo del cambio. Por lo tanto, proporciona un acoplamiento más laxo en el que no tenemos que preocuparnos de que el cambio de algún código provoque que otro código dependiente requiera un cambio. Un ejemplo típico es la situación identificada como [el infierno de los constructores |passing-dependencies#Constructor hell]. +Es preferible utilizar la [composición |nette:introduction-to-object-oriented-programming#composition] en lugar de [la herencia |nette:introduction-to-object-oriented-programming#inheritance] porque sirve para reutilizar código sin tener que preocuparse por las consecuencias de los cambios. Así, proporciona un acoplamiento más laxo en el que no tenemos que preocuparnos de que cambiar algún código provoque la necesidad de cambiar otro código dependiente. Un ejemplo típico es una situación conocida como [el infierno de los constructores |passing-dependencies#Constructor hell]. ¿Se puede utilizar Nette DI Container fuera de Nette? .[#toc-can-nette-di-container-be-used-outside-of-nette] diff --git a/dependency-injection/es/passing-dependencies.texy b/dependency-injection/es/passing-dependencies.texy index 8c80722dc9..cc895439a8 100644 --- a/dependency-injection/es/passing-dependencies.texy +++ b/dependency-injection/es/passing-dependencies.texy @@ -96,9 +96,9 @@ final class MyClass extends BaseClass El problema surge cuando queremos cambiar el constructor de la clase `BaseClass`, por ejemplo cuando se añade una nueva dependencia. Entonces tenemos que modificar también todos los constructores de los hijos. Lo que convierte tal modificación en un infierno. -¿Cómo evitarlo? La solución es **priorizar la composición sobre la herencia**. +¿Cómo evitarlo? La solución es **priorizar la [composición sobre la herencia** |faq#Why composition is preferred over inheritance]. -Así que diseñemos el código de otra manera. Evitaremos las clases abstractas `Base*`. En lugar de que `MyClass` obtenga alguna funcionalidad heredando de `BaseClass`, tendrá esa funcionalidad pasada como una dependencia: +Así que vamos a diseñar el código de forma diferente. Evitaremos las clases [abstractas |nette:introduction-to-object-oriented-programming#abstract-classes] `Base*`. En lugar de que `MyClass` obtenga alguna funcionalidad heredando de `BaseClass`, tendrá esa funcionalidad pasada como una dependencia: ```php final class SomeFunctionality diff --git a/dependency-injection/fr/faq.texy b/dependency-injection/fr/faq.texy index 6a16f99f8a..ed54ba9878 100644 --- a/dependency-injection/fr/faq.texy +++ b/dependency-injection/fr/faq.texy @@ -61,7 +61,7 @@ N'oubliez pas que le passage à l'injection de dépendances est un investissemen Pourquoi la composition est-elle préférable à l'héritage ? .[#toc-why-composition-is-preferred-over-inheritance] ---------------------------------------------------------------------------------------------------------------- -Il est préférable d'utiliser la composition plutôt que l'héritage car elle permet de réutiliser le code sans avoir à s'inquiéter de l'effet de ruissellement des changements. Elle permet donc un couplage plus lâche, sans avoir à se soucier du fait que la modification d'un code entraîne la modification d'un autre code dépendant. Un exemple typique est la situation identifiée comme l'[enfer des constructeurs |passing-dependencies#Constructor hell]. +Il est préférable d'utiliser la [composition |nette:introduction-to-object-oriented-programming#composition] plutôt que l'[héritage |nette:introduction-to-object-oriented-programming#inheritance] car elle permet de réutiliser le code sans avoir à se soucier des conséquences des changements. Ainsi, elle permet un couplage plus lâche où nous n'avons pas à nous soucier du fait que la modification d'un code entraînera la nécessité de modifier d'autres codes dépendants. Un exemple typique est une situation appelée " [enfer du constructeur" |passing-dependencies#Constructor hell]. Nette DI Container peut-il être utilisé en dehors de Nette ? .[#toc-can-nette-di-container-be-used-outside-of-nette] diff --git a/dependency-injection/fr/passing-dependencies.texy b/dependency-injection/fr/passing-dependencies.texy index 72726f495d..b40d5b3da1 100644 --- a/dependency-injection/fr/passing-dependencies.texy +++ b/dependency-injection/fr/passing-dependencies.texy @@ -96,9 +96,9 @@ final class MyClass extends BaseClass Le problème se pose lorsque nous voulons modifier le constructeur de la classe `BaseClass`, par exemple lorsqu'une nouvelle dépendance est ajoutée. Il faut alors modifier tous les constructeurs des enfants. Ce qui rend une telle modification infernale. -Comment éviter cela ? La solution est de **prioriser la composition sur l'héritage**. +Comment éviter cela ? La solution est de **prioriser la [composition sur l'héritage** |faq#Why composition is preferred over inheritance]. -Concevons donc le code différemment. Nous éviterons les classes abstraites `Base*`. Au lieu que `MyClass` obtienne une fonctionnalité en héritant de `BaseClass`, cette fonctionnalité lui sera transmise en tant que dépendance : +Concevons donc le code différemment. Nous éviterons les classes [abstraites |nette:introduction-to-object-oriented-programming#abstract-classes] `Base*`. Au lieu que `MyClass` obtienne une fonctionnalité en héritant de `BaseClass`, cette fonctionnalité lui sera transmise en tant que dépendance : ```php final class SomeFunctionality diff --git a/dependency-injection/hu/faq.texy b/dependency-injection/hu/faq.texy index 7bb9fe4437..65c5acc939 100644 --- a/dependency-injection/hu/faq.texy +++ b/dependency-injection/hu/faq.texy @@ -61,7 +61,7 @@ Ne feledje, hogy a függőségi injektálásra való áttérés a kód minőség Miért előnyösebb a kompozíció az örökléssel szemben? .[#toc-why-composition-is-preferred-over-inheritance] ---------------------------------------------------------------------------------------------------------- -Az öröklés helyett előnyösebb a kompozíciót használni, mivel ez a kód újrafelhasználhatóságát szolgálja anélkül, hogy aggódnunk kellene a változtatások átcsapó hatása miatt. Így lazább csatolást biztosít, ahol nem kell aggódnunk amiatt, hogy egy kód megváltoztatása más függő kódok megváltoztatását eredményezi. Tipikus példa erre a [konstruktorpokolként |passing-dependencies#Constructor hell] azonosított helyzet. +Az [öröklés |nette:introduction-to-object-oriented-programming#inheritance] helyett előnyösebb a [kompozíciót |nette:introduction-to-object-oriented-programming#composition] használni, mert ez a kód újrafelhasználását szolgálja anélkül, hogy aggódnunk kellene a változások következményei miatt. Így lazább csatolást biztosít, ahol nem kell aggódnunk amiatt, hogy bizonyos kódok megváltoztatása más függő kódok megváltoztatásának szükségességét eredményezi. Tipikus példa erre a [konstruktorpokolnak |passing-dependencies#Constructor hell] nevezett helyzet. Használható-e a Nette DI Container a Nette rendszeren kívül is? .[#toc-can-nette-di-container-be-used-outside-of-nette] diff --git a/dependency-injection/hu/passing-dependencies.texy b/dependency-injection/hu/passing-dependencies.texy index 924341e21f..0ec0b57a4c 100644 --- a/dependency-injection/hu/passing-dependencies.texy +++ b/dependency-injection/hu/passing-dependencies.texy @@ -96,9 +96,9 @@ final class MyClass extends BaseClass A probléma akkor jelentkezik, amikor a `BaseClass` osztály konstruktorát meg akarjuk változtatni, például egy új függőség hozzáadásakor. Ekkor a gyerekek összes konstruktorát is módosítani kell. Ami pokollá teszi az ilyen módosítást. -Hogyan lehet ezt megelőzni? A megoldás az, hogy **prioritást adunk a kompozíciónak az örökléssel szemben**. +Hogyan lehet ezt megelőzni? A megoldás az, hogy **elsőbbséget adunk a [kompozíciónak az örökléssel szemben** |faq#Why composition is preferred over inheritance]. -Tehát tervezzük meg a kódot másképp. Kerüljük az absztrakt `Base*` osztályokat. Ahelyett, hogy a `MyClass` a `BaseClass` örökölése révén kapna bizonyos funkciókat, ahelyett, hogy a függőségként kapná meg ezeket a funkciókat: +Tervezzük meg tehát a kódot másképp. Kerüljük az [absztrakt |nette:introduction-to-object-oriented-programming#abstract-classes] `Base*` osztályokat. Ahelyett, hogy a `MyClass` a `BaseClass` osztályból örökölve kapna bizonyos funkciókat, ahelyett, hogy függőségként átadnánk ezeket a funkciókat: ```php final class SomeFunctionality diff --git a/dependency-injection/it/faq.texy b/dependency-injection/it/faq.texy index 4dfa2d5e1a..80ab92df88 100644 --- a/dependency-injection/it/faq.texy +++ b/dependency-injection/it/faq.texy @@ -61,7 +61,7 @@ Ricordate che il passaggio alla Dependency Injection è un investimento nella qu Perché la composizione è preferibile all'ereditarietà? .[#toc-why-composition-is-preferred-over-inheritance] ------------------------------------------------------------------------------------------------------------ -È preferibile usare la composizione piuttosto che l'ereditarietà, perché serve a riutilizzare il codice senza doversi preoccupare dell'effetto a cascata delle modifiche. In questo modo si ottiene un accoppiamento più lasco, in cui non ci si deve preoccupare che la modifica di un codice provochi la modifica di un altro codice dipendente. Un esempio tipico è la situazione definita [inferno dei costruttori |passing-dependencies#Constructor hell]. +È preferibile usare la [composizione |nette:introduction-to-object-oriented-programming#composition] invece dell'[ereditarietà |nette:introduction-to-object-oriented-programming#inheritance] perché serve a riutilizzare il codice senza doversi preoccupare delle conseguenze delle modifiche. In questo modo, si ottiene un accoppiamento meno rigido, in cui non ci si deve preoccupare che la modifica di un codice comporti la necessità di modificare altro codice dipendente. Un esempio tipico è la situazione denominata " [inferno dei costruttori |passing-dependencies#Constructor hell]". Nette DI Container può essere utilizzato al di fuori di Nette? .[#toc-can-nette-di-container-be-used-outside-of-nette] diff --git a/dependency-injection/it/passing-dependencies.texy b/dependency-injection/it/passing-dependencies.texy index 47f03a6686..849437fa9c 100644 --- a/dependency-injection/it/passing-dependencies.texy +++ b/dependency-injection/it/passing-dependencies.texy @@ -96,9 +96,9 @@ final class MyClass extends BaseClass Il problema si presenta quando si vuole modificare il costruttore della classe `BaseClass`, ad esempio quando viene aggiunta una nuova dipendenza. Allora dobbiamo modificare anche tutti i costruttori dei figli. Il che rende tale modifica un inferno. -Come evitarlo? La soluzione è quella di **privilegiare la composizione rispetto all'ereditarietà**. +Come evitarlo? La soluzione è quella di **privilegiare la [composizione rispetto all'ereditarietà** |faq#Why composition is preferred over inheritance]. -Quindi progettiamo il codice in modo diverso. Eviteremo le classi astratte di `Base*`. Invece di ottenere una funzionalità da `MyClass` ereditando da `BaseClass`, avrà quella funzionalità passata come dipendenza: +Quindi progettiamo il codice in modo diverso. Eviteremo le classi [astratte |nette:introduction-to-object-oriented-programming#abstract-classes] di `Base*`. Invece di ottenere alcune funzionalità ereditando da `BaseClass`, `MyClass` avrà quella funzionalità passata come dipendenza: ```php final class SomeFunctionality diff --git a/dependency-injection/ja/faq.texy b/dependency-injection/ja/faq.texy index f8656dc7a5..f972f6d088 100644 --- a/dependency-injection/ja/faq.texy +++ b/dependency-injection/ja/faq.texy @@ -61,7 +61,7 @@ Dependency Injectionへの移行は、コードの品質とアプリケーショ なぜコンポジションが継承より好まれるのか? .[#toc-why-composition-is-preferred-over-inheritance] --------------------------------------------------------------------------- -継承ではなく、コンポジションを使用することが望ましい。あるコードを変更すると、他の依存するコードも変更しなければならなくなるという心配がないため、より緩やかな結合が可能になります。典型的な例として、「[コンストラクタ地獄 |passing-dependencies#Constructor hell]」と呼ばれる状況があります。 +[継承の |nette:en:introduction-to-object-oriented-programming#inheritance]代わりに[コンポジションを |nette:en:introduction-to-object-oriented-programming#composition]使うのが望ましいのは、コンポジションは変更の結果を気にすることなくコードを再利用できるからだ。そのため、あるコードを変更すると、他の依存するコードも変更しなければならなくなるという心配をする必要がない。典型的な例は、[コンストラクタ地獄 |passing-dependencies#Constructor hell]と呼ばれる状況だ。 ネッテDIコンテナは、ネッテ以外でも使えるのですか? .[#toc-can-nette-di-container-be-used-outside-of-nette] diff --git a/dependency-injection/ja/passing-dependencies.texy b/dependency-injection/ja/passing-dependencies.texy index df513946b2..6b7d36c81b 100644 --- a/dependency-injection/ja/passing-dependencies.texy +++ b/dependency-injection/ja/passing-dependencies.texy @@ -96,9 +96,9 @@ final class MyClass extends BaseClass 問題は、新しい依存関係が追加されたときなど、`BaseClass` クラスのコンストラクタを変更したいときに発生します。そうすると、子クラスのコンストラクタもすべて変更しなければならない。そのため、このような修正は地獄のようなものです。 -これを防ぐにはどうしたらいいのでしょうか?解決策は、**継承よりも構成を優先させる**ことです。 +これを防ぐには?解決策は、**[継承よりもコンポジションを |faq#Why composition is preferred over inheritance]優先させる[** |faq#Why composition is preferred over inheritance]ことだ。 -そこで、コードを違った形で設計してみましょう。抽象的な`Base*` クラスは避けることにします。`MyClass` が`BaseClass` を継承して機能を得る代わりに、その機能は依存関係として渡されるようにします。 +そこで、コードを別の方法で設計してみよう。[抽象的な |nette:en:introduction-to-object-oriented-programming#abstract-classes] `Base*` クラスは避けよう。`MyClass` が`BaseClass` を継承して機能を得る代わりに、その機能は依存関係として渡されます: ```php final class SomeFunctionality diff --git a/dependency-injection/pl/faq.texy b/dependency-injection/pl/faq.texy index 46b1bd8cc7..7441e70a05 100644 --- a/dependency-injection/pl/faq.texy +++ b/dependency-injection/pl/faq.texy @@ -61,7 +61,7 @@ Pamiętaj, że przejście na Dependency Injection jest inwestycją w jakość ko Dlaczego kompozycja jest preferowana nad dziedziczeniem? .[#toc-why-composition-is-preferred-over-inheritance] -------------------------------------------------------------------------------------------------------------- -Lepiej jest używać kompozycji niż dziedziczenia, ponieważ służy to celowi ponownego użycia kodu bez potrzeby martwienia się o efekt podstępnej zmiany. W ten sposób zapewnia bardziej luźne sprzężenie, gdzie nie musimy się martwić o to, że zmiana jakiegoś kodu powoduje, że inny zależny kod wymaga zmiany. Typowym przykładem jest sytuacja określona jako [piekło konstruktorów |passing-dependencies#Constructor hell]. +Preferowane jest użycie [kompozycji |nette:introduction-to-object-oriented-programming#composition] zamiast [dziedziczenia |nette:introduction-to-object-oriented-programming#inheritance], ponieważ służy ona do ponownego wykorzystania kodu bez konieczności martwienia się o konsekwencje zmian. W ten sposób zapewnia luźniejsze sprzężenie, w którym nie musimy się martwić, że zmiana jakiegoś kodu spowoduje konieczność zmiany innego zależnego kodu. Typowym przykładem jest sytuacja określana jako piekło [konstruktorów |passing-dependencies#Constructor hell]. Czy Nette DI Container może być używany poza Nette? .[#toc-can-nette-di-container-be-used-outside-of-nette] diff --git a/dependency-injection/pl/passing-dependencies.texy b/dependency-injection/pl/passing-dependencies.texy index db5b61194a..ee51056c95 100644 --- a/dependency-injection/pl/passing-dependencies.texy +++ b/dependency-injection/pl/passing-dependencies.texy @@ -96,9 +96,9 @@ final class MyClass extends BaseClass Problem pojawia się, gdy chcemy zmienić konstruktor klasy `BaseClass`, na przykład gdy dodamy nową zależność. Wtedy musimy zmodyfikować również wszystkie konstruktory dzieci. Co czyni taką modyfikację piekłem. -Jak temu zapobiec? Rozwiązaniem jest **priorytet kompozycji nad dziedziczeniem**. +Jak temu zapobiec? Rozwiązaniem jest **przedkładanie [kompozycji nad dziedziczenie** |faq#Why composition is preferred over inheritance]. -Zaprojektujmy więc kod inaczej. Będziemy unikać klas abstrakcyjnych `Base*`. Zamiast `MyClass` uzyskać pewną funkcjonalność poprzez dziedziczenie z `BaseClass`, będzie ona miała tę funkcjonalność przekazaną jako zależność: +Zaprojektujmy więc kod inaczej. Unikniemy [abstrakcyjnych |nette:introduction-to-object-oriented-programming#abstract-classes] klas `Base*`. Zamiast `MyClass` uzyskiwać pewną funkcjonalność poprzez dziedziczenie z `BaseClass`, będzie mieć tę funkcjonalność przekazaną jako zależność: ```php final class SomeFunctionality diff --git a/dependency-injection/pt/faq.texy b/dependency-injection/pt/faq.texy index 09f9f07758..c9ff9daa30 100644 --- a/dependency-injection/pt/faq.texy +++ b/dependency-injection/pt/faq.texy @@ -61,7 +61,7 @@ Lembre-se de que passar para a Injeção de Dependência é um investimento na q Por que a composição é preferível à herança? .[#toc-why-composition-is-preferred-over-inheritance] -------------------------------------------------------------------------------------------------- -É preferível usar composição em vez de herança, pois serve ao propósito da reutilização do código sem ter a necessidade de se preocupar com o efeito de trickle down da mudança. Assim, ele proporciona um acoplamento mais frouxo onde não temos que nos preocupar em mudar algum código causando algum outro código dependente que necessite de mudança. Um exemplo típico é a situação identificada como [o inferno do construtor |passing-dependencies#Constructor hell]. +É preferível usar a [composição |nette:introduction-to-object-oriented-programming#composition] em vez da [herança |nette:introduction-to-object-oriented-programming#inheritance] porque ela serve para reutilizar o código sem ter de se preocupar com as consequências das alterações. Assim, ela proporciona um acoplamento mais frouxo, em que não precisamos nos preocupar com o fato de que a alteração de algum código causará a necessidade de alterar outro código dependente. Um exemplo típico é uma situação conhecida como [inferno do construtor |passing-dependencies#Constructor hell]. O Nette DI Container pode ser usado fora da Nette? .[#toc-can-nette-di-container-be-used-outside-of-nette] diff --git a/dependency-injection/pt/passing-dependencies.texy b/dependency-injection/pt/passing-dependencies.texy index b1655bd3dc..0d9e6a6285 100644 --- a/dependency-injection/pt/passing-dependencies.texy +++ b/dependency-injection/pt/passing-dependencies.texy @@ -96,9 +96,9 @@ final class MyClass extends BaseClass O problema ocorre quando queremos mudar o construtor da classe `BaseClass`, por exemplo, quando uma nova dependência é acrescentada. Então temos que modificar todos os construtores das crianças também. O que faz de tal modificação um inferno. -Como evitar isso? A solução é **priorizar a composição sobre a herança***. +Como evitar isso? A solução é **priorizar a [composição em vez da herança** |faq#Why composition is preferred over inheritance]. -Portanto, vamos projetar o código de forma diferente. Evitaremos as aulas abstratas `Base*`. Ao invés de `MyClass` obter alguma funcionalidade herdando de `BaseClass`, terá essa funcionalidade passada como uma dependência: +Portanto, vamos projetar o código de forma diferente. Evitaremos classes `Base*` [abstratas |nette:introduction-to-object-oriented-programming#abstract-classes]. Em vez de `MyClass` obter alguma funcionalidade herdando de `BaseClass`, essa funcionalidade será passada como uma dependência: ```php final class SomeFunctionality diff --git a/dependency-injection/ro/faq.texy b/dependency-injection/ro/faq.texy index 9d09d2e6fe..807ecc97a1 100644 --- a/dependency-injection/ro/faq.texy +++ b/dependency-injection/ro/faq.texy @@ -61,7 +61,7 @@ Nu uitați că trecerea la Injectarea dependențelor este o investiție în cali De ce este preferată compoziția în locul moștenirii? .[#toc-why-composition-is-preferred-over-inheritance] ---------------------------------------------------------------------------------------------------------- -Este preferabilă utilizarea compoziției în locul moștenirii, deoarece servește scopului de reutilizare a codului, fără a fi nevoie să vă faceți griji cu privire la efectul de schimbare. Astfel, se asigură o cuplare mai lejeră, în care nu trebuie să ne facem griji că modificarea unui cod ar putea duce la modificarea unui alt cod dependent. Un exemplu tipic este situația identificată drept [iadul constructorilor |passing-dependencies#Constructor hell]. +Este de preferat să se utilizeze [compoziția |nette:introduction-to-object-oriented-programming#composition] în locul [moștenirii |nette:introduction-to-object-oriented-programming#inheritance], deoarece aceasta permite reutilizarea codului fără a fi nevoie să ne facem griji cu privire la consecințele modificărilor. Astfel, oferă un cuplaj mai slab, în care nu trebuie să ne facem griji că modificarea unui cod va determina necesitatea de a modifica alt cod dependent. Un exemplu tipic este o situație denumită " [iadul constructorilor |passing-dependencies#Constructor hell]". Poate fi utilizat Nette DI Container în afara Nette? .[#toc-can-nette-di-container-be-used-outside-of-nette] diff --git a/dependency-injection/ro/passing-dependencies.texy b/dependency-injection/ro/passing-dependencies.texy index 9c3d341285..fb686cfe1d 100644 --- a/dependency-injection/ro/passing-dependencies.texy +++ b/dependency-injection/ro/passing-dependencies.texy @@ -96,9 +96,9 @@ final class MyClass extends BaseClass Problema apare atunci când dorim să modificăm constructorul clasei `BaseClass`, de exemplu atunci când se adaugă o nouă dependență. Atunci trebuie să modificăm și toți constructorii copiilor. Ceea ce face ca o astfel de modificare să fie un iad. -Cum să prevenim acest lucru? Soluția este să **prioritizăm compoziția în detrimentul moștenirii**. +Cum se poate preveni acest lucru? Soluția constă în **prioritizarea [compoziției în detrimentul moștenirii** |faq#Why composition is preferred over inheritance]. -Așadar, haideți să proiectăm codul în mod diferit. Vom evita clasele abstracte `Base*`. În loc ca `MyClass` să obțină o anumită funcționalitate prin moștenirea de la `BaseClass`, aceasta va avea acea funcționalitate transmisă ca dependență: +Deci, să proiectăm codul în mod diferit. Vom evita clasele [abstracte |nette:introduction-to-object-oriented-programming#abstract-classes] `Base*`. În loc ca `MyClass` să primească o anumită funcționalitate prin moștenirea de la `BaseClass`, aceasta va avea acea funcționalitate transmisă ca dependență: ```php final class SomeFunctionality diff --git a/dependency-injection/ru/faq.texy b/dependency-injection/ru/faq.texy index bf7d5b1260..815c0bc076 100644 --- a/dependency-injection/ru/faq.texy +++ b/dependency-injection/ru/faq.texy @@ -61,7 +61,7 @@ DI не влияет на производительность приложен Почему композиция предпочтительнее наследования? .[#toc-why-composition-is-preferred-over-inheritance] ------------------------------------------------------------------------------------------------------ -Предпочтительнее использовать композицию, а не наследование, так как она служит цели повторного использования кода без необходимости беспокоиться о нисходящем эффекте изменений. Таким образом, это обеспечивает более свободную связь, где нам не нужно беспокоиться о том, что изменение какого-то кода приведет к тому, что другой зависимый код потребует изменений. Типичным примером является ситуация, называемая [ад конструкторов |passing-dependencies#Constructor hell]. +Предпочтительнее использовать [композицию |nette:introduction-to-object-oriented-programming#composition] вместо [наследования |nette:introduction-to-object-oriented-programming#inheritance], поскольку она позволяет повторно использовать код, не заботясь о последствиях изменений. Таким образом, обеспечивается более тесная связь, когда не нужно беспокоиться о том, что изменение одного кода приведет к необходимости изменения другого, зависимого кода. Типичным примером является ситуация, называемая " [адом конструкторов |passing-dependencies#Constructor hell]". Можно ли использовать Nette DI Container вне Nette? .[#toc-can-nette-di-container-be-used-outside-of-nette] diff --git a/dependency-injection/ru/passing-dependencies.texy b/dependency-injection/ru/passing-dependencies.texy index ed13246974..069d13d329 100644 --- a/dependency-injection/ru/passing-dependencies.texy +++ b/dependency-injection/ru/passing-dependencies.texy @@ -96,9 +96,9 @@ final class MyClass extends BaseClass Проблема возникает, когда мы хотим изменить конструктор класса `BaseClass`, например, когда добавляется новая зависимость. Тогда мы должны изменить все конструкторы дочерних классов. Что превращает такую модификацию в ад. -Как предотвратить это? Решение заключается в **приоритете композиции над наследованием**. +Как предотвратить это? Решение заключается в **приоритете [композиции над наследованием** |faq#Why composition is preferred over inheritance]. -Поэтому давайте спроектируем код по-другому. Мы будем избегать абстрактных классов `Base*`. Вместо того чтобы `MyClass` получал некоторую функциональность, наследуя от `BaseClass`, эта функциональность будет передаваться ему как зависимость: +Поэтому давайте спроектируем код по-другому. Мы будем избегать [абстрактных |nette:introduction-to-object-oriented-programming#abstract-classes] классов `Base*`. Вместо того чтобы `MyClass` получал некоторую функциональность, наследуя от `BaseClass`, ему будет передаваться эта функциональность как зависимость: ```php final class SomeFunctionality diff --git a/dependency-injection/sl/faq.texy b/dependency-injection/sl/faq.texy index 52b344bd7a..f7ca52162b 100644 --- a/dependency-injection/sl/faq.texy +++ b/dependency-injection/sl/faq.texy @@ -61,7 +61,7 @@ Ne pozabite, da je prehod na vbrizgavanje odvisnosti naložba v kakovost kode in Zakaj ima sestava prednost pred dedovanjem? .[#toc-why-composition-is-preferred-over-inheritance] ------------------------------------------------------------------------------------------------- -Namesto dedovanja je bolje uporabiti sestavo, saj je tako mogoče kodo ponovno uporabiti, ne da bi bilo treba skrbeti za učinek sprememb. Tako zagotavlja bolj ohlapno vezavo, pri kateri nam ni treba skrbeti, da bi sprememba neke kode povzročila spremembo druge odvisne kode. Tipičen primer je situacija, ki je opredeljena kot [pekel konstruktorjev |passing-dependencies#Constructor hell]. +Namesto [dedovanja |nette:introduction-to-object-oriented-programming#inheritance] je bolje uporabiti [sestavo |nette:introduction-to-object-oriented-programming#composition], saj omogoča ponovno uporabo kode, ne da bi morali skrbeti za posledice sprememb. Tako zagotavlja ohlapnejšo vezavo, pri kateri nam ni treba skrbeti, da bo sprememba neke kode povzročila potrebo po spremembi druge odvisne kode. Značilen primer je situacija, ki se imenuje [konstruktorski pekel |passing-dependencies#Constructor hell]. Ali se lahko vsebnik Nette DI Container uporablja zunaj sistema Nette? .[#toc-can-nette-di-container-be-used-outside-of-nette] diff --git a/dependency-injection/sl/passing-dependencies.texy b/dependency-injection/sl/passing-dependencies.texy index 88d40d5663..e9bb7e1997 100644 --- a/dependency-injection/sl/passing-dependencies.texy +++ b/dependency-injection/sl/passing-dependencies.texy @@ -96,9 +96,9 @@ final class MyClass extends BaseClass Težava se pojavi, ko želimo spremeniti konstruktor razreda `BaseClass`, na primer ko dodamo novo odvisnost. Takrat moramo spremeniti tudi vse konstruktorje otrok. Zaradi tega je takšna sprememba pekel. -Kako to preprečiti? Rešitev je, da **prednost dajemo kompoziciji pred dedovanjem**. +Kako to preprečiti? Rešitev je, da dajete prednost [sestavi pred dedovanjem** |faq#Why composition is preferred over inheritance]. -Zato kodo oblikujmo drugače. Izogibali se bomo abstraktnim `Base*` razredom. Namesto da bi razred `MyClass` pridobil neko funkcionalnost s podedovanjem od razreda `BaseClass`, mu bo ta funkcionalnost posredovana kot odvisnost: +Zato kodo oblikujmo drugače. Izognili se bomo [abstraktnim |nette:introduction-to-object-oriented-programming#abstract-classes] `Base*` razredom. Namesto da bi razred `MyClass` pridobil določeno funkcionalnost s podedovanjem od razreda `BaseClass`, mu bo ta funkcionalnost posredovana kot odvisnost: ```php final class SomeFunctionality diff --git a/dependency-injection/tr/faq.texy b/dependency-injection/tr/faq.texy index cb6cb89752..359c8192e3 100644 --- a/dependency-injection/tr/faq.texy +++ b/dependency-injection/tr/faq.texy @@ -61,7 +61,7 @@ Dependency Injection'a geçmenin kod kalitesine ve uygulamanın uzun vadeli sür Neden kalıtım yerine kompozisyon tercih edilir? .[#toc-why-composition-is-preferred-over-inheritance] ----------------------------------------------------------------------------------------------------- -Değişimin damlama etkisi konusunda endişelenmeye gerek kalmadan kodun yeniden kullanılabilirliği amacına hizmet ettiği için kalıtım yerine bileşimin kullanılması tercih edilir. Böylece, bazı kodların değiştirilmesinin diğer bazı bağımlı kodların değişmesine neden olması konusunda endişelenmemizi gerektirmeyen daha gevşek bir bağlantı sağlar. Tipik bir örnek, [kurucu cehennemi |passing-dependencies#Constructor hell] olarak tanımlanan durumdur. +[Kalıtım |nette:introduction-to-object-oriented-programming#inheritance] yerine [bileşimin |nette:introduction-to-object-oriented-programming#composition] kullanılması tercih edilir çünkü değişikliklerin sonuçları hakkında endişelenmek zorunda kalmadan kodun yeniden kullanılmasına hizmet eder. Böylece, bazı kodların değiştirilmesinin diğer bağımlı kodların değiştirilmesine neden olacağından endişelenmemize gerek kalmayan daha gevşek bir bağlantı sağlar. Tipik bir örnek, [kurucu cehennemi |passing-dependencies#Constructor hell] olarak adlandırılan bir durumdur. Nette DI Container Nette dışında kullanılabilir mi? .[#toc-can-nette-di-container-be-used-outside-of-nette] diff --git a/dependency-injection/tr/passing-dependencies.texy b/dependency-injection/tr/passing-dependencies.texy index d77ec173aa..7846ea3410 100644 --- a/dependency-injection/tr/passing-dependencies.texy +++ b/dependency-injection/tr/passing-dependencies.texy @@ -96,9 +96,9 @@ final class MyClass extends BaseClass Sorun, `BaseClass` sınıfının kurucusunu değiştirmek istediğimizde, örneğin yeni bir bağımlılık eklendiğinde ortaya çıkar. O zaman tüm alt sınıfların kurucularını da değiştirmemiz gerekir. Bu da böyle bir değişikliği cehenneme çevirir. -Bu nasıl önlenebilir? Çözüm **kalıtım yerine bileşime öncelik vermektir**. +Bu nasıl önlenebilir? Çözüm [**kalıtım yerine bileşime |faq#Why composition is preferred over inheritance] öncelik [vermektir** |faq#Why composition is preferred over inheritance]. -Öyleyse kodu farklı bir şekilde tasarlayalım. Soyut `Base*` sınıflarından kaçınacağız. `MyClass` , `BaseClass`'dan miras alarak bazı işlevler elde etmek yerine, bu işlevleri bir bağımlılık olarak aktaracaktır: +Öyleyse kodu farklı bir şekilde tasarlayalım. [Soyut |nette:introduction-to-object-oriented-programming#abstract-classes] `Base*` sınıflarından kaçınacağız. `MyClass` , `BaseClass`'dan miras alarak bazı işlevler elde etmek yerine, bu işlevselliği bir bağımlılık olarak geçirecektir: ```php final class SomeFunctionality diff --git a/dependency-injection/uk/faq.texy b/dependency-injection/uk/faq.texy index c04c4b1a9e..130d1a6617 100644 --- a/dependency-injection/uk/faq.texy +++ b/dependency-injection/uk/faq.texy @@ -61,7 +61,7 @@ DI не впливає на продуктивність програми або Чому композиція краща за успадкування? .[#toc-why-composition-is-preferred-over-inheritance] -------------------------------------------------------------------------------------------- -Краще використовувати композицію, ніж успадкування, оскільки вона слугує для повторного використання коду без необхідності турбуватися про ефект "просочування" змін. Таким чином, це забезпечує більш вільний зв'язок, коли нам не потрібно турбуватися про те, що зміна одного коду спричинить зміну іншого залежного коду, який також потребує змін. Типовим прикладом є ситуація, яку називають [пеклом конструктора |passing-dependencies#Constructor hell]. +Краще використовувати [композицію |nette:introduction-to-object-oriented-programming#composition] замість [успадкування |nette:introduction-to-object-oriented-programming#inheritance], оскільки вона дозволяє повторно використовувати код, не турбуючись про наслідки змін. Таким чином, це забезпечує більш слабкий зв'язок, коли нам не потрібно турбуватися про те, що зміна одного коду призведе до необхідності зміни іншого залежного коду. Типовим прикладом є ситуація, яку називають пеклом [конструктора |passing-dependencies#Constructor hell]. Чи можна використовувати Nette DI Container за межами Nette? .[#toc-can-nette-di-container-be-used-outside-of-nette] diff --git a/dependency-injection/uk/passing-dependencies.texy b/dependency-injection/uk/passing-dependencies.texy index 5200e69e95..6797c329ae 100644 --- a/dependency-injection/uk/passing-dependencies.texy +++ b/dependency-injection/uk/passing-dependencies.texy @@ -96,9 +96,9 @@ final class MyClass extends BaseClass Проблема виникає, коли ми хочемо змінити конструктор класу `BaseClass`, наприклад, коли додається нова залежність. Тоді нам доведеться модифікувати всі конструктори дочірніх класів. Що перетворює таку модифікацію на справжнє пекло. -Як цього уникнути? Рішення полягає в тому, щоб **приоритизувати композицію над успадкуванням**. +Як цьому запобігти? Рішення полягає в тому, щоб **надати пріоритет [композиції над успадкуванням** |faq#Why composition is preferred over inheritance]. -Отже, давайте проектувати код по-іншому. Уникаймо абстрактних класів `Base*`. Замість того, щоб `MyClass` отримував певну функціональність шляхом успадкування від `BaseClass`, він отримає цю функціональність як залежність: +Тож давайте спроектуємо код по-іншому. Ми будемо уникати [абстрактних |nette:introduction-to-object-oriented-programming#abstract-classes] класів `Base*`. Замість того, щоб `MyClass` отримував певну функціональність шляхом успадкування від `BaseClass`, він отримає цю функціональність як залежність: ```php final class SomeFunctionality diff --git a/quickstart/bg/@home.texy b/quickstart/bg/@home.texy index 3f9c74c040..6a69c02c80 100644 --- a/quickstart/bg/@home.texy +++ b/quickstart/bg/@home.texy @@ -7,7 +7,7 @@ След първите две глави ще имате свой собствен работещ блог и ще сте готови да публикувате страхотни публикации, въпреки че функциите ще бъдат доста ограничени след приключването на тези две глави. За да направите нещата по-приятни за вашите потребители, трябва да прочетете и следващите глави и да продължите да подобрявате приложението си. .[tip] -Този урок предполага, че сте завършили документа [Инсталиране |nette:installation] и успешно сте настроили инструментите си. +Този урок предполага, че сте завършили документа [Инсталиране |nette:installation] и успешно сте настроили инструментите си. Предполага се също, че разбирате [обектно-ориентираното програмиране в PHP |nette:introduction-to-object-oriented-programming]. Моля, използвайте PHP 8.1 или по-нова версия. Можете да намерите пълното приложение [в GitHub |https://github.com/nette-examples/quickstart/tree/v4.0]. diff --git a/quickstart/cs/@home.texy b/quickstart/cs/@home.texy index 6cf314d7eb..401452593d 100644 --- a/quickstart/cs/@home.texy +++ b/quickstart/cs/@home.texy @@ -7,7 +7,7 @@ Poznejme spolu Nette Framework, při vytváření jednoduchého blogu s komentá Již po prvních dvou kapitolách budeme mít svůj vlastní funkční blog a budeme moci publikovat své skvělé příspěvky, i když funkce budou zatím do značné míry omezeny. Měli byste si přečíst také následující kapitoly, kde si naprogramujeme přidávání komentářů, editování článků a na závěr blog zabezpečíme. .[tip] -Tento návod předpokládá, že jste přečetli stránku [Instalace |nette:installation] a úspěšně si připravili potřebné nástroje. +Tento návod předpokládá, že jste přečetli stránku [Instalace |nette:installation] a úspěšně si připravili potřebné nástroje. Také předpokládá, že rozumíte [objektově orientovanému programování v PHP |nette:introduction-to-object-oriented-programming]. Používejte prosím PHP 8.1 nebo novější. Kompletní aplikaci najdete [na GitHubu |https://github.com/nette-examples/quickstart/tree/v4.0]. diff --git a/quickstart/de/@home.texy b/quickstart/de/@home.texy index e9d1289a19..a09cf56fcf 100644 --- a/quickstart/de/@home.texy +++ b/quickstart/de/@home.texy @@ -7,7 +7,7 @@ Lernen Sie das Nette Framework kennen, indem Sie einen einfachen Blog mit Kommen Nach den ersten beiden Kapiteln haben Sie Ihren eigenen funktionierenden Blog und können Ihre tollen Beiträge veröffentlichen, auch wenn der Funktionsumfang nach Abschluss dieser beiden Kapitel ziemlich eingeschränkt ist. Um die Dinge für Ihre Nutzer schöner zu machen, sollten Sie auch die folgenden Kapitel lesen und Ihre Anwendung weiter verbessern. .[tip] -In diesem Tutorial wird davon ausgegangen, dass Sie das Dokument [Installation |nette:installation] abgeschlossen und Ihr Tooling erfolgreich eingerichtet haben. +Dieses Tutorial setzt voraus, dass Sie das Dokument [Installation |nette:installation] abgeschlossen und Ihr Tooling erfolgreich eingerichtet haben. Außerdem wird vorausgesetzt, dass Sie mit der [objektorientierten Programmierung in PHP |nette:introduction-to-object-oriented-programming] vertraut sind. Bitte verwenden Sie PHP 8.1 oder höher. Sie finden die vollständige Anwendung [auf GitHub |https://github.com/nette-examples/quickstart/tree/v4.0]. diff --git a/quickstart/el/@home.texy b/quickstart/el/@home.texy index 7be876f93f..fe9de743bd 100644 --- a/quickstart/el/@home.texy +++ b/quickstart/el/@home.texy @@ -7,7 +7,7 @@ Μετά τα δύο πρώτα κεφάλαια, θα έχετε το δικό σας λειτουργικό ιστολόγιο και θα είστε έτοιμοι να δημοσιεύσετε τις φοβερές αναρτήσεις σας, αν και οι δυνατότητες θα είναι αρκετά περιορισμένες μετά την ολοκλήρωση αυτών των δύο κεφαλαίων. Για να κάνετε τα πράγματα πιο ευχάριστα για τους χρήστες σας, θα πρέπει επίσης να διαβάσετε τα επόμενα κεφάλαια και να συνεχίσετε να βελτιώνετε την εφαρμογή σας. .[tip] -Αυτό το σεμινάριο προϋποθέτει ότι έχετε ολοκληρώσει το έγγραφο [Εγκατάσταση |nette:installation] και έχετε ρυθμίσει με επιτυχία τα εργαλεία σας. +Αυτό το σεμινάριο προϋποθέτει ότι έχετε ολοκληρώσει το έγγραφο [Εγκατάσταση |nette:installation] και έχετε ρυθμίσει με επιτυχία τα εργαλεία σας. Προϋποθέτει επίσης ότι κατανοείτε τον [αντικειμενοστραφή προγραμματισμό στην PHP |nette:introduction-to-object-oriented-programming]. Παρακαλούμε χρησιμοποιήστε PHP 8.1 ή νεότερη έκδοση. Μπορείτε να βρείτε την πλήρη εφαρμογή [στο GitHub |https://github.com/nette-examples/quickstart/tree/v4.0]. diff --git a/quickstart/en/@home.texy b/quickstart/en/@home.texy index e900687fef..8e222c163d 100644 --- a/quickstart/en/@home.texy +++ b/quickstart/en/@home.texy @@ -7,7 +7,7 @@ Get to know Nette Framework while creating a simple blog with comments. Let's be After the first two chapters, you will have your own working blog and you'll be ready to publish your awesome posts, although the features will be pretty much limited after completing these two chapters. To make things nicer for your users, you should also read the following chapters and keep improving your application. .[tip] -This tutorial assumes that you completed the [Installation |nette:installation] document and have successfully set up your tooling. +This tutorial assumes that you completed the [Installation |nette:installation] document and have successfully set up your tooling. It also assumes that you understand [object-oriented programming in PHP |nette:introduction-to-object-oriented-programming]. Please use PHP 8.1 or later. You can find the complete application [on GitHub |https://github.com/nette-examples/quickstart/tree/v4.0]. diff --git a/quickstart/es/@home.texy b/quickstart/es/@home.texy index e7fcf1dbba..d9f6ede195 100644 --- a/quickstart/es/@home.texy +++ b/quickstart/es/@home.texy @@ -7,7 +7,7 @@ Conoce Nette Framework mientras creas un sencillo blog con comentarios. ¡Empece Después de los dos primeros capítulos, tendrás tu propio blog funcionando y estarás listo para publicar tus increíbles posts, aunque las características serán bastante limitadas después de completar estos dos capítulos. Para hacer las cosas más agradables para tus usuarios, también deberías leer los siguientes capítulos y seguir mejorando tu aplicación. .[tip] -Este tutorial asume que usted ha completado el documento de [Instalación |nette:installation] y ha configurado con éxito sus herramientas. +Este tutorial asume que usted ha completado el documento de [Instalación |nette:installation] y ha configurado exitosamente sus herramientas. También asume que usted entiende la [programación orientada a objetos en PHP |nette:introduction-to-object-oriented-programming]. Por favor, utilice PHP 8.1 o posterior. Puedes encontrar la aplicación completa [en GitHub |https://github.com/nette-examples/quickstart/tree/v4.0]. diff --git a/quickstart/fr/@home.texy b/quickstart/fr/@home.texy index f658dbaf6c..fd46514d53 100644 --- a/quickstart/fr/@home.texy +++ b/quickstart/fr/@home.texy @@ -7,7 +7,7 @@ Apprenez à connaître Nette Framework tout en créant un simple blog avec des c Après les deux premiers chapitres, vous aurez votre propre blog fonctionnel et vous serez prêt à publier vos superbes articles, bien que les fonctionnalités soient assez limitées après avoir terminé ces deux chapitres. Pour rendre les choses plus agréables pour vos utilisateurs, vous devriez également lire les chapitres suivants et continuer à améliorer votre application. .[tip] -Ce tutoriel suppose que vous avez terminé le document d'[installation |nette:installation] et que vous avez configuré votre outil avec succès. +Ce tutoriel suppose que vous avez terminé le document d'[installation |nette:installation] et que vous avez configuré votre outil avec succès. Il suppose également que vous comprenez la [programmation orientée objet en PHP |nette:introduction-to-object-oriented-programming]. Veuillez utiliser PHP 8.1 ou plus récent. Vous pouvez trouver l'application complète [sur GitHub |https://github.com/nette-examples/quickstart/tree/v4.0]. diff --git a/quickstart/hu/@home.texy b/quickstart/hu/@home.texy index 0039d3d464..068ee759eb 100644 --- a/quickstart/hu/@home.texy +++ b/quickstart/hu/@home.texy @@ -7,7 +7,7 @@ Ismerkedjen meg a Nette Frameworkkel, miközben létrehoz egy egyszerű blogot k Az első két fejezet után saját működő blogod lesz, és készen állsz arra, hogy közzétedd a fantasztikus bejegyzéseidet, bár a funkciók eléggé korlátozottak lesznek a két fejezet befejezése után. Hogy a felhasználók számára még szebb legyen, érdemes a következő fejezeteket is elolvasnod, és folyamatosan fejlesztened az alkalmazásodat. .[tip] -Ez a bemutató feltételezi, hogy befejezte a [Telepítés |nette:installation] dokumentumot, és sikeresen beállította a szerszámokat. +Ez a bemutató feltételezi, hogy befejezte a [Telepítés |nette:installation] dokumentumot, és sikeresen beállította a szerszámokat. Feltételezi továbbá, hogy ért az [objektumorientált PHP programozáshoz |nette:introduction-to-object-oriented-programming]. Kérjük, használjon PHP 8.1 vagy újabb verziót. A teljes alkalmazás megtalálható a [GitHubon |https://github.com/nette-examples/quickstart/tree/v4.0]. diff --git a/quickstart/it/@home.texy b/quickstart/it/@home.texy index b4e7d163e7..3b699f777a 100644 --- a/quickstart/it/@home.texy +++ b/quickstart/it/@home.texy @@ -7,7 +7,7 @@ Imparate a conoscere Nette Framework creando un semplice blog con commenti. Iniz Dopo i primi due capitoli, avrete il vostro blog funzionante e sarete pronti a pubblicare i vostri fantastici post, anche se le funzionalità saranno piuttosto limitate dopo aver completato questi due capitoli. Per rendere le cose più piacevoli ai vostri utenti, dovreste leggere anche i capitoli successivi e continuare a migliorare la vostra applicazione. .[tip] -Questa esercitazione presuppone che abbiate completato il documento [Installazione |nette:installation] e che abbiate configurato con successo il vostro tooling. +Questa esercitazione presuppone che si sia completato il documento di [installazione |nette:installation] e che si sia configurato con successo lo strumento. Si presuppone inoltre che si conosca la [programmazione orientata agli oggetti in PHP |nette:introduction-to-object-oriented-programming]. Utilizzare PHP 8.1 o successivo. L'applicazione completa è disponibile [su GitHub |https://github.com/nette-examples/quickstart/tree/v4.0]. diff --git a/quickstart/pl/@home.texy b/quickstart/pl/@home.texy index f436718ce8..72a6f1f9e8 100644 --- a/quickstart/pl/@home.texy +++ b/quickstart/pl/@home.texy @@ -7,7 +7,7 @@ Poznajmy wspólnie Nette Framework, tworząc jednocześnie prosty blog z komenta Po pierwszych dwóch rozdziałach będziesz miał swój własny działający blog i będziesz gotowy do publikowania swoich niesamowitych postów, chociaż funkcje będą dość mocno ograniczone po ukończeniu tych dwóch rozdziałów. Aby uczynić rzeczy milszymi dla Twoich użytkowników, powinieneś również przeczytać kolejne rozdziały i wciąż ulepszać swoją aplikację. .[tip] -Ten poradnik zakłada, że użytkownik ukończył dokument [Instalacja |nette:installation] i pomyślnie skonfigurował swoje oprzyrządowanie. +Ten samouczek zakłada, że ukończyłeś dokument [instalacyjny |nette:installation] i pomyślnie skonfigurowałeś swoje narzędzia. Zakłada również, że rozumiesz [programowanie obiektowe w PHP |nette:introduction-to-object-oriented-programming]. Proszę używać PHP 8.1 lub nowszego. Kompletną aplikację można znaleźć [na GitHubie |https://github.com/nette-examples/quickstart/tree/v4.0]. diff --git a/quickstart/pt/@home.texy b/quickstart/pt/@home.texy index 95cf8a86d9..053e25a150 100644 --- a/quickstart/pt/@home.texy +++ b/quickstart/pt/@home.texy @@ -7,7 +7,7 @@ Conheça o Nette Framework enquanto cria um blog simples com comentários. Vamos Após os dois primeiros capítulos, você terá seu próprio blog de trabalho e estará pronto para publicar seus incríveis posts, embora as características sejam bastante limitadas após completar estes dois capítulos. Para tornar as coisas mais agradáveis para seus usuários, você também deve ler os capítulos seguintes e continuar melhorando sua aplicação. .[tip] -Este tutorial pressupõe que você completou o documento de [instalação |nette:installation] e configurou com sucesso suas ferramentas. +Este tutorial pressupõe que você tenha concluído o documento [de instalação |nette:installation] e configurado com êxito suas ferramentas. Ele também pressupõe que você entenda de [programação orientada a objetos em PHP |nette:introduction-to-object-oriented-programming]. Por favor, use PHP 8.1 ou posterior. Você pode encontrar a aplicação completa [no GitHub |https://github.com/nette-examples/quickstart/tree/v4.0]. diff --git a/quickstart/ro/@home.texy b/quickstart/ro/@home.texy index 35b39ebbdc..5bf51a417e 100644 --- a/quickstart/ro/@home.texy +++ b/quickstart/ro/@home.texy @@ -7,7 +7,7 @@ Faceți cunoștință cu Nette Framework în timp ce creați un blog simplu cu c După primele două capitole, veți avea propriul blog funcțional și veți fi gata să vă publicați postările minunate, deși funcțiile vor fi destul de limitate după finalizarea acestor două capitole. Pentru ca lucrurile să fie mai frumoase pentru utilizatori, ar trebui să citiți și următoarele capitole și să continuați să vă îmbunătățiți aplicația. .[tip] -Acest tutorial pornește de la premisa că ați finalizat documentul de [instalare |nette:installation] și că ați configurat cu succes uneltele. +Acest tutorial pornește de la premisa că ați finalizat documentul de [instalare |nette:installation] și că ați configurat cu succes uneltele. De asemenea, se presupune că înțelegeți [programarea orientată pe obiecte în PHP |nette:introduction-to-object-oriented-programming]. Vă rugăm să utilizați PHP 8.1 sau o versiune ulterioară. Puteți găsi aplicația completă [pe GitHub |https://github.com/nette-examples/quickstart/tree/v4.0]. diff --git a/quickstart/ru/@home.texy b/quickstart/ru/@home.texy index ed7270a31b..caf12f810d 100644 --- a/quickstart/ru/@home.texy +++ b/quickstart/ru/@home.texy @@ -7,7 +7,7 @@ После первых двух глав у вас будет свой собственный работающий блог, и вы будете готовы публиковать свои потрясающие посты, хотя после завершения этих двух глав возможности будут довольно сильно ограничены. Чтобы сделать все более приятным для ваших пользователей, вам также следует прочитать следующие главы и продолжать совершенствовать свое приложение. .[tip] -В этом руководстве предполагается, что вы завершили документ [Установка |nette:installation] и успешно настроили инструментарий. +В данном руководстве предполагается, что вы выполнили документ " [Установка |nette:installation] " и успешно настроили инструментарий. Также предполагается, что вы понимаете [объектно-ориентированное программирование на PHP |nette:introduction-to-object-oriented-programming]. Пожалуйста, используйте PHP 8.1 или более позднюю версию. Полное приложение вы можете найти [на GitHub |https://github.com/nette-examples/quickstart/tree/v4.0]. diff --git a/quickstart/sl/@home.texy b/quickstart/sl/@home.texy index d12b28f7a0..512f5448d2 100644 --- a/quickstart/sl/@home.texy +++ b/quickstart/sl/@home.texy @@ -7,7 +7,7 @@ Spoznajte ogrodje Nette in ustvarite preprost blog s komentarji. Začnimo! Po prvih dveh poglavjih boste imeli svoj delujoči blog in pripravljeni boste objavljati svoje odlične objave, čeprav bodo funkcije po zaključku teh dveh poglavij precej omejene. Da bi bile stvari za vaše uporabnike prijetnejše, preberite tudi naslednja poglavja in še naprej izboljšujte svojo aplikacijo. .[tip] -Ta vadnica predpostavlja, da ste dokončali dokument [Namestitev |nette:installation] in uspešno nastavili svoje orodje. +Ta vadnica predpostavlja, da ste dokončali dokument [Namestitev |nette:installation] in uspešno nastavili svoje orodje. Prav tako predpostavlja, da razumete [objektno usmerjeno programiranje v PHP |nette:introduction-to-object-oriented-programming]. Uporabite PHP 8.1 ali novejšo različico. Celotno aplikacijo lahko najdete [na GitHubu |https://github.com/nette-examples/quickstart/tree/v4.0]. diff --git a/quickstart/tr/@home.texy b/quickstart/tr/@home.texy index 8b7b9947c9..9a39f0b045 100644 --- a/quickstart/tr/@home.texy +++ b/quickstart/tr/@home.texy @@ -7,7 +7,7 @@ Yorumlarla basit bir blog oluştururken Nette Framework'ü tanıyın. Hadi başl İlk iki bölümden sonra, kendi çalışan blogunuza sahip olacaksınız ve harika gönderilerinizi yayınlamaya hazır olacaksınız, ancak bu iki bölümü tamamladıktan sonra özellikler oldukça sınırlı olacaktır. Kullanıcılarınız için işleri daha güzel hale getirmek için sonraki bölümleri de okumalı ve uygulamanızı geliştirmeye devam etmelisiniz. .[tip] -Bu eğitimde [Kurulum |nette:installation] belgesini tamamladığınız ve araçlarınızı başarıyla kurduğunuz varsayılmaktadır. +Bu öğretici, [Kurulum |nette:installation] belgesini tamamladığınızı ve araçlarınızı başarıyla kurduğunuzu varsayar. Ayrıca [PHP'de nesne yönelimli programlamayı |nette:introduction-to-object-oriented-programming] anladığınızı varsayar. Lütfen PHP 8.1 veya üstünü kullanın. Uygulamanın tamamını [GitHub |https://github.com/nette-examples/quickstart/tree/v4.0]'da bulabilirsiniz. diff --git a/quickstart/uk/@home.texy b/quickstart/uk/@home.texy index 3514fbacc0..293cf05c35 100644 --- a/quickstart/uk/@home.texy +++ b/quickstart/uk/@home.texy @@ -7,7 +7,7 @@ Після перших двох розділів у вас буде власний робочий блог, і ви будете готові публікувати свої чудові пости, хоча після завершення цих двох розділів функції будуть досить обмежені. Щоб зробити життя ваших користувачів приємнішим, ви також повинні прочитати наступні розділи і продовжувати вдосконалювати свій додаток. .[tip] -Цей посібник передбачає, що ви заповнили документ " [Інсталяція |nette:installation] " і успішно налаштували свої інструменти. +Цей посібник припускає, що ви заповнили [інсталяційний |nette:installation] документ і успішно налаштували ваш інструментарій. Також передбачається, що ви розумієте [об'єктно-орієнтоване програмування на PHP |nette:introduction-to-object-oriented-programming]. Будь ласка, використовуйте PHP 8.1 або новішу версію. Ви можете знайти повну версію програми [на GitHub |https://github.com/nette-examples/quickstart/tree/v4.0]. From 32a6f53265623cf8f1239ab1117a5792b569d827 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 25 Oct 2023 17:56:32 +0200 Subject: [PATCH 029/137] fixed link --- dependency-injection/bg/global-state.texy | 2 +- dependency-injection/cs/global-state.texy | 2 +- dependency-injection/de/global-state.texy | 2 +- dependency-injection/el/global-state.texy | 2 +- dependency-injection/en/global-state.texy | 2 +- dependency-injection/es/global-state.texy | 2 +- dependency-injection/fr/global-state.texy | 2 +- dependency-injection/hu/global-state.texy | 2 +- dependency-injection/it/global-state.texy | 2 +- dependency-injection/ja/global-state.texy | 2 +- dependency-injection/pl/global-state.texy | 2 +- dependency-injection/pt/global-state.texy | 2 +- dependency-injection/ro/global-state.texy | 2 +- dependency-injection/ru/global-state.texy | 2 +- dependency-injection/sl/global-state.texy | 2 +- dependency-injection/tr/global-state.texy | 2 +- dependency-injection/uk/global-state.texy | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) diff --git a/dependency-injection/bg/global-state.texy b/dependency-injection/bg/global-state.texy index bbb5bbc5ba..410e2eb227 100644 --- a/dependency-injection/bg/global-state.texy +++ b/dependency-injection/bg/global-state.texy @@ -301,4 +301,4 @@ class Foo По време на този процес може да откриете, че трябва да разделите даден клас, защото той има повече от една отговорност. Не се притеснявайте за това; стремете се към принципа на една отговорност. -*Искам да благодаря на Мишко Хевери, чиито статии като [Flaw: Brittle Global State & Singletons |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] са в основата на тази глава.* +*Искам да благодаря на Мишко Хевери, чиито статии като [Flaw: Brittle Global State & Singletons |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] са в основата на тази глава.* diff --git a/dependency-injection/cs/global-state.texy b/dependency-injection/cs/global-state.texy index 41c15a1b8c..7bf4a5f329 100644 --- a/dependency-injection/cs/global-state.texy +++ b/dependency-injection/cs/global-state.texy @@ -301,4 +301,4 @@ Když promýšlíte návrh kódu, myslete na to, že každé `static $foo` před Během tohoto procesu možná zjistíte, že je třeba třídu rozdělit, protože má více než jednu odpovědnost. Nebojte se toho; usilujte o princip jedné odpovědnosti. -*Rád bych poděkoval Miškovi Heverymu, jehož články, jako je [Flaw: Brittle Global State & Singletons |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/], jsou základem této kapitoly.* +*Rád bych poděkoval Miškovi Heverymu, jehož články, jako je [Flaw: Brittle Global State & Singletons |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/], jsou základem této kapitoly.* diff --git a/dependency-injection/de/global-state.texy b/dependency-injection/de/global-state.texy index 4df2cdc0ec..488839bea8 100644 --- a/dependency-injection/de/global-state.texy +++ b/dependency-injection/de/global-state.texy @@ -301,4 +301,4 @@ Wenn Sie über den Entwurf von Code nachdenken, sollten Sie bedenken, dass jedes Während dieses Prozesses kann es vorkommen, dass Sie eine Klasse aufteilen müssen, weil sie mehr als eine Verantwortung hat. Machen Sie sich keine Gedanken darüber; streben Sie das Prinzip der einen Verantwortung an. -*Ich möchte Miško Hevery danken, dessen Artikel wie [Flaw: Brittle Global State & Singletons |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] die Grundlage für dieses Kapitel bilden.* +*Ich möchte Miško Hevery danken, dessen Artikel wie [Flaw: Brittle Global State & Singletons |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] die Grundlage für dieses Kapitel bilden.* diff --git a/dependency-injection/el/global-state.texy b/dependency-injection/el/global-state.texy index 621b419f46..c9684f8313 100644 --- a/dependency-injection/el/global-state.texy +++ b/dependency-injection/el/global-state.texy @@ -301,4 +301,4 @@ class Foo Κατά τη διάρκεια αυτής της διαδικασίας, μπορεί να διαπιστώσετε ότι πρέπει να χωρίσετε μια κλάση επειδή έχει περισσότερες από μία αρμοδιότητες. Μην ανησυχείτε γι' αυτό- επιδιώξτε την αρχή της μίας ευθύνης. -*Θα ήθελα να ευχαριστήσω τον Miško Hevery, του οποίου άρθρα όπως το [Flaw: Brittle Global State & Singletons |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] αποτελούν τη βάση αυτού του κεφαλαίου.* +*Θα ήθελα να ευχαριστήσω τον Miško Hevery, του οποίου άρθρα όπως το [Flaw: Brittle Global State & Singletons |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] αποτελούν τη βάση αυτού του κεφαλαίου.* diff --git a/dependency-injection/en/global-state.texy b/dependency-injection/en/global-state.texy index f8f47d4b7e..a3c30bc990 100644 --- a/dependency-injection/en/global-state.texy +++ b/dependency-injection/en/global-state.texy @@ -301,4 +301,4 @@ When contemplating code design, keep in mind that each `static $foo` represents During this process, you may find that you need to split a class because it has more than one responsibility. Don't worry about it; strive for the principle of one responsibility. -*I would like to thank Miško Hevery, whose articles such as [Flaw: Brittle Global State & Singletons |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] form the basis of this chapter.* +*I would like to thank Miško Hevery, whose articles such as [Flaw: Brittle Global State & Singletons |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] form the basis of this chapter.* diff --git a/dependency-injection/es/global-state.texy b/dependency-injection/es/global-state.texy index 6a5d698af1..f659c7e7cd 100644 --- a/dependency-injection/es/global-state.texy +++ b/dependency-injection/es/global-state.texy @@ -301,4 +301,4 @@ Cuando contemples el diseño del código, ten en cuenta que cada `static $foo` r Durante este proceso, puede que descubras que necesitas dividir una clase porque tiene más de una responsabilidad. No te preocupes por ello; esfuérzate por el principio de una sola responsabilidad. -*Me gustaría dar las gracias a Miško Hevery, cuyos artículos como [Flaw: Brittle Global State & Singletons |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] forman la base de este capítulo.* +*Me gustaría dar las gracias a Miško Hevery, cuyos artículos como [Flaw: Brittle Global State & Singletons |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] forman la base de este capítulo.* diff --git a/dependency-injection/fr/global-state.texy b/dependency-injection/fr/global-state.texy index e55a85076d..f1471bab7a 100644 --- a/dependency-injection/fr/global-state.texy +++ b/dependency-injection/fr/global-state.texy @@ -301,4 +301,4 @@ Lorsque vous envisagez la conception d'un code, gardez à l'esprit que chaque `s Au cours de ce processus, vous constaterez peut-être que vous devez diviser une classe parce qu'elle a plus d'une responsabilité. Ne vous en préoccupez pas ; efforcez-vous de respecter le principe de la responsabilité unique. -*Je tiens à remercier Miško Hevery, dont les articles tels que [Flaw : Brittle Global State & Singletons |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] constituent la base de ce chapitre*. +*Je tiens à remercier Miško Hevery, dont les articles tels que [Flaw : Brittle Global State & Singletons |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] constituent la base de ce chapitre*. diff --git a/dependency-injection/hu/global-state.texy b/dependency-injection/hu/global-state.texy index 3ef1f4916f..1e1c80841e 100644 --- a/dependency-injection/hu/global-state.texy +++ b/dependency-injection/hu/global-state.texy @@ -301,4 +301,4 @@ Amikor a kódtervezésről gondolkodik, tartsa szem előtt, hogy minden egyes `s E folyamat során előfordulhat, hogy egy osztályt fel kell osztanod, mert egynél több felelőssége van. Ne aggódjon emiatt; törekedjen az egy felelősség elvére. -*Köszönöm Miško Hevery-nek, akinek olyan cikkei, mint a [Flaw: Brittle Global State & Singletons (Hiba: Törékeny globális állapot és szingletonok |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] ) képezik e fejezet alapját.* +*Köszönöm Miško Hevery-nek, akinek olyan cikkei, mint a [Flaw: Brittle Global State & Singletons (Hiba: Törékeny globális állapot és szingletonok |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] ) képezik e fejezet alapját.* diff --git a/dependency-injection/it/global-state.texy b/dependency-injection/it/global-state.texy index 11fc656413..3bba0b1c54 100644 --- a/dependency-injection/it/global-state.texy +++ b/dependency-injection/it/global-state.texy @@ -301,4 +301,4 @@ Quando si progetta il codice, bisogna tenere presente che ogni `static $foo` rap Durante questo processo, potreste scoprire che è necessario dividere una classe perché ha più di una responsabilità. Non preoccupatevi di questo; cercate di mantenere il principio di una sola responsabilità. -*Vorrei ringraziare Miško Hevery, i cui articoli, come [Flaw: Brittle Global State & Singletons |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/], costituiscono la base di questo capitolo.* +*Vorrei ringraziare Miško Hevery, i cui articoli, come [Flaw: Brittle Global State & Singletons |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/], costituiscono la base di questo capitolo.* diff --git a/dependency-injection/ja/global-state.texy b/dependency-injection/ja/global-state.texy index 7622def46d..7967ed3628 100644 --- a/dependency-injection/ja/global-state.texy +++ b/dependency-injection/ja/global-state.texy @@ -301,4 +301,4 @@ class Foo この過程で、クラスが複数の責任を持つため、クラスを分割する必要があることがわかるかもしれません。そのようなことは気にせず、1つの責任という原則を貫くようにしましょう。 -*本章は、Miško Hevery氏の「[Flaw: Brittle Global State & Singletons |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/]」等の論文に基づくものです。 +*本章は、Miško Hevery氏の「[Flaw: Brittle Global State & Singletons |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/]」等の論文に基づくものです。 diff --git a/dependency-injection/pl/global-state.texy b/dependency-injection/pl/global-state.texy index d2812e5143..4492031a5c 100644 --- a/dependency-injection/pl/global-state.texy +++ b/dependency-injection/pl/global-state.texy @@ -301,4 +301,4 @@ Rozważając projekt kodu, pamiętaj, że każdy `static $foo` reprezentuje prob Podczas tego procesu może się okazać, że musisz podzielić klasę, ponieważ ma ona więcej niż jedną odpowiedzialność. Nie przejmuj się tym; dąż do zasady jednej odpowiedzialności. -*Chciałbym podziękować Miško Hevery'emu, którego artykuły takie jak [Flaw: Brittle Global State & Singletons |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] stanowią podstawę tego rozdziału.* +*Chciałbym podziękować Miško Hevery'emu, którego artykuły takie jak [Flaw: Brittle Global State & Singletons |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] stanowią podstawę tego rozdziału.* diff --git a/dependency-injection/pt/global-state.texy b/dependency-injection/pt/global-state.texy index f5a33c5ea0..b50cbab11d 100644 --- a/dependency-injection/pt/global-state.texy +++ b/dependency-injection/pt/global-state.texy @@ -301,4 +301,4 @@ Ao contemplar o projeto do código, tenha em mente que cada `static $foo` repres Durante este processo, você pode descobrir que precisa dividir uma classe porque ela tem mais de uma responsabilidade. Não se preocupe com isso; esforce-se pelo princípio de uma responsabilidade. -*Gostaria de agradecer a Miško Hevery, cujos artigos como [Flaw: Brittle Global State & Singletons |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] formam a base deste capítulo.* +*Gostaria de agradecer a Miško Hevery, cujos artigos como [Flaw: Brittle Global State & Singletons |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] formam a base deste capítulo.* diff --git a/dependency-injection/ro/global-state.texy b/dependency-injection/ro/global-state.texy index 7a4d561745..ea7e944b2d 100644 --- a/dependency-injection/ro/global-state.texy +++ b/dependency-injection/ro/global-state.texy @@ -301,4 +301,4 @@ Atunci când vă gândiți la proiectarea codului, nu uitați că fiecare `stati În timpul acestui proces, s-ar putea să descoperiți că trebuie să divizați o clasă deoarece aceasta are mai multe responsabilități. Nu vă faceți griji în această privință; străduiți-vă să respectați principiul unei singure responsabilități. -*Doresc să îi mulțumesc lui Miško Hevery, ale cărui articole, precum [Flaw: Brittle Global State & Singletons |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/], constituie baza acestui capitol.* +*Doresc să îi mulțumesc lui Miško Hevery, ale cărui articole, precum [Flaw: Brittle Global State & Singletons |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/], constituie baza acestui capitol.* diff --git a/dependency-injection/ru/global-state.texy b/dependency-injection/ru/global-state.texy index fd015989bb..3e32260d4e 100644 --- a/dependency-injection/ru/global-state.texy +++ b/dependency-injection/ru/global-state.texy @@ -301,4 +301,4 @@ class Foo Во время этого процесса вы можете обнаружить, что вам нужно разделить класс, потому что он несет более одной ответственности. Не беспокойтесь об этом; стремитесь к принципу одной ответственности. -*Я хотел бы поблагодарить Мишко Хевери, чьи статьи, такие как [Flaw: Brittle Global State & Singletons |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/], легли в основу этой главы*. +*Я хотел бы поблагодарить Мишко Хевери, чьи статьи, такие как [Flaw: Brittle Global State & Singletons |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/], легли в основу этой главы*. diff --git a/dependency-injection/sl/global-state.texy b/dependency-injection/sl/global-state.texy index 841f1d51ab..6650892f07 100644 --- a/dependency-injection/sl/global-state.texy +++ b/dependency-injection/sl/global-state.texy @@ -301,4 +301,4 @@ Ko razmišljate o oblikovanju kode, imejte v mislih, da vsaka stran `static $foo Med tem postopkom boste morda ugotovili, da morate razred razdeliti, ker ima več kot eno odgovornost. Ne skrbite zaradi tega; prizadevajte si za načelo ene odgovornosti. -*Zahvaljujem se Mišku Heveryju, čigar članki, kot je [Flaw: Brittle Global State & Singletons |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/], so podlaga za to poglavje.* +*Zahvaljujem se Mišku Heveryju, čigar članki, kot je [Flaw: Brittle Global State & Singletons |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/], so podlaga za to poglavje.* diff --git a/dependency-injection/tr/global-state.texy b/dependency-injection/tr/global-state.texy index 72c7d53aa1..1cbfcdb6c6 100644 --- a/dependency-injection/tr/global-state.texy +++ b/dependency-injection/tr/global-state.texy @@ -301,4 +301,4 @@ Kod tasarımını düşünürken, her `static $foo` adresinin bir sorunu temsil Bu süreç sırasında, birden fazla sorumluluğu olduğu için bir sınıfı bölmeniz gerektiğini fark edebilirsiniz. Bu konuda endişelenmeyin; tek sorumluluk ilkesi için çaba gösterin. -*[Flaw: Brittle Global State & Singletons |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] gibi makaleleri bu bölümün temelini oluşturan Miško Hevery'ye teşekkür ederim.* +*[Flaw: Brittle Global State & Singletons |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/] gibi makaleleri bu bölümün temelini oluşturan Miško Hevery'ye teşekkür ederim.* diff --git a/dependency-injection/uk/global-state.texy b/dependency-injection/uk/global-state.texy index 489daa66b6..092a16313b 100644 --- a/dependency-injection/uk/global-state.texy +++ b/dependency-injection/uk/global-state.texy @@ -301,4 +301,4 @@ class Foo Під час цього процесу ви можете виявити, що вам потрібно розділити клас, оскільки він має більше однієї відповідальності. Не турбуйтеся про це; прагніть до принципу єдиної відповідальності. -*Я хотів би подякувати Мішко Хевері, чиї статті, такі як [Flaw: Brittle Global State та Singletons |http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/], лягли в основу цієї глави. Я хотів би подякувати Мішко Хевері.* +*Я хотів би подякувати Мішко Хевері, чиї статті, такі як [Flaw: Brittle Global State та Singletons |https://web.archive.org/web/20230321084133/http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/], лягли в основу цієї глави. Я хотів би подякувати Мішко Хевері.* From bd232a8f84b5dee3ae939195ee030880f73701c7 Mon Sep 17 00:00:00 2001 From: Patrik Sehnoutek <58843354+pat0s@users.noreply.github.com> Date: Sun, 29 Oct 2023 19:39:46 +0100 Subject: [PATCH 030/137] Typo (#1034) --- dependency-injection/cs/container.texy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependency-injection/cs/container.texy b/dependency-injection/cs/container.texy index 3583a27dad..0f861f22c6 100644 --- a/dependency-injection/cs/container.texy +++ b/dependency-injection/cs/container.texy @@ -41,7 +41,7 @@ $controller = $container->createUserController(); Kontejneru se pouze zeptáme na objekt a již nemusíme vědět nic o tom, jak jej vytvořit a jaké má závislosti; to všechno ví kontejner. Závislosti jsou kontejnerem injektovány automaticky. V tom je jeho síla. -Kontejner má zatím zapsané všechny údaje navrdo. Uděláme tedy další krok a přidáme parametry, aby byl kontejner skutečně užitečný: +Kontejner má zatím zapsané všechny údaje natvrdo. Uděláme tedy další krok a přidáme parametry, aby byl kontejner skutečně užitečný: ```php class Container From 8e3a29f9fda0d568e4e7c0adc55a737aff73927c Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sun, 29 Oct 2023 15:58:19 +0100 Subject: [PATCH 031/137] nette/forms 3.1.14 --- forms/bg/controls.texy | 81 ++++++++++++++++++++++++++++++++++++++---- forms/cs/controls.texy | 81 ++++++++++++++++++++++++++++++++++++++---- forms/de/controls.texy | 81 ++++++++++++++++++++++++++++++++++++++---- forms/el/controls.texy | 81 ++++++++++++++++++++++++++++++++++++++---- forms/en/controls.texy | 81 ++++++++++++++++++++++++++++++++++++++---- forms/es/controls.texy | 81 ++++++++++++++++++++++++++++++++++++++---- forms/fr/controls.texy | 81 ++++++++++++++++++++++++++++++++++++++---- forms/hu/controls.texy | 81 ++++++++++++++++++++++++++++++++++++++---- forms/it/controls.texy | 81 ++++++++++++++++++++++++++++++++++++++---- forms/pl/controls.texy | 81 ++++++++++++++++++++++++++++++++++++++---- forms/pt/controls.texy | 81 ++++++++++++++++++++++++++++++++++++++---- forms/ro/controls.texy | 81 ++++++++++++++++++++++++++++++++++++++---- forms/ru/controls.texy | 81 ++++++++++++++++++++++++++++++++++++++---- forms/sl/controls.texy | 81 ++++++++++++++++++++++++++++++++++++++---- forms/tr/controls.texy | 81 ++++++++++++++++++++++++++++++++++++++---- forms/uk/controls.texy | 81 ++++++++++++++++++++++++++++++++++++++---- 16 files changed, 1200 insertions(+), 96 deletions(-) diff --git a/forms/bg/controls.texy b/forms/bg/controls.texy index c3983e946b..9c3b11e008 100644 --- a/forms/bg/controls.texy +++ b/forms/bg/controls.texy @@ -20,13 +20,9 @@ $form->addText('name', 'Имя:') Максималната дължина може да бъде ограничена с помощта на `setMaxLength()`. Функцията [addFilter() |validation#Modifying-Input-Values] позволява да се промени стойността, въведена от потребителя. -Можете да използвате `setHtmlType()`, за да промените [символа на |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] входния елемент на `search`, `tel`, `url`, `range`, `datetime-local`, `month`, `time`, `week`, `color`. Вместо типовете `number` и `email` ви препоръчваме да използвате [addInteger |#addInteger], [addFloat |#addFloat] и [addEmail |#addEmail], които имат валидиране от страна на сървъра. +Можете да промените визуалния характер на текстово поле до типове като `search`, `tel` или `url`, като използвате `setHtmlType()`, както е показано в [спецификацията |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types]. Не забравяйте, че промяната на типа е само визуална и не изпълнява функции за валидиране. За типа `url` е подходящо да добавите специфично [правило за URL |validation#Text inputs]. -```php -$form->addText('color', 'Выберите цвет:') - ->setHtmlType('color') - ->addRule($form::Pattern, 'недопустимое значение', '[0-9a-f]{6}'); -``` +За други типове входни данни, като `number`, `range`, `email`, `date`, `datetime-local`, `time` и `color`, използвайте специализирани методи като [addInteger |#addInteger], [addFloat |#addFloat], [addEmail |#addEmail] [addDate |#addDate], [addTime |#addTime], [addDateTime |#addDateTime] и [addColor |#addColor], които осигуряват валидиране от страна на сървъра. Типовете `month` и `week` все още не се поддържат напълно от всички браузъри. Един елемент може да бъде зададен на така наречената "празна стойност", която е нещо подобно на стойността по подразбиране, но ако потребителят не я презапише, тя връща празен низ или `null`. @@ -259,6 +255,79 @@ $form->addMultiUpload('files', 'Файлы:') Правилата `MimeType` и `Image` идентифицират желания тип файл или изображение чрез неговия подпис. Целостта на целия файл не се проверява. Можете да разберете дали дадено изображение е повредено, например като се опитате да [го изтеглите |http:request#toImage]. +addDate(string|int $name, $label=null): DateTimeControl .[method]{data-version:3.1.14} +====================================================================================== + +Добавя поле, което позволява на потребителя лесно да въвежда дата, състояща се от година, месец и ден (клас [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +За стойност по подразбиране приема или обекти, реализиращи `DateTimeInterface`, низ с време, или число, представляващо времеви печат на UNIX. Същото се отнася и за аргументите на правилата `Min`, `Max` или `Range`, които определят минималната и максималната допустима дата. + +```php +$form->addDate('date', 'Date:') + ->setDefaultValue(new DateTime) + ->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month')); +``` + +По подразбиране програмата връща обект `DateTimeImmutable`. Използвайки метода `setFormat()`, можете да зададете [текстов формат |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] или времева марка: + +```php +$form->addDate('date', 'Date:') + ->setFormat('Y-m-d'); +``` + + +addTime(string|int $name, $label=null, bool $withSeconds = false): DateTimeControl .[method]{data-version:3.1.14} +================================================================================================================= + +Добавя поле, което позволява на потребителя лесно да въвежда време, състоящо се от часове, минути и по избор секунди (клас [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +За стойност по подразбиране то приема или обекти, реализиращи `DateTimeInterface`, низ с време, или число, представляващо UNIX времеви печат. Използва се само информацията за времето от тези входове; датата се игнорира. Същото се отнася и за аргументите на правилата `Min`, `Max` или `Range`, които определят минималното и максималното разрешено време. Ако зададената минимална стойност е по-висока от максималната, се създава времеви диапазон, обхващащ полунощ. + +```php +$form->addTime('time', 'Time:', withSeconds: true) + ->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']); +``` + +По подразбиране се връща обект `DateTimeImmutable` (с фиктивна дата 1 януари, година 0). Използвайки метода `setFormat()`, можете да зададете [текстов формат |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: + +```php +$form->addTime('time', 'Time:') + ->setFormat('H:i'); +``` + + +addDateTime(string|int $name, $label=null, bool $withSeconds = false): DateTimeControl .[method]{data-version:3.1.14} +===================================================================================================================== + +Добавя поле, което позволява на потребителя лесно да въвежда както дата, така и час, състоящи се от година, месец, ден, часове, минути и по желание секунди (клас [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +За стойност по подразбиране то приема или обекти, реализиращи `DateTimeInterface`, низ с време, или число, представляващо UNIX timestamp. Същото се отнася и за аргументите на правилата `Min`, `Max` или `Range`, които определят минималната и максималната допустима дата. + +```php +$form->addDateTime('datetime', 'Date and Time:') + ->setDefaultValue(new DateTime) + ->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month')); +``` + +По подразбиране програмата връща обект `DateTimeImmutable`. Използвайки метода `setFormat()`, можете да зададете [текстов формат |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] или времева марка: + +```php +$form->addDateTime('datetime') + ->setFormat(DateTimeControl::FormatTimestamp); +``` + + +addColor(string|int $name, $label=null): ColorPicker .[method]{data-version:3.1.14} +=================================================================================== + +Добавя поле за избор на цвят (клас [ColorPicker |api:Nette\Forms\Controls\ColorPicker]). Цветът е низ във формат `#rrggbb`. Ако потребителят не направи избор, върнатият цвят по подразбиране е черен `#000000`. + +```php +$form->addColor('color', 'Color:') + ->setDefaultValue('#3C8ED7'); +``` + + addHidden(string|int $name, string $default=null): HiddenField .[method] ======================================================================== diff --git a/forms/cs/controls.texy b/forms/cs/controls.texy index 46b5ccf4ed..a644c150b1 100644 --- a/forms/cs/controls.texy +++ b/forms/cs/controls.texy @@ -20,13 +20,9 @@ Automaticky validuje UTF-8, ořezává levo- a pravostranné mezery a odstraňuj Maximální délku lze omezit pomocí `setMaxLength()`. Pozměnit uživatelem vloženou hodnotu umožňuje [addFilter()|validation#Úprava vstupu]. -Pomocí `setHtmlType()` lze změnit [charakter|https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] vstupního prvku na `search`, `tel`, `url`, `range`, `datetime-local`, `month`, `time`, `week`, `color`. Místo typů `number` a `email` doporučujeme použít [#addInteger], [#addFloat] a [#addEmail], které disponují validací na straně serveru. +Pomocí `setHtmlType()` lze změnit vizuální charakter textového pole na typy jako `search`, `tel` nebo `url` viz [specifikace|https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types]. Pamatujte, že změna typu je pouze vizuální a nezastupuje funkci validace. Pro typ `url` je vhodné přidat specifické validační [pravidlo URL|validation#Textové vstupy]. -```php -$form->addText('color', 'Vyberte barvu:') - ->setHtmlType('color') - ->addRule($form::Pattern, 'invalid value', '[0-9a-f]{6}'); -``` +Pro další typy vstupů, jako `number`, `range`, `email`, `date`, `datetime-local`, `time` a `color`, použijte specializované metody jako [#addInteger], [#addFloat], [#addEmail] [#addDate], [#addTime], [#addDateTime] a [#addColor], které zajišťují serverovou validaci. Typy `month` a `week` zatím nejsou plně podporovány ve všech prohlížečích. Prvku lze nastavit tzv. empty-value, což je něco jako výchozí hodnota, ale pokud ji uživatel nezmění, vrátí prvek prázdný řetězec či `null`. @@ -259,6 +255,79 @@ Nikdy nevěřte originálním názvům souborů vráceným metodou `FileUpload:: Pravidla `MimeType` a `Image` detekují požadovaný typ na základě signatury souboru a neověřují jeho integritu. Zda není obrázek poškozený lze zjistit například pokusem o jeho [načtení|http:request#toImage]. +addDate(string|int $name, $label=null): DateTimeControl .[method]{data-version:3.1.14} +====================================================================================== + +Přidá políčko, které umožní uživateli snadno zadat datum skládající se z roku, měsíce a dne (třída [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +Jako výchozí hodnotu akceptuje buď objekty implementující rozhraní `DateTimeInterface`, řetězec s časem, nebo číslo představující UNIX timestamp. Totéž platí pro argumenty pravidel `Min`, `Max` nebo `Range`, jež definují minimální a maximální povolený datum. + +```php +$form->addDate('date', 'Datum:') + ->setDefaultValue(new DateTime) + ->addRule($form::Min, 'Datum musí být minimálně měsíc staré.', new DateTime('-1 month')); +``` + +Standardně vrací objekt `DateTimeImmutable`, metodou `setFormat()` můžete specifikovat [textový formát|https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] či timestamp: + +```php +$form->addDate('date', 'Datum:') + ->setFormat('Y-m-d'); +``` + + +addTime(string|int $name, $label=null, bool $withSeconds = false): DateTimeControl .[method]{data-version:3.1.14} +================================================================================================================= + +Přidá políčko, které umožní uživateli snadno zadat čas skládající se z hodin, minut a volitelně i sekund (třída [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +Jako výchozí hodnotu akceptuje buď objekty implementující rozhraní `DateTimeInterface`, řetězec s časem, nebo číslo představující UNIX timestamp. Z těchto vstupů je využita pouze časová informace, datum je ignorováno. Totéž platí pro argumenty pravidel `Min`, `Max` nebo `Range`, jež definují minimální a maximální povolený čas. Pokud je nastavená minimální hodnota vyšší než maximální, vytvoří se časový rozsah přesahující půlnoc. + +```php +$form->addTime('time', 'Čas:', withSeconds: true) + ->addRule($form::Range, 'Čas musí být v rozsahu od %d do %d.', ['12:30', '13:30']); +``` + +Standardně vrací objekt `DateTimeImmutable` (s fiktivním datem 1. ledna roku 0), metodou `setFormat()` můžete specifikovat [textový formát|https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: + +```php +$form->addTime('time', 'Čas:') + ->setFormat('H:i'); +``` + + +addDateTime(string|int $name, $label=null, bool $withSeconds = false): DateTimeControl .[method]{data-version:3.1.14} +===================================================================================================================== + +Přidá políčko, které umožní uživateli snadno zadat datum a čas skládající se z roku, měsíce, dne, hodin, minut a volitelně i sekund (třída [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +Jako výchozí hodnotu akceptuje buď objekty implementující rozhraní `DateTimeInterface`, řetězec s časem, nebo číslo představující UNIX timestamp. Totéž platí pro argumenty pravidel `Min`, `Max` nebo `Range`, jež definují minimální a maximální povolený datum. + +```php +$form->addDateTime('datetime', 'Datum a čas:') + ->setDefaultValue(new DateTime) + ->addRule($form::Min, 'Datum musí být minimálně měsíc staré.', new DateTime('-1 month')); +``` + +Standardně vrací objekt `DateTimeImmutable`, metodou `setFormat()` můžete specifikovat [textový formát|https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] či timestamp: + +```php +$form->addDateTime('datetime') + ->setFormat(DateTimeControl::FormatTimestamp); +``` + + +addColor(string|int $name, $label=null): ColorPicker .[method]{data-version:3.1.14} +=================================================================================== + +Přidá políčko pro výběr barvy (třída [ColorPicker |api:Nette\Forms\Controls\ColorPicker]). Barva je řetězec ve tvaru `#rrggbb`. Pokud uživatel volbu neprovede, vrátí se černá barva `#000000`. + +```php +$form->addColor('color', 'Barva:') + ->setDefaultValue('#3C8ED7'); +``` + + addHidden(string|int $name, string $default=null): HiddenField .[method] ======================================================================== diff --git a/forms/de/controls.texy b/forms/de/controls.texy index 8f6891b8a0..8a93444ebc 100644 --- a/forms/de/controls.texy +++ b/forms/de/controls.texy @@ -20,13 +20,9 @@ Es validiert automatisch UTF-8, schneidet linke und rechte Leerzeichen ab und en Die maximale Länge kann mit `setMaxLength()` begrenzt werden. Mit [addFilter() |validation#Modifying Input Values] können Sie den vom Benutzer eingegebenen Wert ändern. -Sie können `setHtmlType()` verwenden, um das [Zeichen |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] des Eingabeelements in `search`, `tel`, `url`, `range`, `datetime-local`, `month`, `time`, `week`, `color` zu ändern. Anstelle der Typen `number` und `email` empfehlen wir die Verwendung von [addInteger |#addInteger], [addFloat |#addFloat] und [addEmail |#addEmail], die über eine serverseitige Validierung verfügen. +Sie können das visuelle Zeichen eines Textfeldes in Typen wie `search`, `tel` oder `url` ändern, indem Sie `setHtmlType()` verwenden, wie in der [Spezifikation |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] angegeben. Denken Sie daran, dass die Änderung des Typs nur visuell ist und keine Validierungsfunktionen ausführt. Für den Typ `url` ist es sinnvoll, eine spezielle [URL-Regel |validation#Text inputs] hinzuzufügen. -```php -$form->addText('color', 'Choose color:') - ->setHtmlType('color') - ->addRule($form::Pattern, 'invalid value', '[0-9a-f]{6}'); -``` +Für andere Eingabetypen wie `number`, `range`, `email`, `date`, `datetime-local`, `time` und `color` verwenden Sie spezielle Methoden wie [addInteger |#addInteger], [addFloat |#addFloat], [addEmail |#addEmail] [addDate |#addDate], [addTime |#addTime], [addDateTime |#addDateTime] und [addColor |#addColor], die eine serverseitige Validierung gewährleisten. Die Typen `month` und `week` werden noch nicht von allen Browsern vollständig unterstützt. Für das Element kann der sogenannte empty-value gesetzt werden, der so etwas wie der Standardwert ist, aber, wenn der Benutzer ihn nicht überschreibt, einen leeren String oder `null` zurückgibt. @@ -259,6 +255,79 @@ Vertrauen Sie nicht auf die von der Methode `FileUpload::getName()` zurückgegeb Die Regeln `MimeType` und `Image` erkennen den gewünschten Typ einer Datei oder eines Bildes anhand ihrer Signatur. Die Integrität der gesamten Datei wird nicht geprüft. Sie können herausfinden, ob ein Bild nicht beschädigt ist, indem Sie beispielsweise versuchen, [es zu laden |http:request#toImage]. +addDate(string|int $name, $label=null): DateTimeControl .[method]{data-version:3.1.14} +====================================================================================== + +Fügt ein Feld hinzu, das es dem Benutzer ermöglicht, auf einfache Weise ein Datum bestehend aus Jahr, Monat und Tag einzugeben (Klasse [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +Für den Standardwert akzeptiert es entweder Objekte, die `DateTimeInterface` implementieren, eine Zeichenkette mit der Uhrzeit oder eine Zahl, die einen UNIX-Zeitstempel darstellt. Dasselbe gilt für die Regelargumente `Min`, `Max` oder `Range`, die das minimal und maximal zulässige Datum festlegen. + +```php +$form->addDate('date', 'Date:') + ->setDefaultValue(new DateTime) + ->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month')); +``` + +Standardmäßig wird ein `DateTimeImmutable` Objekt zurückgegeben. Mit der Methode `setFormat()` können Sie ein [Textformat |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] oder einen Zeitstempel angeben: + +```php +$form->addDate('date', 'Date:') + ->setFormat('Y-m-d'); +``` + + +addTime(string|int $name, $label=null, bool $withSeconds = false): DateTimeControl .[method]{data-version:3.1.14} +================================================================================================================= + +Fügt ein Feld hinzu, das dem Benutzer die einfache Eingabe der Zeit in Stunden, Minuten und optional Sekunden ermöglicht (Klasse [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +Als Standardwert akzeptiert es entweder Objekte, die `DateTimeInterface` implementieren, einen String mit der Zeit oder eine Zahl, die einen UNIX-Zeitstempel darstellt. Es wird nur die Zeitinformation aus diesen Eingaben verwendet; das Datum wird ignoriert. Dasselbe gilt für die Regelargumente `Min`, `Max` oder `Range`, die die minimal und maximal zulässige Zeit festlegen. Wenn der Mindestwert höher ist als der Höchstwert, wird ein Zeitbereich bis Mitternacht erstellt. + +```php +$form->addTime('time', 'Time:', withSeconds: true) + ->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']); +``` + +Standardmäßig wird ein `DateTimeImmutable` -Objekt (mit dem fiktiven Datum des 1. Januar, Jahr 0) zurückgegeben. Mit der Methode `setFormat()` können Sie ein [Textformat |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] angeben: + +```php +$form->addTime('time', 'Time:') + ->setFormat('H:i'); +``` + + +addDateTime(string|int $name, $label=null, bool $withSeconds = false): DateTimeControl .[method]{data-version:3.1.14} +===================================================================================================================== + +Fügt ein Feld hinzu, das es dem Benutzer ermöglicht, auf einfache Weise sowohl Datum als auch Uhrzeit einzugeben, bestehend aus Jahr, Monat, Tag, Stunden, Minuten und optional Sekunden (Klasse [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +Als Standardwert akzeptiert es entweder Objekte, die `DateTimeInterface` implementieren, einen String mit der Zeit oder eine Zahl, die einen UNIX-Zeitstempel darstellt. Dasselbe gilt für die Regelargumente `Min`, `Max` oder `Range`, die das minimal und maximal zulässige Datum festlegen. + +```php +$form->addDateTime('datetime', 'Date and Time:') + ->setDefaultValue(new DateTime) + ->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month')); +``` + +Standardmäßig wird ein `DateTimeImmutable` Objekt zurückgegeben. Mit der Methode `setFormat()` können Sie ein [Textformat |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] oder einen Zeitstempel angeben: + +```php +$form->addDateTime('datetime') + ->setFormat(DateTimeControl::FormatTimestamp); +``` + + +addColor(string|int $name, $label=null): ColorPicker .[method]{data-version:3.1.14} +=================================================================================== + +Fügt ein Farbauswahlfeld (Klasse [ColorPicker |api:Nette\Forms\Controls\ColorPicker]) hinzu. Die Farbe ist ein String im Format `#rrggbb`. Wenn der Benutzer keine Auswahl trifft, wird als Standardfarbe Schwarz zurückgegeben `#000000`. + +```php +$form->addColor('color', 'Color:') + ->setDefaultValue('#3C8ED7'); +``` + + addHidden(string|int $name, string $default=null): HiddenField .[method] ======================================================================== diff --git a/forms/el/controls.texy b/forms/el/controls.texy index a138d0e62d..12f94bb294 100644 --- a/forms/el/controls.texy +++ b/forms/el/controls.texy @@ -20,13 +20,9 @@ $form->addText('name', 'Name:') Το μέγιστο μήκος μπορεί να περιοριστεί χρησιμοποιώντας το `setMaxLength()`. Η [addFilter() |validation#Modifying Input Values] σας επιτρέπει να αλλάξετε την τιμή που εισάγει ο χρήστης. -Μπορείτε να χρησιμοποιήσετε το `setHtmlType()` για να αλλάξετε τον [χαρακτήρα |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] του στοιχείου εισόδου σε `search`, `tel`, `url`, `range`, `datetime-local`, `month`, `time`, `week`, `color`. Αντί των τύπων `number` και `email`, συνιστούμε να χρησιμοποιείτε τους τύπους [addInteger |#addInteger], [addFloat |#addFloat] και [addEmail |#addEmail], οι οποίοι διαθέτουν επικύρωση από την πλευρά του διακομιστή. +Μπορείτε να αλλάξετε τον οπτικό χαρακτήρα ενός πεδίου κειμένου σε τύπους όπως `search`, `tel` ή `url` χρησιμοποιώντας το `setHtmlType()`, όπως φαίνεται στις [προδιαγραφές |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types]. Να θυμάστε ότι η αλλαγή του τύπου είναι μόνο οπτική και δεν εκτελεί λειτουργίες επικύρωσης. Για τον τύπο `url`, είναι σκόπιμο να προσθέσετε έναν ειδικό [κανόνα URL |validation#Text inputs]. -```php -$form->addText('color', 'Choose color:') - ->setHtmlType('color') - ->addRule($form::Pattern, 'invalid value', '[0-9a-f]{6}'); -``` +Για άλλους τύπους εισόδου, όπως `number`, `range`, `email`, `date`, `datetime-local`, `time` και `color`, χρησιμοποιήστε εξειδικευμένες μεθόδους όπως [addInteger |#addInteger], [addFloat |#addFloat], [addEmail |#addEmail] [addDate |#addDate], [addTime |#addTime], [addDateTime |#addDateTime] και [addColor |#addColor], οι οποίες εξασφαλίζουν επικύρωση από την πλευρά του διακομιστή. Οι τύποι `month` και `week` δεν υποστηρίζονται ακόμη πλήρως από όλους τους φυλλομετρητές. Για το στοιχείο μπορεί να οριστεί η λεγόμενη κενή τιμή (empty-value), η οποία είναι κάτι σαν την προεπιλεγμένη τιμή, αλλά αν ο χρήστης δεν την αντικαταστήσει, επιστρέφει κενή συμβολοσειρά ή `null`. @@ -259,6 +255,79 @@ $form->addMultiUpload('files', 'Files:') Οι κανόνες `MimeType` και `Image` ανιχνεύουν τον απαιτούμενο τύπο αρχείου ή εικόνας από την υπογραφή του. Η ακεραιότητα ολόκληρου του αρχείου δεν ελέγχεται. Μπορείτε να διαπιστώσετε αν μια εικόνα δεν είναι κατεστραμμένη, για παράδειγμα, προσπαθώντας να [τη φορτώσετε |http:request#toImage]. +addDate(string|int $name, $label=null): DateTimeControl .[method]{data-version:3.1.14} +====================================================================================== + +Προσθέτει ένα πεδίο που επιτρέπει στο χρήστη να εισάγει εύκολα μια ημερομηνία που αποτελείται από έτος, μήνα και ημέρα (κλάση [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +Για την προεπιλεγμένη τιμή, δέχεται είτε αντικείμενα που υλοποιούν το `DateTimeInterface`, ένα αλφαριθμητικό με την ώρα, είτε έναν αριθμό που αντιπροσωπεύει ένα UNIX timestamp. Το ίδιο ισχύει και για τα ορίσματα των κανόνων `Min`, `Max` ή `Range`, τα οποία καθορίζουν την ελάχιστη και τη μέγιστη επιτρεπόμενη ημερομηνία. + +```php +$form->addDate('date', 'Date:') + ->setDefaultValue(new DateTime) + ->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month')); +``` + +Από προεπιλογή, επιστρέφει ένα αντικείμενο `DateTimeImmutable`. Χρησιμοποιώντας τη μέθοδο `setFormat()`, μπορείτε να καθορίσετε μια [μορφή κειμένου |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] ή μια χρονοσφραγίδα: + +```php +$form->addDate('date', 'Date:') + ->setFormat('Y-m-d'); +``` + + +addTime(string|int $name, $label=null, bool $withSeconds = false): DateTimeControl .[method]{data-version:3.1.14} +================================================================================================================= + +Προσθέτει ένα πεδίο που επιτρέπει στο χρήστη να εισάγει εύκολα την ώρα που αποτελείται από ώρες, λεπτά και προαιρετικά δευτερόλεπτα (κλάση [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +Για την προεπιλεγμένη τιμή, δέχεται είτε αντικείμενα που υλοποιούν το `DateTimeInterface`, ένα αλφαριθμητικό με την ώρα, είτε έναν αριθμό που αντιπροσωπεύει μια χρονοσφραγίδα UNIX. Χρησιμοποιείται μόνο η πληροφορία της ώρας από αυτές τις εισόδους- η ημερομηνία αγνοείται. Το ίδιο ισχύει και για τα ορίσματα των κανόνων `Min`, `Max` ή `Range`, τα οποία καθορίζουν τον ελάχιστο και μέγιστο επιτρεπόμενο χρόνο. Εάν η ελάχιστη τιμή που έχει οριστεί είναι μεγαλύτερη από τη μέγιστη, δημιουργείται ένα χρονικό εύρος που εκτείνεται μέχρι τα μεσάνυχτα. + +```php +$form->addTime('time', 'Time:', withSeconds: true) + ->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']); +``` + +Από προεπιλογή, επιστρέφει ένα αντικείμενο `DateTimeImmutable` (με φανταστική ημερομηνία την 1η Ιανουαρίου του έτους 0). Χρησιμοποιώντας τη μέθοδο `setFormat()`, μπορείτε να καθορίσετε μια [μορφή κειμένου |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: + +```php +$form->addTime('time', 'Time:') + ->setFormat('H:i'); +``` + + +addDateTime(string|int $name, $label=null, bool $withSeconds = false): DateTimeControl .[method]{data-version:3.1.14} +===================================================================================================================== + +Προσθέτει ένα πεδίο που επιτρέπει στο χρήστη να εισάγει εύκολα τόσο ημερομηνία όσο και ώρα που αποτελείται από έτος, μήνα, ημέρα, ώρες, λεπτά και προαιρετικά δευτερόλεπτα (κλάση [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +Για την προεπιλεγμένη τιμή, δέχεται είτε αντικείμενα που υλοποιούν το `DateTimeInterface`, ένα αλφαριθμητικό με την ώρα, είτε έναν αριθμό που αντιπροσωπεύει ένα UNIX timestamp. Το ίδιο ισχύει και για τα ορίσματα των κανόνων `Min`, `Max` ή `Range`, τα οποία καθορίζουν την ελάχιστη και τη μέγιστη επιτρεπόμενη ημερομηνία. + +```php +$form->addDateTime('datetime', 'Date and Time:') + ->setDefaultValue(new DateTime) + ->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month')); +``` + +Από προεπιλογή, επιστρέφει ένα αντικείμενο `DateTimeImmutable`. Χρησιμοποιώντας τη μέθοδο `setFormat()`, μπορείτε να καθορίσετε μια [μορφή κειμένου |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] ή μια χρονοσφραγίδα: + +```php +$form->addDateTime('datetime') + ->setFormat(DateTimeControl::FormatTimestamp); +``` + + +addColor(string|int $name, $label=null): ColorPicker .[method]{data-version:3.1.14} +=================================================================================== + +Προσθέτει ένα πεδίο επιλογής χρώματος (κλάση [ColorPicker |api:Nette\Forms\Controls\ColorPicker]). Το χρώμα είναι μια συμβολοσειρά στη μορφή `#rrggbb`. Εάν ο χρήστης δεν κάνει επιλογή, το προεπιλεγμένο χρώμα που επιστρέφεται είναι το μαύρο `#000000`. + +```php +$form->addColor('color', 'Color:') + ->setDefaultValue('#3C8ED7'); +``` + + addHidden(string|int $name, string $default=null): HiddenField .[method] ======================================================================== diff --git a/forms/en/controls.texy b/forms/en/controls.texy index 59b9206619..0b116fa600 100644 --- a/forms/en/controls.texy +++ b/forms/en/controls.texy @@ -20,13 +20,9 @@ It automatically validates UTF-8, trims left and right whitespaces, and removes The maximum length can be limited using `setMaxLength()`. The [addFilter()|validation#Modifying Input Values] allows you to change the user-entered value. -You can use `setHtmlType()` to change the [character |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] of the input element to `search`, `tel`, `url`, `range`, `datetime-local`, `month`, `time`, `week`, `color`. Instead of the `number` and `email` types, we recommend using [addInteger |#addInteger], [addFloat |#addFloat] and [addEmail |#addEmail], which have server-side validation. +You can change the visual character of a text field to types like `search`, `tel`, or `url` using `setHtmlType()`, as seen in the [specification|https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types]. Remember that changing the type is only visual and does not perform validation functions. For the `url` type, it is appropriate to add a specific [URL rule|validation#Text inputs]. -```php -$form->addText('color', 'Choose color:') - ->setHtmlType('color') - ->addRule($form::Pattern, 'invalid value', '[0-9a-f]{6}'); -``` +For other input types such as `number`, `range`, `email`, `date`, `datetime-local`, `time`, and `color`, use specialized methods like [#addInteger], [#addFloat], [#addEmail] [#addDate], [#addTime], [#addDateTime], and [#addColor], which ensure server-side validation. The types `month` and `week` are not yet fully supported in all browsers. The so-called empty-value can be set for the element, which is something like the default value, but if the user does not overwrite it, returns empty string or `null`. @@ -259,6 +255,79 @@ Do not trust the original file names returned by method `FileUpload::getName()`, Rules `MimeType` and `Image` detect required type of file or image by its signature. The integrity of the entire file is not checked. You can find out if an image is not corrupted for example by trying to [load it|http:request#toImage]. +addDate(string|int $name, $label=null): DateTimeControl .[method]{data-version:3.1.14} +====================================================================================== + +Adds a field that allows the user to easily input a date consisting of year, month, and day (class [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +For the default value, it accepts either objects implementing the `DateTimeInterface`, a string with time, or a number representing a UNIX timestamp. The same applies to the `Min`, `Max`, or `Range` rule arguments, which define the minimum and maximum allowed date. + +```php +$form->addDate('date', 'Date:') + ->setDefaultValue(new DateTime) + ->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month')); +``` + +By default, it returns a `DateTimeImmutable` object. Using the `setFormat()` method, you can specify a [text format|https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] or timestamp: + +```php +$form->addDate('date', 'Date:') + ->setFormat('Y-m-d'); +``` + + +addTime(string|int $name, $label=null, bool $withSeconds = false): DateTimeControl .[method]{data-version:3.1.14} +================================================================================================================= + +Adds a field that allows the user to easily input time consisting of hours, minutes, and optionally seconds (class [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +For the default value, it accepts either objects implementing the `DateTimeInterface`, a string with time, or a number representing a UNIX timestamp. Only the time information from these inputs is used; the date is ignored. The same applies to the `Min`, `Max`, or `Range` rule arguments, which define the minimum and maximum allowed time. If the minimum value set is higher than the maximum, a time range spanning midnight is created. + +```php +$form->addTime('time', 'Time:', withSeconds: true) + ->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']); +``` + +By default, it returns a `DateTimeImmutable` object (with a fictitious date of January 1, year 0). Using the `setFormat()` method, you can specify a [text format|https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: + +```php +$form->addTime('time', 'Time:') + ->setFormat('H:i'); +``` + + +addDateTime(string|int $name, $label=null, bool $withSeconds = false): DateTimeControl .[method]{data-version:3.1.14} +===================================================================================================================== + +Adds a field that allows the user to easily input both date and time consisting of year, month, day, hours, minutes, and optionally seconds (class [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +For the default value, it accepts either objects implementing the `DateTimeInterface`, a string with time, or a number representing a UNIX timestamp. The same applies to the `Min`, `Max`, or `Range` rule arguments, which define the minimum and maximum allowed date. + +```php +$form->addDateTime('datetime', 'Date and Time:') + ->setDefaultValue(new DateTime) + ->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month')); +``` + +By default, it returns a `DateTimeImmutable` object. Using the `setFormat()` method, you can specify a [text format|https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] or timestamp: + +```php +$form->addDateTime('datetime') + ->setFormat(DateTimeControl::FormatTimestamp); +``` + + +addColor(string|int $name, $label=null): ColorPicker .[method]{data-version:3.1.14} +=================================================================================== + +Adds a color selection field (class [ColorPicker |api:Nette\Forms\Controls\ColorPicker]). The color is a string in the format `#rrggbb`. If the user doesn't make a selection, the default color returned is black `#000000`. + +```php +$form->addColor('color', 'Color:') + ->setDefaultValue('#3C8ED7'); +``` + + addHidden(string|int $name, string $default=null): HiddenField .[method] ======================================================================== diff --git a/forms/es/controls.texy b/forms/es/controls.texy index 2e48bd6cfe..92501c63f6 100644 --- a/forms/es/controls.texy +++ b/forms/es/controls.texy @@ -20,13 +20,9 @@ Valida automáticamente UTF-8, recorta los espacios en blanco a izquierda y dere La longitud máxima puede limitarse mediante `setMaxLength()`. La [función addFilter() |validation#Modifying Input Values] permite cambiar el valor introducido por el usuario. -Puede utilizar `setHtmlType()` para cambiar el [carácter |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] del elemento de entrada a `search`, `tel`, `url`, `range`, `datetime-local`, `month`, `time`, `week`, `color`. En lugar de los tipos `number` y `email`, recomendamos utilizar [addInteger |#addInteger], [addFloat |#addFloat] y [addEmail |#addEmail], que tienen validación del lado del servidor. +Puede cambiar el carácter visual de un campo de texto a tipos como `search`, `tel`, o `url` utilizando `setHtmlType()`, como se ve en la [especificación |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types]. Recuerde que el cambio de tipo es sólo visual y no realiza funciones de validación. Para el tipo `url`, es conveniente añadir una [regla URL |validation#Text inputs] específica. -```php -$form->addText('color', 'Elige color:') - ->setHtmlType('color') - ->addRule($form::Pattern, 'valor no válido', '[0-9a-f]{6}'); -``` +Para otros tipos de entrada como `number`, `range`, `email`, `date`, `datetime-local`, `time`, y `color`, utilice métodos especializados como [addInteger |#addInteger], [addFloat |#addFloat], [addEmail |#addEmail] [addDate |#addDate], [addTime |#addTime], [addDateTime |#addDateTime], y [addColor |#addColor], que aseguran la validación del lado del servidor. Los tipos `month` y `week` aún no son totalmente compatibles con todos los navegadores. Se puede establecer el llamado empty-value para el elemento, que es algo así como el valor por defecto, pero si el usuario no lo sobrescribe, devuelve cadena vacía o `null`. @@ -259,6 +255,79 @@ No confíe en los nombres de archivo originales devueltos por el método `FileUp Las reglas `MimeType` y `Image` detectan el tipo de archivo o imagen requerido por su firma. No se comprueba la integridad de todo el archivo. Puedes averiguar si una imagen no está corrupta, por ejemplo, intentando [cargarla |http:request#toImage]. +addDate(string|int $name, $label=null): DateTimeControl .[method]{data-version:3.1.14} +====================================================================================== + +Añade un campo que permite al usuario introducir fácilmente una fecha consistente en año, mes y día (clase [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +Para el valor predeterminado, acepta objetos que implementen la regla `DateTimeInterface`, una cadena con la hora o un número que represente una marca de tiempo UNIX. Lo mismo ocurre con los argumentos de regla `Min`, `Max`, o `Range`, que definen la fecha mínima y máxima permitidas. + +```php +$form->addDate('date', 'Date:') + ->setDefaultValue(new DateTime) + ->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month')); +``` + +Por defecto, devuelve un objeto `DateTimeImmutable`. Mediante el método `setFormat()`, puede especificar un [formato de texto |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] o una marca de tiempo: + +```php +$form->addDate('date', 'Date:') + ->setFormat('Y-m-d'); +``` + + +addTime(string|int $name, $label=null, bool $withSeconds = false): DateTimeControl .[method]{data-version:3.1.14} +================================================================================================================= + +Añade un campo que permite al usuario introducir fácilmente la hora consistente en horas, minutos y, opcionalmente, segundos (clase [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +Por defecto, acepta objetos que implementen la clase `DateTimeInterface`, una cadena con la hora o un número que represente una marca de tiempo UNIX. Sólo se utiliza la información horaria de estas entradas; la fecha se ignora. Lo mismo ocurre con los argumentos de regla `Min`, `Max` o `Range`, que definen el tiempo mínimo y máximo permitido. Si el valor mínimo establecido es superior al máximo, se crea un intervalo de tiempo que abarca la medianoche. + +```php +$form->addTime('time', 'Time:', withSeconds: true) + ->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']); +``` + +Por defecto, devuelve un objeto `DateTimeImmutable` (con una fecha ficticia del 1 de enero del año 0). Mediante el método `setFormat()`, puede especificar un [formato de texto |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: + +```php +$form->addTime('time', 'Time:') + ->setFormat('H:i'); +``` + + +addDateTime(string|int $name, $label=null, bool $withSeconds = false): DateTimeControl .[method]{data-version:3.1.14} +===================================================================================================================== + +Añade un campo que permite al usuario introducir fácilmente tanto la fecha como la hora consistente en año, mes, día, horas, minutos y opcionalmente segundos (clase [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +Para el valor por defecto, acepta bien objetos que implementen el `DateTimeInterface`, una cadena con la hora, o un número que represente una marca de tiempo UNIX. Lo mismo se aplica a los argumentos de regla `Min`, `Max`, o `Range`, que definen la fecha mínima y máxima permitidas. + +```php +$form->addDateTime('datetime', 'Date and Time:') + ->setDefaultValue(new DateTime) + ->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month')); +``` + +Por defecto, devuelve un objeto `DateTimeImmutable`. Mediante el método `setFormat()`, puede especificar un [formato de texto |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] o una marca de tiempo: + +```php +$form->addDateTime('datetime') + ->setFormat(DateTimeControl::FormatTimestamp); +``` + + +addColor(string|int $name, $label=null): ColorPicker .[method]{data-version:3.1.14} +=================================================================================== + +Añade un campo de selección de color (clase [ColorPicker |api:Nette\Forms\Controls\ColorPicker]). El color es una cadena con el formato `#rrggbb`. Si el usuario no hace una selección, el color devuelto por defecto es el negro `#000000`. + +```php +$form->addColor('color', 'Color:') + ->setDefaultValue('#3C8ED7'); +``` + + addHidden(string|int $name, string $default=null): HiddenField .[method] ======================================================================== diff --git a/forms/fr/controls.texy b/forms/fr/controls.texy index 7909477786..6699cffb17 100644 --- a/forms/fr/controls.texy +++ b/forms/fr/controls.texy @@ -20,13 +20,9 @@ Il valide automatiquement l'UTF-8, coupe les espaces à gauche et à droite et s La longueur maximale peut être limitée en utilisant `setMaxLength()`. La [fonction addFilter() |validation#Modifying Input Values] permet de modifier la valeur saisie par l'utilisateur. -Vous pouvez utiliser `setHtmlType()` pour changer le [caractère de |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] l'élément d'entrée en `search`, `tel`, `url`, `range`, `datetime-local`, `month`, `time`, `week`, `color`. Au lieu des types `number` et `email`, nous vous recommandons d'utiliser [addInteger |#addInteger], [addFloat |#addFloat] et [addEmail |#addEmail], qui ont une validation côté serveur. +Vous pouvez modifier le caractère visuel d'un champ de texte en utilisant des types tels que `search`, `tel`, ou `url` en utilisant `setHtmlType()`, comme indiqué dans la [spécification |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types]. N'oubliez pas que le changement de type n'est que visuel et qu'il n'exécute pas de fonctions de validation. Pour le type `url`, il convient d'ajouter une [règle URL |validation#Text inputs] spécifique. -```php -$form->addText('color', 'Choose color:') - ->setHtmlType('color') - ->addRule($form::Pattern, 'invalid value', '[0-9a-f]{6}'); -``` +Pour les autres types d'entrée tels que `number`, `range`, `email`, `date`, `datetime-local`, `time`, et `color`, utilisez des méthodes spécialisées telles que [addInteger |#addInteger], [addFloat |#addFloat], [addEmail |#addEmail] [addDate |#addDate], [addTime |#addTime], [addDateTime |#addDateTime], et [addColor |#addColor], qui assurent la validation côté serveur. Les types `month` et `week` ne sont pas encore totalement pris en charge par tous les navigateurs. La valeur dite vide peut être définie pour l'élément, qui ressemble à la valeur par défaut, mais si l'utilisateur ne l'écrase pas, elle renvoie une chaîne vide ou `null`. @@ -259,6 +255,79 @@ Ne vous fiez pas aux noms de fichiers originaux renvoyés par la méthode `FileU Les règles `MimeType` et `Image` détectent le type de fichier ou d'image requis par sa signature. L'intégrité de l'ensemble du fichier n'est pas vérifiée. Vous pouvez savoir si une image n'est pas corrompue, par exemple en essayant de [la charger |http:request#toImage]. +addDate(string|int $name, $label=null): DateTimeControl .[method]{data-version:3.1.14} +====================================================================================== + +Ajoute un champ qui permet à l'utilisateur de saisir facilement une date composée de l'année, du mois et du jour (classe [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +Pour la valeur par défaut, il accepte soit des objets implémentant la classe `DateTimeInterface`, soit une chaîne de caractères avec l'heure, soit un nombre représentant un horodatage UNIX. Il en va de même pour les arguments `Min`, `Max` ou `Range`, qui définissent la date minimale et maximale autorisée. + +```php +$form->addDate('date', 'Date:') + ->setDefaultValue(new DateTime) + ->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month')); +``` + +Par défaut, elle renvoie un objet `DateTimeImmutable`. La méthode `setFormat()` permet de spécifier un [format texte |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] ou un horodatage : + +```php +$form->addDate('date', 'Date:') + ->setFormat('Y-m-d'); +``` + + +addTime(string|int $name, $label=null, bool $withSeconds = false): DateTimeControl .[method]{data-version:3.1.14} +================================================================================================================= + +Ajoute un champ qui permet à l'utilisateur de saisir facilement l'heure sous forme d'heures, de minutes et éventuellement de secondes (classe [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +Pour la valeur par défaut, il accepte soit des objets implémentant `DateTimeInterface`, soit une chaîne de caractères avec l'heure, soit un nombre représentant un horodatage UNIX. Seule l'information temporelle de ces entrées est utilisée ; la date est ignorée. Il en va de même pour les arguments `Min`, `Max` ou `Range`, qui définissent la durée minimale et maximale autorisée. Si la valeur minimale définie est supérieure à la valeur maximale, une plage horaire s'étendant jusqu'à minuit est créée. + +```php +$form->addTime('time', 'Time:', withSeconds: true) + ->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']); +``` + +Par défaut, la méthode renvoie un objet `DateTimeImmutable` (avec une date fictive du 1er janvier de l'année 0). La méthode `setFormat()` permet de spécifier un [format de texte |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: + +```php +$form->addTime('time', 'Time:') + ->setFormat('H:i'); +``` + + +addDateTime(string|int $name, $label=null, bool $withSeconds = false): DateTimeControl .[method]{data-version:3.1.14} +===================================================================================================================== + +Ajoute un champ qui permet à l'utilisateur de saisir facilement la date et l'heure en indiquant l'année, le mois, le jour, les heures, les minutes et, éventuellement, les secondes (classe [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +Pour la valeur par défaut, il accepte soit des objets implémentant la classe `DateTimeInterface`, soit une chaîne de caractères avec l'heure, soit un nombre représentant un horodatage UNIX. Il en va de même pour les arguments `Min`, `Max` ou `Range`, qui définissent la date minimale et maximale autorisée. + +```php +$form->addDateTime('datetime', 'Date and Time:') + ->setDefaultValue(new DateTime) + ->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month')); +``` + +Par défaut, elle renvoie un objet `DateTimeImmutable`. La méthode `setFormat()` permet de spécifier un [format texte |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] ou un horodatage : + +```php +$form->addDateTime('datetime') + ->setFormat(DateTimeControl::FormatTimestamp); +``` + + +addColor(string|int $name, $label=null): ColorPicker .[method]{data-version:3.1.14} +=================================================================================== + +Ajoute un champ de sélection de couleur (classe [ColorPicker |api:Nette\Forms\Controls\ColorPicker]). La couleur est une chaîne au format `#rrggbb`. Si l'utilisateur ne fait pas de sélection, la couleur renvoyée par défaut est le noir `#000000`. + +```php +$form->addColor('color', 'Color:') + ->setDefaultValue('#3C8ED7'); +``` + + addHidden(string|int $name, string $default=null): HiddenField .[method] ======================================================================== diff --git a/forms/hu/controls.texy b/forms/hu/controls.texy index 48ab6d0292..bf607218fe 100644 --- a/forms/hu/controls.texy +++ b/forms/hu/controls.texy @@ -20,13 +20,9 @@ Automatikusan érvényesíti az UTF-8 szabványt, levágja a bal és jobb oldali A maximális hossz a `setMaxLength()` segítségével korlátozható. Az [addFilter() |validation#Modifying Input Values] lehetővé teszi a felhasználó által megadott érték megváltoztatását. -A `setHtmlType()` segítségével a bemeneti elem [karakterét |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] megváltoztathatja `search`, `tel`, `url`, `range`, `datetime-local`, `month`, `time`, `week`, `color`. A `number` és `email` típusok helyett az [addInteger |#addInteger], [addFloat |#addFloat] és [addEmail |#addEmail] típusok használatát javasoljuk, amelyek szerveroldali érvényesítéssel rendelkeznek. +A szövegmező vizuális karakterét a `search`, `tel` vagy `url` típusokra változtathatja a `setHtmlType()` segítségével, ahogyan az a [specifikációban |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] látható. Ne feledje, hogy a típus megváltoztatása csak vizuális, és nem végez érvényesítési funkciókat. A `url` típushoz célszerű egy speciális [URL-szabályt |validation#Text inputs] hozzáadni. -```php -$form->addText('color', 'Choose color:') - ->setHtmlType('color') - ->addRule($form::Pattern, 'invalid value', '[0-9a-f]{6}'); -``` +Más bemeneti típusokhoz, mint például a `number`, `range`, `email`, `date`, `datetime-local`, `time` és `color`, használjon speciális módszereket, mint például az [addInteger |#addInteger], [addFloat |#addFloat], [addEmail |#addEmail] [addDate |#addDate], [addTime |#addTime], [addDateTime |#addDateTime] és [addColor |#addColor], amelyek biztosítják a szerveroldali érvényesítést. A `month` és a `week` típusok még nem támogatottak teljes mértékben minden böngészőben. Az elemhez beállítható az úgynevezett üres-érték, ami valami olyasmi, mint az alapértelmezett érték, de ha a felhasználó nem írja felül, akkor üres stringet vagy `null` ad vissza. @@ -259,6 +255,79 @@ Ne bízzon a `FileUpload::getName()` módszer által visszaküldött eredeti fá A `MimeType` és a `Image` szabályok az aláírás alapján ismerik fel a kívánt fájl- vagy képtípust. A teljes fájl sértetlenségét nem ellenőrzik. Azt, hogy egy kép nem sérült-e, például a [betöltési |http:request#toImage] próbálkozással állapíthatja meg. +addDate(string|int $name, $label=null): DateTimeControl .[method]{data-version:3.1.14} +====================================================================================== + +Hozzáad egy mezőt, amely lehetővé teszi a felhasználó számára, hogy egyszerűen beírjon egy dátumot, amely évből, hónapból és napból áll ( [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl] osztály). + +Alapértelmezett értékként elfogadja a `DateTimeInterface` objektumokat megvalósító objektumokat, az időt tartalmazó karakterláncot, vagy egy UNIX időbélyeget reprezentáló számot. Ugyanez vonatkozik a `Min`, `Max` vagy `Range` szabály argumentumaira is, amelyek a minimális és maximálisan megengedett dátumot határozzák meg. + +```php +$form->addDate('date', 'Date:') + ->setDefaultValue(new DateTime) + ->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month')); +``` + +Alapértelmezés szerint egy `DateTimeImmutable` objektumot ad vissza. A `setFormat()` módszerrel [szöveges formátumot |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] vagy időbélyeget adhat meg: + +```php +$form->addDate('date', 'Date:') + ->setFormat('Y-m-d'); +``` + + +addTime(string|int $name, $label=null, bool $withSeconds = false): DateTimeControl .[method]{data-version:3.1.14} +================================================================================================================= + +Hozzáad egy mezőt, amely lehetővé teszi a felhasználó számára, hogy egyszerűen beírja az órákból, percekből és opcionálisan másodpercekből álló időt ( [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl] osztály). + +Alapértelmezett értékként elfogadja a `DateTimeInterface` objektumokat megvalósító objektumokat, az időt tartalmazó karakterláncot vagy egy UNIX időbélyeget jelentő számot. Csak az ezekből a bemenetekből származó időinformáció kerül felhasználásra; a dátumot figyelmen kívül hagyja. Ugyanez vonatkozik a `Min`, `Max` vagy `Range` szabály argumentumaira is, amelyek a minimális és maximális megengedett időt határozzák meg. Ha a beállított minimális érték nagyobb, mint a maximális, akkor egy éjfélig tartó időtartomány jön létre. + +```php +$form->addTime('time', 'Time:', withSeconds: true) + ->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']); +``` + +Alapértelmezés szerint egy `DateTimeImmutable` objektumot ad vissza (a 0. év január 1-jei fiktív dátummal). A `setFormat()` módszerrel [szöveges formátumot |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] adhat meg: + +```php +$form->addTime('time', 'Time:') + ->setFormat('H:i'); +``` + + +addDateTime(string|int $name, $label=null, bool $withSeconds = false): DateTimeControl .[method]{data-version:3.1.14} +===================================================================================================================== + +Hozzáad egy olyan mezőt, amely lehetővé teszi a felhasználó számára, hogy egyszerűen beírja a dátumot és az időt, amely évből, hónapból, napból, órából, percből és opcionálisan másodpercekből áll ( [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl] osztály). + +Alapértelmezett értékként elfogadja a `DateTimeInterface` objektumokat megvalósító objektumokat, egy karakterláncot az idővel, vagy egy UNIX időbélyeget reprezentáló számot. Ugyanez vonatkozik a `Min`, `Max` vagy `Range` szabály argumentumaira is, amelyek a minimális és maximálisan megengedett dátumot határozzák meg. + +```php +$form->addDateTime('datetime', 'Date and Time:') + ->setDefaultValue(new DateTime) + ->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month')); +``` + +Alapértelmezés szerint egy `DateTimeImmutable` objektumot ad vissza. A `setFormat()` módszerrel [szöveges formátumot |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] vagy időbélyeget adhat meg: + +```php +$form->addDateTime('datetime') + ->setFormat(DateTimeControl::FormatTimestamp); +``` + + +addColor(string|int $name, $label=null): ColorPicker .[method]{data-version:3.1.14} +=================================================================================== + +Hozzáad egy színválasztó mezőt ( [ColorPicker |api:Nette\Forms\Controls\ColorPicker] osztály). A szín egy karakterlánc a `#rrggbb` formátumban. Ha a felhasználó nem választ, a visszaküldött alapértelmezett szín a fekete `#000000`. + +```php +$form->addColor('color', 'Color:') + ->setDefaultValue('#3C8ED7'); +``` + + addHidden(string|int $name, string $default=null): HiddenField .[method] ======================================================================== diff --git a/forms/it/controls.texy b/forms/it/controls.texy index 1155aaa398..2666d0bc36 100644 --- a/forms/it/controls.texy +++ b/forms/it/controls.texy @@ -20,13 +20,9 @@ Convalida automaticamente UTF-8, taglia gli spazi bianchi a destra e a sinistra La lunghezza massima può essere limitata utilizzando `setMaxLength()`. Il metodo [addFilter() |validation#Modifying Input Values] consente di modificare il valore inserito dall'utente. -Si può usare `setHtmlType()` per cambiare il [carattere |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] dell'elemento di input in `search`, `tel`, `url`, `range`, `datetime-local`, `month`, `time`, `week`, `color`. Al posto dei tipi `number` e `email`, si consiglia di usare [addInteger |#addInteger], [addFloat |#addFloat] e [addEmail |#addEmail], che hanno una validazione lato server. +È possibile cambiare il carattere visivo di un campo di testo in tipi come `search`, `tel`, o `url` usando `setHtmlType()`, come si vede nelle [specifiche |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types]. Ricordare che la modifica del tipo è solo visiva e non svolge funzioni di validazione. Per il tipo `url`, è opportuno aggiungere una [regola URL |validation#Text inputs] specifica. -```php -$form->addText('color', 'Choose color:') - ->setHtmlType('color') - ->addRule($form::Pattern, 'invalid value', '[0-9a-f]{6}'); -``` +Per altri tipi di input, come `number`, `range`, `email`, `date`, `datetime-local`, `time` e `color`, utilizzare metodi specializzati come [addInteger |#addInteger], [addFloat |#addFloat], [addEmail |#addEmail] [addDate |#addDate], [addTime |#addTime], [addDateTime |#addDateTime] e [addColor |#addColor], che garantiscono la validazione lato server. I tipi `month` e `week` non sono ancora pienamente supportati da tutti i browser. È possibile impostare il cosiddetto valore vuoto per l'elemento, che è qualcosa di simile al valore predefinito, ma se l'utente non lo sovrascrive, restituisce una stringa vuota o `null`. @@ -259,6 +255,79 @@ Non fidatevi dei nomi originali dei file restituiti dal metodo `FileUpload::getN Le regole `MimeType` e `Image` rilevano il tipo di file o immagine richiesto in base alla sua firma. L'integrità dell'intero file non viene controllata. È possibile scoprire se un'immagine non è danneggiata, ad esempio provando a [caricarla |http:request#toImage]. +addDate(string|int $name, $label=null): DateTimeControl .[method]{data-version:3.1.14} +====================================================================================== + +Aggiunge un campo che consente all'utente di inserire facilmente una data composta da anno, mese e giorno (classe [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +Per il valore predefinito, accetta o oggetti che implementano la regola `DateTimeInterface`, una stringa con l'ora o un numero che rappresenta un timestamp UNIX. Lo stesso vale per gli argomenti delle regole `Min`, `Max`, o `Range`, che definiscono la data minima e massima consentita. + +```php +$form->addDate('date', 'Date:') + ->setDefaultValue(new DateTime) + ->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month')); +``` + +Per impostazione predefinita, restituisce un oggetto `DateTimeImmutable`. Utilizzando il metodo `setFormat()`, è possibile specificare un [formato di testo |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] o un timestamp: + +```php +$form->addDate('date', 'Date:') + ->setFormat('Y-m-d'); +``` + + +addTime(string|int $name, $label=null, bool $withSeconds = false): DateTimeControl .[method]{data-version:3.1.14} +================================================================================================================= + +Aggiunge un campo che consente all'utente di inserire facilmente il tempo composto da ore, minuti e, facoltativamente, secondi (classe [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +Per il valore predefinito, accetta oggetti che implementano `DateTimeInterface`, una stringa con l'ora o un numero che rappresenta un timestamp UNIX. Solo le informazioni sull'ora di questi input vengono utilizzate; la data viene ignorata. Lo stesso vale per gli argomenti delle regole `Min`, `Max`, o `Range`, che definiscono il tempo minimo e massimo consentito. Se il valore minimo impostato è superiore a quello massimo, viene creato un intervallo di tempo che copre la mezzanotte. + +```php +$form->addTime('time', 'Time:', withSeconds: true) + ->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']); +``` + +Per impostazione predefinita, restituisce un oggetto `DateTimeImmutable` (con una data fittizia del 1° gennaio, anno 0). Utilizzando il metodo `setFormat()`, è possibile specificare un [formato di testo |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: + +```php +$form->addTime('time', 'Time:') + ->setFormat('H:i'); +``` + + +addDateTime(string|int $name, $label=null, bool $withSeconds = false): DateTimeControl .[method]{data-version:3.1.14} +===================================================================================================================== + +Aggiunge un campo che consente all'utente di inserire facilmente sia la data che l'ora, composta da anno, mese, giorno, ore, minuti e, facoltativamente, secondi (classe [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +Per il valore predefinito, accetta sia oggetti che implementano `DateTimeInterface`, sia una stringa con l'ora, sia un numero che rappresenta un timestamp UNIX. Lo stesso vale per gli argomenti delle regole `Min`, `Max`, o `Range`, che definiscono la data minima e massima consentita. + +```php +$form->addDateTime('datetime', 'Date and Time:') + ->setDefaultValue(new DateTime) + ->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month')); +``` + +Per impostazione predefinita, restituisce un oggetto `DateTimeImmutable`. Utilizzando il metodo `setFormat()`, è possibile specificare un [formato di testo |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] o un timestamp: + +```php +$form->addDateTime('datetime') + ->setFormat(DateTimeControl::FormatTimestamp); +``` + + +addColor(string|int $name, $label=null): ColorPicker .[method]{data-version:3.1.14} +=================================================================================== + +Aggiunge un campo di selezione del colore (classe [ColorPicker |api:Nette\Forms\Controls\ColorPicker]). Il colore è una stringa nel formato `#rrggbb`. Se l'utente non effettua alcuna selezione, il colore predefinito restituito è il nero `#000000`. + +```php +$form->addColor('color', 'Color:') + ->setDefaultValue('#3C8ED7'); +``` + + addHidden(string|int $name, string $default=null): HiddenField .[method] ======================================================================== diff --git a/forms/pl/controls.texy b/forms/pl/controls.texy index c81b9eb35e..758987e551 100644 --- a/forms/pl/controls.texy +++ b/forms/pl/controls.texy @@ -20,13 +20,9 @@ Automatycznie waliduje UTF-8, obcina lewe i prawe spacje oraz usuwa przerwy w li Maksymalna długość może być ograniczona za pomocą `setMaxLength()`. Modyfikacja wartości wprowadzonej przez użytkownika umożliwia [addFilter() |validation#Modifying-Input-Values]. -Możesz użyć `setHtmlType()`, aby zmienić [znak |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] elementu wejściowego na `search`, `tel`, `url`, `range`, `datetime-local`, `month`, `time`, `week`, `color`. Zamiast typów `number` i `email` zalecamy użycie [addInteger |#addInteger], [addFloat |#addFloat] i [addEmail |#addEmail], które mają walidację po stronie serwera. +Można zmienić wizualny charakter pola tekstowego na typy takie jak `search`, `tel`, lub `url` przy użyciu `setHtmlType()`, jak pokazano w [specyfikacji |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types]. Należy pamiętać, że zmiana typu jest tylko wizualna i nie wykonuje funkcji walidacji. W przypadku typu `url` należy dodać określoną [regułę adresu URL |validation#Text inputs]. -```php -$form->addText('color', 'Vyberte barvu:') - ->setHtmlType('color') - ->addRule($form::Pattern, 'invalid value', '[0-9a-f]{6}'); -``` +W przypadku innych typów wejściowych, takich jak `number`, `range`, `email`, `date`, `datetime-local`, `time` i `color`, należy użyć specjalistycznych metod, takich jak [addInteger |#addInteger], [addFloat |#addFloat], [addEmail |#addEmail], [addDate |#addDate], [addTime |#addTime], [addDateTime |#addDateTime] i [addColor |#addColor], które zapewniają walidację po stronie serwera. Typy `month` i `week` nie są jeszcze w pełni obsługiwane we wszystkich przeglądarkach. Element może być ustawiony na empty-value, co jest jak wartość domyślna, ale jeśli użytkownik nie zmieni go, element zwróci pusty ciąg lub `null`. @@ -259,6 +255,79 @@ Nigdy nie ufaj oryginalnym nazwom plików zwracanym przez metodę `FileUpload::g Reguły `MimeType` i `Image` wykrywają żądany typ na podstawie sygnatury pliku i nie sprawdzają jego integralności. Możesz określić, czy obraz nie jest uszkodzony, na przykład próbując go [odzyskać |http:request#toImage]. +addDate(string|int $name, $label=null): DateTimeControl .[method]{data-version:3.1.14} +====================================================================================== + +Dodaje pole, które pozwala użytkownikowi łatwo wprowadzić datę składającą się z roku, miesiąca i dnia (klasa [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +Dla wartości domyślnej akceptuje obiekty implementujące `DateTimeInterface`, ciąg znaków z czasem lub liczbę reprezentującą znacznik czasu UNIX. To samo dotyczy argumentów reguł `Min`, `Max` lub `Range`, które definiują minimalną i maksymalną dozwoloną datę. + +```php +$form->addDate('date', 'Date:') + ->setDefaultValue(new DateTime) + ->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month')); +``` + +Domyślnie zwraca ona obiekt `DateTimeImmutable`. Za pomocą metody `setFormat()` można określić [format tekstowy |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] lub znacznik czasu: + +```php +$form->addDate('date', 'Date:') + ->setFormat('Y-m-d'); +``` + + +addTime(string|int $name, $label=null, bool $withSeconds = false): DateTimeControl .[method]{data-version:3.1.14} +================================================================================================================= + +Dodaje pole, które umożliwia użytkownikowi łatwe wprowadzanie czasu składającego się z godzin, minut i opcjonalnie sekund (klasa [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +Dla wartości domyślnej akceptuje obiekty implementujące `DateTimeInterface`, ciąg znaków z czasem lub liczbę reprezentującą znacznik czasu UNIX. Używane są tylko informacje o czasie z tych danych wejściowych; data jest ignorowana. To samo dotyczy argumentów reguł `Min`, `Max` lub `Range`, które definiują minimalny i maksymalny dozwolony czas. Jeśli ustawiona wartość minimalna jest wyższa niż maksymalna, tworzony jest zakres czasu obejmujący północ. + +```php +$form->addTime('time', 'Time:', withSeconds: true) + ->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']); +``` + +Domyślnie zwraca obiekt `DateTimeImmutable` (z fikcyjną datą 1 stycznia, rok 0). Za pomocą metody `setFormat()` można określić [format tekstowy |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: + +```php +$form->addTime('time', 'Time:') + ->setFormat('H:i'); +``` + + +addDateTime(string|int $name, $label=null, bool $withSeconds = false): DateTimeControl .[method]{data-version:3.1.14} +===================================================================================================================== + +Dodaje pole, które umożliwia użytkownikowi łatwe wprowadzanie zarówno daty, jak i czasu składającego się z roku, miesiąca, dnia, godzin, minut i opcjonalnie sekund (klasa [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +Dla wartości domyślnej akceptuje obiekty implementujące `DateTimeInterface`, ciąg znaków z czasem lub liczbę reprezentującą znacznik czasu UNIX. To samo dotyczy argumentów reguł `Min`, `Max` lub `Range`, które definiują minimalną i maksymalną dozwoloną datę. + +```php +$form->addDateTime('datetime', 'Date and Time:') + ->setDefaultValue(new DateTime) + ->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month')); +``` + +Domyślnie zwraca ona obiekt `DateTimeImmutable`. Za pomocą metody `setFormat()` można określić [format tekstowy |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] lub znacznik czasu: + +```php +$form->addDateTime('datetime') + ->setFormat(DateTimeControl::FormatTimestamp); +``` + + +addColor(string|int $name, $label=null): ColorPicker .[method]{data-version:3.1.14} +=================================================================================== + +Dodaje pole wyboru koloru (klasa [ColorPicker |api:Nette\Forms\Controls\ColorPicker]). Kolor jest ciągiem znaków w formacie `#rrggbb`. Jeśli użytkownik nie dokona wyboru, domyślnym zwracanym kolorem jest czarny `#000000`. + +```php +$form->addColor('color', 'Color:') + ->setDefaultValue('#3C8ED7'); +``` + + addHidden(string|int $name, string $default=null): HiddenField .[method] ======================================================================== diff --git a/forms/pt/controls.texy b/forms/pt/controls.texy index 7436750031..be69298606 100644 --- a/forms/pt/controls.texy +++ b/forms/pt/controls.texy @@ -20,13 +20,9 @@ Ela valida automaticamente UTF-8, apara os espaços em branco à esquerda e à d O comprimento máximo pode ser limitado usando `setMaxLength()`. O [addFilter() |validation#Modifying Input Values] permite alterar o valor inserido pelo usuário. -Você pode usar `setHtmlType()` para alterar o [caractere |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] do elemento de entrada para `search`, `tel`, `url`, `range`, `datetime-local`, `month`, `time`, `week`, `color`. Em vez dos tipos `number` e `email`, recomendamos o uso de [addInteger |#addInteger], [addFloat |#addFloat] e [addEmail |#addEmail], que têm validação no lado do servidor. +Você pode alterar o caractere visual de um campo de texto para tipos como `search`, `tel`, ou `url` usando `setHtmlType()`, como visto na [especificação |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types]. Lembre-se de que a alteração do tipo é apenas visual e não executa funções de validação. Para o tipo `url`, é apropriado adicionar uma [regra de URL |validation#Text inputs] específica. -```php -$form->addText('color', 'Choose color:') - ->setHtmlType('color') - ->addRule($form::Pattern, 'invalid value', '[0-9a-f]{6}'); -``` +Para outros tipos de entrada, como `number`, `range`, `email`, `date`, `datetime-local`, `time` e `color`, use métodos especializados como [addInteger |#addInteger], [addFloat |#addFloat], [addEmail |#addEmail], [addDate |#addDate], [addTime |#addTime], [addDateTime |#addDateTime] e [addColor |#addColor], que garantem a validação do lado do servidor. Os tipos `month` e `week` ainda não são totalmente compatíveis com todos os navegadores. O chamado valor vazio pode ser definido para o elemento, que é algo como o valor padrão, mas se o usuário não o sobrescrever, retorna uma string vazia ou `null`. @@ -259,6 +255,79 @@ Não confie nos nomes originais dos arquivos devolvidos pelo método `FileUpload As regras `MimeType` e `Image` detectam o tipo de arquivo ou imagem exigida por sua assinatura. A integridade do arquivo inteiro não é verificada. Você pode descobrir se uma imagem não está corrompida, por exemplo, ao tentar [carregá-la |http:request#toImage]. +addDate(string|int $name, $label=null): DateTimeControl .[method]{data-version:3.1.14} +====================================================================================== + +Adiciona um campo que permite ao usuário inserir facilmente uma data composta por ano, mês e dia (classe [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +Para o valor padrão, ele aceita objetos que implementam o `DateTimeInterface`, uma cadeia de caracteres com a hora ou um número que representa um carimbo de data/hora do UNIX. O mesmo se aplica aos argumentos de regra `Min`, `Max` ou `Range`, que definem a data mínima e máxima permitida. + +```php +$form->addDate('date', 'Date:') + ->setDefaultValue(new DateTime) + ->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month')); +``` + +Por padrão, ele retorna um objeto `DateTimeImmutable`. Usando o método `setFormat()`, você pode especificar um [formato de texto |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] ou um carimbo de data/hora: + +```php +$form->addDate('date', 'Date:') + ->setFormat('Y-m-d'); +``` + + +addTime(string|int $name, $label=null, bool $withSeconds = false): DateTimeControl .[method]{data-version:3.1.14} +================================================================================================================= + +Adiciona um campo que permite que o usuário insira facilmente o tempo composto por horas, minutos e, opcionalmente, segundos (classe [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +Para o valor padrão, ele aceita objetos que implementam o `DateTimeInterface`, uma cadeia de caracteres com a hora ou um número que representa um carimbo de data/hora do UNIX. Somente as informações de hora dessas entradas são usadas; a data é ignorada. O mesmo se aplica aos argumentos de regra `Min`, `Max` ou `Range`, que definem o tempo mínimo e máximo permitido. Se o valor mínimo definido for maior que o máximo, será criado um intervalo de tempo que vai até a meia-noite. + +```php +$form->addTime('time', 'Time:', withSeconds: true) + ->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']); +``` + +Por padrão, ele retorna um objeto `DateTimeImmutable` (com uma data fictícia de 1º de janeiro do ano 0). Usando o método `setFormat()`, você pode especificar um [formato de texto |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: + +```php +$form->addTime('time', 'Time:') + ->setFormat('H:i'); +``` + + +addDateTime(string|int $name, $label=null, bool $withSeconds = false): DateTimeControl .[method]{data-version:3.1.14} +===================================================================================================================== + +Adiciona um campo que permite que o usuário insira facilmente data e hora, consistindo em ano, mês, dia, horas, minutos e, opcionalmente, segundos (classe [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +Para o valor padrão, ele aceita objetos que implementam o `DateTimeInterface`, uma cadeia de caracteres com a hora ou um número que representa um carimbo de data/hora do UNIX. O mesmo se aplica aos argumentos de regra `Min`, `Max` ou `Range`, que definem a data mínima e máxima permitida. + +```php +$form->addDateTime('datetime', 'Date and Time:') + ->setDefaultValue(new DateTime) + ->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month')); +``` + +Por padrão, ele retorna um objeto `DateTimeImmutable`. Usando o método `setFormat()`, você pode especificar um [formato de texto |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] ou um carimbo de data/hora: + +```php +$form->addDateTime('datetime') + ->setFormat(DateTimeControl::FormatTimestamp); +``` + + +addColor(string|int $name, $label=null): ColorPicker .[method]{data-version:3.1.14} +=================================================================================== + +Adiciona um campo de seleção de cores (classe [ColorPicker |api:Nette\Forms\Controls\ColorPicker]). A cor é uma cadeia de caracteres no formato `#rrggbb`. Se o usuário não fizer uma seleção, a cor padrão retornada será o preto `#000000`. + +```php +$form->addColor('color', 'Color:') + ->setDefaultValue('#3C8ED7'); +``` + + addHidden(string|int $name, string $default=null): HiddenField .[method] ======================================================================== diff --git a/forms/ro/controls.texy b/forms/ro/controls.texy index 41ec7f51b8..78f5294644 100644 --- a/forms/ro/controls.texy +++ b/forms/ro/controls.texy @@ -20,13 +20,9 @@ Validează automat UTF-8, taie spațiile albe din stânga și din dreapta și el Lungimea maximă poate fi limitată folosind `setMaxLength()`. [AddFilter() |validation#Modifying Input Values] vă permite să modificați valoarea introdusă de utilizator. -Puteți utiliza `setHtmlType()` pentru a schimba [caracterul |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] elementului de intrare în `search`, `tel`, `url`, `range`, , `datetime-local`, `month`, `time`, `week`, `color`. În locul tipurilor `number` și `email`, vă recomandăm să utilizați [addInteger |#addInteger], [addFloat |#addFloat] și [addEmail |#addEmail], care au validare pe server. +Puteți schimba caracterul vizual al unui câmp de text în tipuri precum `search`, `tel`, sau `url` folosind `setHtmlType()`, așa cum se vede în [specificație |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types]. Rețineți că schimbarea tipului este doar vizuală și nu îndeplinește funcții de validare. Pentru tipul `url`, este oportun să se adauge o [regulă URL |validation#Text inputs] specifică. -```php -$form->addText('color', 'Choose color:') - ->setHtmlType('color') - ->addRule($form::Pattern, 'invalid value', '[0-9a-f]{6}'); -``` +Pentru alte tipuri de intrare, cum ar fi `number`, `range`, `email`, `date`, `datetime-local`, `time` și `color`, utilizați metode specializate, cum ar fi [addInteger |#addInteger], [addFloat |#addFloat], [addEmail |#addEmail] [addDate |#addDate], [addTime |#addTime], [addDateTime |#addDateTime] și [addColor |#addColor], care asigură validarea pe partea serverului. Tipurile `month` și `week` nu sunt încă pe deplin acceptate în toate browserele. Pentru element se poate seta așa-numita "empty-value", care este ceva de genul valorii implicite, dar, dacă utilizatorul nu o suprascrie, returnează un șir de caractere gol sau `null`. @@ -259,6 +255,79 @@ Nu vă încredeți în numele de fișier original returnat de metoda `FileUpload Regulile `MimeType` și `Image` detectează tipul necesar de fișier sau imagine prin semnătura acestuia. Integritatea întregului fișier nu este verificată. Puteți afla dacă o imagine nu este coruptă, de exemplu, încercând să [o încărcați |http:request#toImage]. +addDate(string|int $name, $label=null): DateTimeControl .[method]{data-version:3.1.14} +====================================================================================== + +Adaugă un câmp care permite utilizatorului să introducă cu ușurință o dată formată din an, lună și zi (clasa [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +Pentru valoarea implicită, acceptă fie obiecte care implementează `DateTimeInterface`, fie un șir de caractere cu ora, fie un număr reprezentând un timestamp UNIX. Același lucru este valabil și pentru argumentele regulilor `Min`, `Max` sau `Range`, care definesc data minimă și maximă admisă. + +```php +$form->addDate('date', 'Date:') + ->setDefaultValue(new DateTime) + ->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month')); +``` + +În mod implicit, returnează un obiect `DateTimeImmutable`. Cu ajutorul metodei `setFormat()`, puteți specifica un [format de text |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] sau un timestamp: + +```php +$form->addDate('date', 'Date:') + ->setFormat('Y-m-d'); +``` + + +addTime(string|int $name, $label=null, bool $withSeconds = false): DateTimeControl .[method]{data-version:3.1.14} +================================================================================================================= + +Adaugă un câmp care permite utilizatorului să introducă cu ușurință ora constând în ore, minute și, opțional, secunde (clasa [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +Pentru valoarea implicită, acceptă fie obiecte care implementează `DateTimeInterface`, fie un șir de caractere cu ora, fie un număr reprezentând un timestamp UNIX. Se utilizează numai informațiile de timp din aceste intrări; data este ignorată. Același lucru este valabil și pentru argumentele de regulă `Min`, `Max` sau `Range`, care definesc timpul minim și maxim admis. Dacă valoarea minimă setată este mai mare decât cea maximă, se creează un interval de timp care se întinde până la miezul nopții. + +```php +$form->addTime('time', 'Time:', withSeconds: true) + ->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']); +``` + +În mod implicit, se returnează un obiect `DateTimeImmutable` (cu o dată fictivă de 1 ianuarie, anul 0). Cu ajutorul metodei `setFormat()`, puteți specifica un [format de text |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: + +```php +$form->addTime('time', 'Time:') + ->setFormat('H:i'); +``` + + +addDateTime(string|int $name, $label=null, bool $withSeconds = false): DateTimeControl .[method]{data-version:3.1.14} +===================================================================================================================== + +Adaugă un câmp care permite utilizatorului să introducă cu ușurință atât data, cât și ora, constând în an, lună, zi, ore, minute și, opțional, secunde (clasa [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +Pentru valoarea implicită, acceptă fie obiecte care implementează `DateTimeInterface`, fie un șir de caractere cu ora, fie un număr reprezentând un timestamp UNIX. Același lucru este valabil și pentru argumentele regulilor `Min`, `Max` sau `Range`, care definesc data minimă și maximă admisă. + +```php +$form->addDateTime('datetime', 'Date and Time:') + ->setDefaultValue(new DateTime) + ->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month')); +``` + +În mod implicit, returnează un obiect `DateTimeImmutable`. Cu ajutorul metodei `setFormat()`, puteți specifica un [format de text |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] sau un timestamp: + +```php +$form->addDateTime('datetime') + ->setFormat(DateTimeControl::FormatTimestamp); +``` + + +addColor(string|int $name, $label=null): ColorPicker .[method]{data-version:3.1.14} +=================================================================================== + +Adaugă un câmp de selecție a culorilor (clasa [ColorPicker |api:Nette\Forms\Controls\ColorPicker]). Culoarea este un șir de caractere în formatul `#rrggbb`. Dacă utilizatorul nu face o selecție, culoarea implicită returnată este negru `#000000`. + +```php +$form->addColor('color', 'Color:') + ->setDefaultValue('#3C8ED7'); +``` + + addHidden(string|int $name, string $default=null): HiddenField .[method] ======================================================================== diff --git a/forms/ru/controls.texy b/forms/ru/controls.texy index b5b1721d51..6c5d18b680 100644 --- a/forms/ru/controls.texy +++ b/forms/ru/controls.texy @@ -20,13 +20,9 @@ $form->addText('name', 'Имя:') Максимальная длина может быть ограничена с помощью `setMaxLength()`. Функция [addFilter()|validation#Modifying-Input-Values] позволяет изменить введенное пользователем значение. -С помощью `setHtmlType()` можно изменить [символ |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] элемента ввода на `search`, `tel`, `url`, `range`, `datetime-local`, `month`, `time`, `week`, `color`. Вместо типов `number` и `email` рекомендуется использовать [addInteger |#addInteger], [addFloat |#addFloat] и [addEmail |#addEmail], которые имеют валидацию на стороне сервера. +Вы можете изменить визуальный характер текстового поля на такие типы, как `search`, `tel`, или `url` с использованием `setHtmlType()`, как показано в [спецификации |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types]. Помните, что изменение типа является только визуальным и не выполняет функции проверки. Для типа `url` целесообразно добавить специальное [правило URL |validation#Text inputs]. -```php -$form->addText('color', 'Выберите цвет:') - ->setHtmlType('color') - ->addRule($form::Pattern, 'недопустимое значение', '[0-9a-f]{6}'); -``` +Для других типов ввода, таких как `number`, `range`, `email`, `date`, `datetime-local`, `time` и `color`, используйте специализированные методы [addInteger |#addInteger], [addFloat |#addFloat], [addEmail |#addEmail] [addDate |#addDate], [addTime |#addTime], [addDateTime |#addDateTime] и [addColor |#addColor], которые обеспечивают валидацию на стороне сервера. Типы `month` и `week` пока не полностью поддерживаются во всех браузерах. Для элемента может быть установлено так называемое «пустое значение», которое является чем-то вроде значения по умолчанию, но если пользователь не перезаписывает его, возвращает пустую строку или `null`. @@ -259,6 +255,79 @@ $form->addMultiUpload('files', 'Файлы:') Правила `MimeType` и `Image` определяют необходимый тип файла или изображения по его сигнатуре. Целостность всего файла не проверяется. Вы можете узнать, не повреждено ли изображение, например, попытавшись [загрузить его|http:request#toImage]. +addDate(string|int $name, $label=null): DateTimeControl .[method]{data-version:3.1.14} +====================================================================================== + +Добавляет поле, позволяющее пользователю легко вводить дату, состоящую из года, месяца и дня (класс [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +В качестве значения по умолчанию он принимает либо объекты, реализующие `DateTimeInterface`, либо строку с временем, либо число, представляющее временную метку UNIX. То же самое относится и к аргументам правил `Min`, `Max` или `Range`, которые определяют минимально и максимально допустимую дату. + +```php +$form->addDate('date', 'Date:') + ->setDefaultValue(new DateTime) + ->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month')); +``` + +По умолчанию возвращается объект `DateTimeImmutable`. С помощью метода `setFormat()` можно задать [текстовый формат |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] или временную метку: + +```php +$form->addDate('date', 'Date:') + ->setFormat('Y-m-d'); +``` + + +addTime(string|int $name, $label=null, bool $withSeconds = false): DateTimeControl .[method]{data-version:3.1.14} +================================================================================================================= + +Добавляет поле, позволяющее пользователю легко вводить время, состоящее из часов, минут и, по желанию, секунд (класс [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +В качестве значения по умолчанию оно принимает либо объекты, реализующие `DateTimeInterface`, либо строку с временем, либо число, представляющее временную метку UNIX. Используется только информация о времени из этих входов, дата игнорируется. То же самое относится и к аргументам правил `Min`, `Max` или `Range`, которые определяют минимальное и максимальное допустимое время. Если минимальное значение больше максимального, то создается временной диапазон, охватывающий полночь. + +```php +$form->addTime('time', 'Time:', withSeconds: true) + ->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']); +``` + +По умолчанию возвращается объект `DateTimeImmutable` (с фиктивной датой 1 января 0-го года). Используя метод `setFormat()`, можно задать [текстовый формат |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: + +```php +$form->addTime('time', 'Time:') + ->setFormat('H:i'); +``` + + +addDateTime(string|int $name, $label=null, bool $withSeconds = false): DateTimeControl .[method]{data-version:3.1.14} +===================================================================================================================== + +Добавляет поле, позволяющее пользователю легко вводить дату и время, состоящие из года, месяца, дня, часов, минут и, по желанию, секунд (класс [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +В качестве значения по умолчанию он принимает либо объекты, реализующие `DateTimeInterface`, либо строку с временем, либо число, представляющее временную метку UNIX. То же самое относится и к аргументам правил `Min`, `Max` или `Range`, которые определяют минимально и максимально допустимую дату. + +```php +$form->addDateTime('datetime', 'Date and Time:') + ->setDefaultValue(new DateTime) + ->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month')); +``` + +По умолчанию возвращается объект `DateTimeImmutable`. С помощью метода `setFormat()` можно задать [текстовый формат |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] или временную метку: + +```php +$form->addDateTime('datetime') + ->setFormat(DateTimeControl::FormatTimestamp); +``` + + +addColor(string|int $name, $label=null): ColorPicker .[method]{data-version:3.1.14} +=================================================================================== + +Добавляет поле выбора цвета (класс [ColorPicker |api:Nette\Forms\Controls\ColorPicker]). Цвет представляет собой строку в формате `#rrggbb`. Если пользователь не делает выбора, то по умолчанию возвращается черный цвет `#000000`. + +```php +$form->addColor('color', 'Color:') + ->setDefaultValue('#3C8ED7'); +``` + + addHidden(string|int $name, string $default=null): HiddenField .[method] ======================================================================== diff --git a/forms/sl/controls.texy b/forms/sl/controls.texy index dbc503a563..18e5bd6a36 100644 --- a/forms/sl/controls.texy +++ b/forms/sl/controls.texy @@ -20,13 +20,9 @@ Samodejno potrdi UTF-8, obreže leve in desne bele prostore ter odstrani prelome Največjo dolžino lahko omejite z uporabo `setMaxLength()`. S funkcijo [addFilter() |validation#Modifying Input Values] lahko spremenite uporabniško vneseno vrednost. -Z uporabo `setHtmlType()` lahko spremenite [znak |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] vhodnega elementa v `search`, `tel`, `url`, `range`, `datetime-local`, `month`, `time`, `week`, `color`. Namesto tipov `number` in `email` priporočamo uporabo tipov [addInteger |#addInteger], [addFloat |#addFloat] in [addEmail |#addEmail], ki imajo preverjanje na strani strežnika. +Vizualni značaj besedilnega polja lahko spremenite v vrste, kot so `search`, `tel` ali `url` z uporabo `setHtmlType()`, kot je prikazano v [specifikaciji |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types]. Ne pozabite, da je spreminjanje tipa le vizualno in ne opravlja funkcij potrjevanja. Za vrsto `url` je primerno dodati posebno [pravilo URL |validation#Text inputs]. -```php -$form->addText('color', 'Choose color:') - ->setHtmlType('color') - ->addRule($form::Pattern, 'invalid value', '[0-9a-f]{6}'); -``` +Za druge vhodne tipe, kot so `number`, `range`, `email`, `date`, `datetime-local`, `time` in `color`, uporabite specializirane metode, kot so [addInteger |#addInteger], [addFloat |#addFloat], [addEmail |#addEmail] [addDate |#addDate], [addTime |#addTime], [addDateTime |#addDateTime] in [addColor |#addColor], ki zagotavljajo preverjanje na strani strežnika. Tipa `month` in `week` še nista v celoti podprta v vseh brskalnikih. Za element lahko nastavite tako imenovano prazno vrednost, ki je nekaj podobnega kot privzeta vrednost, vendar če je uporabnik ne prepiše, vrne prazen niz ali `null`. @@ -259,6 +255,79 @@ Ne zaupajte izvirnim imenom datotek, ki jih vrne metoda `FileUpload::getName()`, Pravili `MimeType` in `Image` zahtevano vrsto datoteke ali slike odkrijeta na podlagi njenega podpisa. Celovitost celotne datoteke se ne preverja. Ali slika ni poškodovana, lahko ugotovite na primer tako, da [jo |http:request#toImage] poskusite [naložiti |http:request#toImage]. +addDate(string|int $name, $label=null): DateTimeControl .[method]{data-version:3.1.14} +====================================================================================== + +Doda polje, ki uporabniku omogoča enostaven vnos datuma, sestavljenega iz leta, meseca in dneva (razred [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +Za privzeto vrednost sprejema predmete, ki implementirajo `DateTimeInterface`, niz s časom ali število, ki predstavlja časovni žig UNIX. Enako velja za argumente pravila `Min`, `Max` ali `Range`, ki določajo najmanjši in največji dovoljeni datum. + +```php +$form->addDate('date', 'Date:') + ->setDefaultValue(new DateTime) + ->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month')); +``` + +Privzeto vrne predmet `DateTimeImmutable`. Z metodo `setFormat()` lahko določite [besedilno obliko |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] ali časovni žig: + +```php +$form->addDate('date', 'Date:') + ->setFormat('Y-m-d'); +``` + + +addTime(string|int $name, $label=null, bool $withSeconds = false): DateTimeControl .[method]{data-version:3.1.14} +================================================================================================================= + +Doda polje, ki uporabniku omogoča enostaven vnos časa, sestavljenega iz ur, minut in po želji sekund (razred [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +Za privzeto vrednost sprejema predmete, ki implementirajo `DateTimeInterface`, niz s časom ali število, ki predstavlja časovni žig UNIX. Uporabijo se samo podatki o času iz teh vnosov; datum se ne upošteva. Enako velja za argumente pravil `Min`, `Max` ali `Range`, ki določajo najmanjši in največji dovoljeni čas. Če je najmanjša nastavljena vrednost višja od največje, se ustvari časovno območje, ki zajema polnoč. + +```php +$form->addTime('time', 'Time:', withSeconds: true) + ->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']); +``` + +Privzeto vrne predmet `DateTimeImmutable` (s fiktivnim datumom 1. januar, leto 0). Z metodo `setFormat()` lahko določite [besedilno obliko |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: + +```php +$form->addTime('time', 'Time:') + ->setFormat('H:i'); +``` + + +addDateTime(string|int $name, $label=null, bool $withSeconds = false): DateTimeControl .[method]{data-version:3.1.14} +===================================================================================================================== + +Doda polje, ki uporabniku omogoča enostaven vnos datuma in časa, sestavljenega iz leta, meseca, dneva, ur, minut in po želji sekund (razred [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +Za privzeto vrednost sprejema predmete, ki implementirajo `DateTimeInterface`, niz s časom ali število, ki predstavlja časovni žig UNIX. Enako velja za argumente pravila `Min`, `Max` ali `Range`, ki določajo najmanjši in največji dovoljeni datum. + +```php +$form->addDateTime('datetime', 'Date and Time:') + ->setDefaultValue(new DateTime) + ->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month')); +``` + +Privzeto vrne predmet `DateTimeImmutable`. Z metodo `setFormat()` lahko določite [besedilno obliko |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] ali časovni žig: + +```php +$form->addDateTime('datetime') + ->setFormat(DateTimeControl::FormatTimestamp); +``` + + +addColor(string|int $name, $label=null): ColorPicker .[method]{data-version:3.1.14} +=================================================================================== + +Doda polje za izbiro barve (razred [ColorPicker |api:Nette\Forms\Controls\ColorPicker]). Barva je niz v obliki `#rrggbb`. Če uporabnik ne opravi izbire, je privzeta vrnjena barva črna `#000000`. + +```php +$form->addColor('color', 'Color:') + ->setDefaultValue('#3C8ED7'); +``` + + addHidden(string|int $name, string $default=null): HiddenField .[method] ======================================================================== diff --git a/forms/tr/controls.texy b/forms/tr/controls.texy index c2a5215541..d67456cd32 100644 --- a/forms/tr/controls.texy +++ b/forms/tr/controls.texy @@ -20,13 +20,9 @@ UTF-8'i otomatik olarak doğrular, sol ve sağ boşlukları keser ve bir saldır Maksimum uzunluk `setMaxLength()` kullanılarak sınırlandırılabilir. [addFilter() |validation#Modifying Input Values] kullanıcı tarafından girilen değeri değiştirmenize olanak tanır. -Giriş öğesinin [karakterini |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] `search`, `tel`, `url`, `range`, `datetime-local`, `month`, `time`, `week`, `color` olarak değiştirmek için `setHtmlType()` kullanabilirsiniz. `number` ve `email` türleri yerine, sunucu tarafı doğrulaması olan [addInteger |#addInteger], [addFloat |#addFloat] ve [addEmail |#addEmail]'i kullanmanızı öneririz. +Bir metin alanının görsel karakterini, [spesifikasyonda |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] görüldüğü gibi `setHtmlType()` kullanarak `search`, `tel` veya `url` gibi türlere değiştirebilirsiniz. Türü değiştirmenin yalnızca görsel olduğunu ve doğrulama işlevlerini yerine getirmediğini unutmayın. `url` türü için belirli bir [URL kuralı |validation#Text inputs] eklemek uygundur. -```php -$form->addText('color', 'Choose color:') - ->setHtmlType('color') - ->addRule($form::Pattern, 'invalid value', '[0-9a-f]{6}'); -``` + `number`, `range`, `email`, `date`, `datetime-local`, `time` ve `color` gibi diğer girdi türleri için sunucu tarafı doğrulama sağlayan [addInteger |#addInteger], [addFloat |#addFloat], [addEmail |#addEmail] [addDate |#addDate], [addTime |#addTime], [addDateTime |#addDateTime] ve [addColor |#addColor] gibi özel yöntemleri kullanın. `month` ve `week` türleri henüz tüm tarayıcılarda tam olarak desteklenmemektedir. Varsayılan değer gibi bir şey olan boş değer öğe için ayarlanabilir, ancak kullanıcı bunun üzerine yazmazsa boş dize veya `null` döndürür. @@ -259,6 +255,79 @@ Dosyalardan biri doğru şekilde yüklenemezse, form başarıyla gönderilmemiş Kurallar `MimeType` ve `Image` gerekli dosya veya görüntü türünü imzasına göre tespit eder. Tüm dosyanın bütünlüğü kontrol edilmez. Bir görüntünün bozuk olup olmadığını örneğin [yüklemeye |http:request#toImage] çalışarak öğrenebilirsiniz. +addDate(string|int $name, $label=null): DateTimeControl .[method]{data-version:3.1.14} +====================================================================================== + +Kullanıcının yıl, ay ve günden oluşan bir tarihi kolayca girmesini sağlayan bir alan ekler ( [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl] sınıfı). + +Varsayılan değer için, `DateTimeInterface` adresini uygulayan nesneleri, zaman içeren bir dizeyi veya UNIX zaman damgasını temsil eden bir sayıyı kabul eder. Aynı durum, izin verilen minimum ve maksimum tarihi tanımlayan `Min`, `Max` veya `Range` kural bağımsız değişkenleri için de geçerlidir. + +```php +$form->addDate('date', 'Date:') + ->setDefaultValue(new DateTime) + ->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month')); +``` + +Varsayılan olarak, bir `DateTimeImmutable` nesnesi döndürür. `setFormat()` yöntemini kullanarak bir [metin biçimi |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] veya zaman damgası belirtebilirsiniz: + +```php +$form->addDate('date', 'Date:') + ->setFormat('Y-m-d'); +``` + + +addTime(string|int $name, $label=null, bool $withSeconds = false): DateTimeControl .[method]{data-version:3.1.14} +================================================================================================================= + +Kullanıcının saat, dakika ve isteğe bağlı olarak saniyelerden oluşan zamanı kolayca girmesini sağlayan bir alan ekler ( [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl] sınıfı). + +Varsayılan değer için, `DateTimeInterface` adresini uygulayan nesneleri, zaman içeren bir dizeyi veya UNIX zaman damgasını temsil eden bir sayıyı kabul eder. Bu girdilerden yalnızca zaman bilgisi kullanılır; tarih göz ardı edilir. Aynı durum, izin verilen minimum ve maksimum zamanı tanımlayan `Min`, `Max` veya `Range` kural bağımsız değişkenleri için de geçerlidir. Ayarlanan minimum değer maksimum değerden yüksekse, gece yarısını kapsayan bir zaman aralığı oluşturulur. + +```php +$form->addTime('time', 'Time:', withSeconds: true) + ->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']); +``` + +Varsayılan olarak, bir `DateTimeImmutable` nesnesi döndürür (1 Ocak, 0 yılı hayali bir tarihle). `setFormat()` yöntemini kullanarak bir [metin biçimi |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] belirtebilirsiniz: + +```php +$form->addTime('time', 'Time:') + ->setFormat('H:i'); +``` + + +addDateTime(string|int $name, $label=null, bool $withSeconds = false): DateTimeControl .[method]{data-version:3.1.14} +===================================================================================================================== + +Kullanıcının yıl, ay, gün, saat, dakika ve isteğe bağlı olarak saniyeden oluşan tarih ve saati kolayca girmesini sağlayan bir alan ekler ( [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl] sınıfı). + +Varsayılan değer için, `DateTimeInterface` adresini uygulayan nesneleri, zaman içeren bir dizeyi veya UNIX zaman damgasını temsil eden bir sayıyı kabul eder. Aynı durum, izin verilen minimum ve maksimum tarihi tanımlayan `Min`, `Max` veya `Range` kural bağımsız değişkenleri için de geçerlidir. + +```php +$form->addDateTime('datetime', 'Date and Time:') + ->setDefaultValue(new DateTime) + ->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month')); +``` + +Varsayılan olarak, bir `DateTimeImmutable` nesnesi döndürür. `setFormat()` yöntemini kullanarak bir [metin biçimi |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] veya zaman damgası belirtebilirsiniz: + +```php +$form->addDateTime('datetime') + ->setFormat(DateTimeControl::FormatTimestamp); +``` + + +addColor(string|int $name, $label=null): ColorPicker .[method]{data-version:3.1.14} +=================================================================================== + +Bir renk seçim alanı ekler ( [ColorPicker |api:Nette\Forms\Controls\ColorPicker] sınıfı). Renk, `#rrggbb` biçiminde bir dizedir. Kullanıcı bir seçim yapmazsa, döndürülen varsayılan renk siyahtır `#000000`. + +```php +$form->addColor('color', 'Color:') + ->setDefaultValue('#3C8ED7'); +``` + + addHidden(string|int $name, string $default=null): HiddenField .[method] ======================================================================== diff --git a/forms/uk/controls.texy b/forms/uk/controls.texy index c32e802012..3391832a95 100644 --- a/forms/uk/controls.texy +++ b/forms/uk/controls.texy @@ -20,13 +20,9 @@ $form->addText('name', 'Имя:') Максимальна довжина може бути обмежена за допомогою `setMaxLength()`. Функція [addFilter() |validation#Modifying-Input-Values] дозволяє змінити введене користувачем значення. -Ви можете використовувати `setHtmlType()` для зміни [символу |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types] вхідного елемента на `search`, `tel`, `url`, `range`, `datetime-local`, `month`, `time`, `week`, `color`. Замість типів `number` та `email` ми рекомендуємо використовувати [addInteger |#addInteger], [addFloat |#addFloat] та [addEmail |#addEmail], які мають перевірку на стороні сервера. +Ви можете змінити візуальний вигляд текстового поля на типи `search`, `tel` або `url` за допомогою `setHtmlType()`, як показано у [специфікації |https://developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types]. Пам'ятайте, що зміна типу є лише візуальною і не виконує функцій перевірки. Для типу `url` доречно додати спеціальне [правило URL-адреси |validation#Text inputs]. -```php -$form->addText('color', 'Выберите цвет:') - ->setHtmlType('color') - ->addRule($form::Pattern, 'недопустимое значение', '[0-9a-f]{6}'); -``` +Для інших типів вводу, таких як `number`, `range`, `email`, `date`, `datetime-local`, `time` і `color`, використовуйте спеціалізовані методи, такі як [addInteger |#addInteger], [addFloat |#addFloat], [addEmail |#addEmail], [addDate |#addDate], [addTime |#addTime], [addDateTime |#addDateTime] і [addColor |#addColor], які забезпечують валідацію на стороні сервера. Типи `month` та `week` ще не повністю підтримуються всіма браузерами. Для елемента може бути встановлено так зване "порожнє значення", яке є чимось на зразок значення за замовчуванням, але якщо користувач не перезаписує його, повертає порожній рядок або `null`. @@ -259,6 +255,79 @@ $form->addMultiUpload('files', 'Файлы:') Правила `MimeType` і `Image` визначають необхідний тип файлу або зображення за його сигнатурою. Цілісність усього файлу не перевіряється. Ви можете дізнатися, чи не пошкоджено зображення, наприклад, спробувавши [завантажити його |http:request#toImage]. +addDate(string|int $name, $label=null): DateTimeControl .[method]{data-version:3.1.14} +====================================================================================== + +Додає поле, яке дозволяє користувачеві легко ввести дату, що складається з року, місяця і дня (клас [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +За замовчуванням приймаються або об'єкти, що реалізують `DateTimeInterface`, або рядок з часом, або число, що представляє мітку часу UNIX. Те саме стосується аргументів правила `Min`, `Max` або `Range`, які визначають мінімальну та максимальну допустиму дату. + +```php +$form->addDate('date', 'Date:') + ->setDefaultValue(new DateTime) + ->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month')); +``` + +За замовчуванням повертається об'єкт `DateTimeImmutable`. За допомогою методу `setFormat()` ви можете вказати [текстовий формат |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] або мітку часу: + +```php +$form->addDate('date', 'Date:') + ->setFormat('Y-m-d'); +``` + + +addTime(string|int $name, $label=null, bool $withSeconds = false): DateTimeControl .[method]{data-version:3.1.14} +================================================================================================================= + +Додає поле, яке дозволяє користувачеві легко вводити час, що складається з годин, хвилин і необов'язково секунд (клас [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +За замовчуванням приймаються або об'єкти, що реалізують `DateTimeInterface`, або рядок з часом, або число, що представляє часову мітку UNIX. Використовується лише інформація про час з цих входів; дата ігнорується. Те саме стосується аргументів правил `Min`, `Max` або `Range`, які визначають мінімальний і максимальний дозволений час. Якщо мінімальне значення перевищує максимальне, створюється часовий діапазон, що охоплює опівніч. + +```php +$form->addTime('time', 'Time:', withSeconds: true) + ->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']); +``` + +За замовчуванням повертається об'єкт `DateTimeImmutable` (з фіктивною датою 1 січня 0 року). За допомогою методу `setFormat()` ви можете вказати [текстовий формат |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: + +```php +$form->addTime('time', 'Time:') + ->setFormat('H:i'); +``` + + +addDateTime(string|int $name, $label=null, bool $withSeconds = false): DateTimeControl .[method]{data-version:3.1.14} +===================================================================================================================== + +Додає поле, яке дозволяє користувачеві легко вводити як дату, так і час, що складається з року, місяця, дня, годин, хвилин і необов'язково секунд (клас [DateTimeControl |api:Nette\Forms\Controls\DateTimeControl]). + +За замовчуванням приймаються або об'єкти, що реалізують `DateTimeInterface`, або рядок з часом, або число, що представляє часову мітку UNIX. Те саме стосується аргументів правила `Min`, `Max` або `Range`, які визначають мінімальну та максимальну допустиму дату. + +```php +$form->addDateTime('datetime', 'Date and Time:') + ->setDefaultValue(new DateTime) + ->addRule($form::Min, 'The date must be at least a month old.', new DateTime('-1 month')); +``` + +За замовчуванням повертається об'єкт `DateTimeImmutable`. За допомогою методу `setFormat()` ви можете вказати [текстовий формат |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] або мітку часу: + +```php +$form->addDateTime('datetime') + ->setFormat(DateTimeControl::FormatTimestamp); +``` + + +addColor(string|int $name, $label=null): ColorPicker .[method]{data-version:3.1.14} +=================================================================================== + +Додає поле вибору кольору (клас [ColorPicker |api:Nette\Forms\Controls\ColorPicker]). Колір є рядком у форматі `#rrggbb`. Якщо користувач не зробив вибір, за замовчуванням повертається чорний колір `#000000`. + +```php +$form->addColor('color', 'Color:') + ->setDefaultValue('#3C8ED7'); +``` + + addHidden(string|int $name, string $default=null): HiddenField .[method] ======================================================================== From e3a4ac4c141f504f5f4dfe6928b5687747125e08 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sun, 29 Oct 2023 22:23:37 +0100 Subject: [PATCH 032/137] nette/utils 4.0.2 --- utils/bg/images.texy | 146 ++++++++++++++++++++++++------------------- utils/cs/images.texy | 146 ++++++++++++++++++++++++------------------- utils/de/images.texy | 146 ++++++++++++++++++++++++------------------- utils/el/images.texy | 146 ++++++++++++++++++++++++------------------- utils/en/images.texy | 146 ++++++++++++++++++++++++------------------- utils/es/images.texy | 146 ++++++++++++++++++++++++------------------- utils/fr/images.texy | 146 ++++++++++++++++++++++++------------------- utils/hu/images.texy | 146 ++++++++++++++++++++++++------------------- utils/it/images.texy | 146 ++++++++++++++++++++++++------------------- utils/pl/images.texy | 146 ++++++++++++++++++++++++------------------- utils/pt/images.texy | 146 ++++++++++++++++++++++++------------------- utils/ro/images.texy | 146 ++++++++++++++++++++++++------------------- utils/ru/images.texy | 146 ++++++++++++++++++++++++------------------- utils/sl/images.texy | 146 ++++++++++++++++++++++++------------------- utils/tr/images.texy | 146 ++++++++++++++++++++++++------------------- utils/uk/images.texy | 146 ++++++++++++++++++++++++------------------- 16 files changed, 1296 insertions(+), 1040 deletions(-) diff --git a/utils/bg/images.texy b/utils/bg/images.texy index 4f2f25bee9..68435e34bd 100644 --- a/utils/bg/images.texy +++ b/utils/bg/images.texy @@ -17,6 +17,7 @@ composer require nette/utils ```php use Nette\Utils\Image; +use Nette\Utils\ImageColor; use Nette\Utils\ImageType; ``` @@ -33,7 +34,7 @@ $image = Image::fromBlank(100, 200); По желание можете да зададете цвят на фона (по подразбиране е черен): ```php -$image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0)); +$image = Image::fromBlank(100, 200, ImageColor::rgb(125, 0, 0)); ``` Или да качите изображение от файл: @@ -191,16 +192,36 @@ $image->cropAuto(IMG_CROP_BLACK); Методът `cropAuto()` е заместител на обект на функцията `imagecropauto()`, за повече подробности вижте [нейната документация |https://www.php.net/manual/en/function.imagecropauto]. +Цветове .[#toc-colors] +====================== + +Методът `ImageColor::rgb()` ви позволява да дефинирате цвят, като използвате червени, зелени и сини (RGB) стойности. По желание можете да зададете и стойност за прозрачност, варираща от 0 (напълно прозрачен) до 1 (напълно непрозрачен), точно както в CSS. + +```php +$color = ImageColor::rgb(255, 0, 0); // Red +$transparentBlue = ImageColor::rgb(0, 0, 255, 0.5); // Semi-transparent blue +``` + +Методът `ImageColor::hex()` ви позволява да дефинирате цвят, като използвате шестнадесетичен формат, подобно на CSS. Той поддържа форматите `#rgb`, `#rrggbb`, `#rgba` и `#rrggbbaa`: + +```php +$color = ImageColor::hex("#F00"); // Red +$transparentGreen = ImageColor::hex("#00FF0080"); // Semi-transparent green +``` + +Цветовете могат да се използват и в други методи, като например `ellipse()`, `fill()` и т.н. + + Рисуване и редактиране .[#toc-drawing-and-editing] ================================================== -Можете да рисувате, можете да пишете, но не разкъсвайте страниците. Всички функции за изображения на PHP, като например [imagefilledellipse |https://www.php.net/manual/en/function.imagefilledellipse.php], са достъпни за вас, но в обектно-ориентиран вид: +Можете да рисувате, да пишете, да използвате всички функции на PHP за манипулиране на изображения, вижте [Преглед на методите |#Overview of methods], но в обектно-ориентирана обвивка: ```php -$image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63)); +$image->filledEllipse($centerX, $centerY, $width, $height, ImageColor::rgb(255, 0, 0)); ``` -Вижте [Преглед на методите |#Overview-of-Methods]. +Тъй като функциите на PHP за изчертаване на правоъгълници са непрактични поради задаването на координати, класът `Image` предлага техни заместители под формата на функциите [rectangleWH() |#rectangleWH()] и [filledRectangleWH() |#filledRectangleWH()]. Комбиниране на няколко изображения .[#toc-merge-multiple-images] @@ -210,7 +231,7 @@ $image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63)); ```php $logo = Image::fromFile('logo.png'); -$blank = Image::fromBlank(320, 240, Image::rgb(52, 132, 210)); +$blank = Image::fromBlank(320, 240, ImageColor::rgb(52, 132, 210)); // координатите отново могат да бъдат зададени като процент $blank->place($logo, '80%', '80%'); // вмъкване в долния десен ъгъл @@ -229,8 +250,8 @@ $blank->place($image, '80%', '80%', 25); // прозрачността е 25% =============================================== -static fromBlank(int $width, int $height, array $color=null): Image .[method] ------------------------------------------------------------------------------ +static fromBlank(int $width, int $height, ImageColor $color=null): Image .[method] +---------------------------------------------------------------------------------- Създава ново истинско цветно изображение със зададени размери. Цветът по подразбиране е черен. @@ -244,9 +265,9 @@ static fromString(string $s, int &$detectedFormat=null): Image .[method] Чете изображение от низ и връща неговия [тип |#Formats] в `$detectedFormat`. -static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method] ---------------------------------------------------------------------------------- -Създава цвят, който може да се използва в други методи, като например `ellipse()`, `fill()` и т.н. +static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated] +--------------------------------------------------------------------------------------------- +Тази функция е заменена от класа `ImageColor`, вижте [цветовете |#Colors]. static typeToExtension(int $type): string .[method] @@ -279,6 +300,11 @@ static isTypeSupported(int $type): bool .[method] Определя дали даденият [тип |#Formats] изображение се поддържа. +static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method] +------------------------------------------------------------------------------------------------------------------------ +Изчислява размерите на правоъгълника, който огражда текст с определен шрифт и размер. Връща асоциативен масив, съдържащ ключовете `left`, `top`, `width`, `height`. Лявото поле може да бъде отрицателно, ако текстът започва с ляв надвес. + + affine(array $affine, array $clip=null): Image .[method] -------------------------------------------------------- Връща изображение, съдържащо афинно-трансформирано src изображение, като се използва опционална област на изрязване. ([повече информация |https://www.php.net/manual/en/function.imageaffine]). @@ -306,21 +332,11 @@ antialias(bool $on): void .[method] Използването на изгладения примитив с прозрачен цвят на фона може да доведе до неочаквани резултати. Методът на смесване използва цвета на фона като всеки друг цвят. ([повече подробности |https://www.php.net/manual/en/function.imageantialias]) -arc(int $x, int $y, int $w, int $h, int $start, int $end, int $color): void .[method] -------------------------------------------------------------------------------------- +arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color): void .[method] +--------------------------------------------------------------------------------------------------------------------------- Изчертава дъга от окръжност с център в зададените координати. ([повече подробности |https://www.php.net/manual/en/function.imagearc]) -char(int $font, int $x, int $y, string $char, int $color): void .[method] -------------------------------------------------------------------------- -Изчертава първия символ `$char` в изображението с горен ляв ъгъл `$x`, `$y` (горният ляв ъгъл е равен на 0, 0), цвят `$color`. ([повече подробности |https://www.php.net/manual/en/function.imagechar]) - - -charUp(int $font, int $x, int $y, string $char, int $color): void .[method] ---------------------------------------------------------------------------- -Изчертава символа `$char` вертикално в посочената координата в посоченото изображение. ([повече подробности |https://www.php.net/manual/en/function.imagecharup]) - - colorAllocate(int $red, int $green, int $blue): int .[method] ------------------------------------------------------------- Връща идентификатор на цвят, представляващ цвят, съставен от дадените компоненти RGB. Трябва да се извика, за да се създаде всеки цвят, който ще се използва в изображението. ([повече подробности |https://www.php.net/manual/en/function.imagecolorallocate]) @@ -447,43 +463,48 @@ crop(int|string $left, int|string $top, int|string $width, int|string $height): Изрязване на изображението до определена правоъгълна област. Размерът може да бъде зададен като цяло число в пиксели или като низ в проценти (напр. `'50%'`). -cropAuto(int $mode=-1, float $threshold=.5, int $color=-1): Image .[method] ---------------------------------------------------------------------------- +cropAuto(int $mode=-1, float $threshold=.5, ?ImageColor $color=null): Image .[method] +------------------------------------------------------------------------------------- Автоматично изрязване на изображението в съответствие със зададеното `$mode`. ([прочети повече) |https://www.php.net/manual/en/function.imagecropauto] -ellipse(int $cx, int $cy, int $w, int $h, int $color): void .[method] ---------------------------------------------------------------------- +ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method] +----------------------------------------------------------------------------------------------- Изчертава елипса с център в зададените координати. ([повече подробности |https://www.php.net/manual/en/function.imageellipse]) -fill(int $x, int $y, int $color): void .[method] ------------------------------------------------- +fill(int $x, int $y, ImageColor $color): void .[method] +------------------------------------------------------- Запълва областта, започваща от зададената координата (горе вляво 0, 0), със зададеното `$color`. ([повече подробности |https://www.php.net/manual/en/function.imagefill]) -filledArc(int $cx, int $cy, int $w, int $h, int $s, int $e, int $color, int $style): void .[method] ---------------------------------------------------------------------------------------------------- +filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style): void .[method] +--------------------------------------------------------------------------------------------------------------------------------------------- Изчертава непълна дъга с център в зададените координати. ([повече подробности |https://www.php.net/manual/en/function.imagefilledarc]) -filledEllipse(int $cx, int $cy, int $w, int $h, int $color): void .[method] ---------------------------------------------------------------------------- +filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method] +----------------------------------------------------------------------------------------------------- Изчертава елипса с център в зададените координати. ([повече подробности |https://www.php.net/manual/en/function.imagefilledellipse]) -filledPolygon(array $points, int $numPoints, int $color): void .[method] ------------------------------------------------------------------------- +filledPolygon(array $points, ImageColor $color): void .[method] +--------------------------------------------------------------- Създава запълнен многоъгълник върху изображението. ([повече подробности |https://www.php.net/manual/en/function.imagefilledpolygon]) -filledRectangle(int $x1, int $y1, int $x2, int $y2, int $color): void .[method] -------------------------------------------------------------------------------- -Създава правоъгълник, запълнен с `$color` в изображението, като започва от точка 1 и завършва в точка 2. Точка 0, 0 е горният ляв ъгъл на изображението. ([повече подробности |https://www.php.net/manual/en/function.imagefilledrectangle]) +filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------- +Създава правоъгълник, запълнен с `$color` в изображението, започващ от `$x1` & `$y1` и завършващ на `$x2` & `$y2`. Точка 0, 0 е горният ляв ъгъл на изображението. ([още) |https://www.php.net/manual/en/function.imagefilledrectangle] -fillToBorder(int $x, int $y, int $border, int $color): void .[method] ---------------------------------------------------------------------- +filledRectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------------------- +Създава правоъгълник, запълнен с `$color` в изображението, започващ от точките `$left` и `$top`, с ширина `$width` и височина `$height`. Точка 0, 0 е горният ляв ъгъл на изображението. + + +fillToBorder(int $x, int $y, int $border, ImageColor $color): void .[method] +---------------------------------------------------------------------------- Създава запълване, чийто цвят на границата се определя от `$border`. Началната точка на запълването е `$x`, `$y` (горният ляв ъгъл - 0, 0), а областта се запълва с цвета `$color`. ([повече подробности |https://www.php.net/manual/en/function.imagefilltoborder]) @@ -497,9 +518,9 @@ flip(int $mode): void .[method] Инвертира изображението на посочения адрес `$mode`. ([прочети повече) |https://www.php.net/manual/en/function.imageflip] -ftText(int $size, int $angle, int $x, int $y, int $col, string $fontFile, string $text, array $extrainfo=null): array .[method] -------------------------------------------------------------------------------------------------------------------------------- -Напишете текст върху изображението, като използвате шрифтове FreeType 2. ([още) |https://www.php.net/manual/en/function.imagefttext] +ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method] +---------------------------------------------------------------------------------------------------------------------------------------- +Напишете текста на картинката. ([повече) |https://www.php.net/manual/en/function.imagefttext] gammaCorrect(float $inputgamma, float $outputgamma): void .[method] @@ -542,13 +563,13 @@ layerEffect(int $effect): void .[method] Задайте флага за алфа смесване, за да използвате ефекти на наслояване. ([повече подробности |https://www.php.net/manual/en/function.imagelayereffect]) -line(int $x1, int $y1, int $x2, int $y2, int $color): void .[method] --------------------------------------------------------------------- +line(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +--------------------------------------------------------------------------- Начертава линия между две дадени точки. ([повече подробности |https://www.php.net/manual/en/function.imageline]) -openPolygon(array $points, int $numPoints, int $color): void .[method] ----------------------------------------------------------------------- +openPolygon(array $points, ImageColor $color): void .[method] +------------------------------------------------------------- Начертава отворен многоъгълник в изображението. За разлика от `polygon()`, между последната и първата точка не се прокарва линия. ([повече подробности |https://www.php.net/manual/en/function.imageopenpolygon]) @@ -567,16 +588,21 @@ place(Image $image, int|string $left=0, int|string $top=0, int $opacity=100): Im Копира `$image` в изображението с координати `$left` и `$top`. Координатите могат да бъдат зададени като цели числа в пиксели или като низове в проценти (напр. `'50%'`). -polygon(array $points, int $numPoints, int $color): void .[method] ------------------------------------------------------------------- +polygon(array $points, ImageColor $color): void .[method] +--------------------------------------------------------- Създава многоъгълник в изображението. ([повече подробности |https://www.php.net/manual/en/function.imagepolygon]) -rectangle(int $x1, int $y1, int $x2, int $y2, int $col): void .[method] ------------------------------------------------------------------------ +rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +-------------------------------------------------------------------------------- Създава правоъгълник със зададени координати. ([повече подробности |https://www.php.net/manual/en/function.imagerectangle]) +rectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------------- +Създава правоъгълник със зададените координати. + + resize(int|string $width, int|string $height, int $flags=Image::OrSmaller): Image .[method] ------------------------------------------------------------------------------------------- Промяна на размера на изображението, [допълнителна информация |#Image-Resize]. Размерите могат да бъдат зададени като цели числа в пиксели или като низове в проценти (напр. `'50%'`). @@ -638,8 +664,8 @@ setInterpolation(int $method=IMG_BILINEAR_FIXED): void .[method] Задава метода на интерполация, който влияе на методите `rotate()` и `affine()`. ([повече подробности |https://www.php.net/manual/en/function.imagesetinterpolation]) -setPixel(int $x, int $y, int $color): void .[method] ----------------------------------------------------- +setPixel(int $x, int $y, ImageColor $color): void .[method] +----------------------------------------------------------- Изчертава пиксел в зададена координата. ([повече подробности |https://www.php.net/manual/en/function.imagesetpixel]) @@ -668,16 +694,6 @@ sharpen(): Image .[method] Изисква *Пълен GD разширение*, така че може да не работи навсякъде. -string(int $font, int $x, int $y, string $str, int $col): void .[method] ------------------------------------------------------------------------- -Извежда низ в зададените координати. ([повече подробности |https://www.php.net/manual/en/function.imagestring]) - - -stringUp(int $font, int $x, int $y, string $s, int $col): void .[method] ------------------------------------------------------------------------- -Извежда низ по вертикала в зададените координати. ([повече подробности |https://www.php.net/manual/en/function.imagestringup]) - - toString(int $type=ImageType::JPEG, int $quality=null): string .[method] ------------------------------------------------------------------------ Записва изображението в низ. @@ -690,6 +706,6 @@ trueColorToPalette(bool $dither, int $ncolors): void .[method] Преобразува истинско цветно изображение в палитра. ([прочети повече) |https://www.php.net/manual/en/function.imagetruecolortopalette] -ttfText(int $size, int $angle, int $x, int $y, int $color, string $fontfile, string $text): array .[method] ------------------------------------------------------------------------------------------------------------ -Отпечатва зададен текст в изображение, като използва шрифтове TrueType. ([повече подробности |https://www.php.net/manual/en/function.imagettftext]) +ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method] +----------------------------------------------------------------------------------------------------------------------------------------- +Записва дадения текст в изображението. ([още) |https://www.php.net/manual/en/function.imagettftext] diff --git a/utils/cs/images.texy b/utils/cs/images.texy index 6c55e1df60..1ae07eb9b7 100644 --- a/utils/cs/images.texy +++ b/utils/cs/images.texy @@ -17,6 +17,7 @@ Všechny příklady předpokládají vytvořený alias: ```php use Nette\Utils\Image; +use Nette\Utils\ImageColor; use Nette\Utils\ImageType; ``` @@ -33,7 +34,7 @@ $image = Image::fromBlank(100, 200); Volitelně lze určit barvu pozadí (výchozí je černá): ```php -$image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0)); +$image = Image::fromBlank(100, 200, ImageColor::rgb(125, 0, 0)); ``` Nebo obrázek načteme ze souboru: @@ -191,16 +192,36 @@ $image->cropAuto(IMG_CROP_BLACK); Metoda `cropAuto()` je objektovou náhradou funkce `imagecropauto()`, v [její dokumentaci|https://www.php.net/manual/en/function.imagecropauto] najdete další informace. +Barvy .{data-version:4.0.2} +=========================== + +Metoda `ImageColor::rgb()` vám umožňuje definovat barvu pomocí hodnot červené, zelené a modré (RGB). Volitelně můžete také specifikovat hodnotu průhlednosti v rozmezí 0 (naprosto průhledné) až 1 (zcela neprůhledné), tedy stejně jako v CSS. + +```php +$color = ImageColor::rgb(255, 0, 0); // Červená +$transparentBlue = ImageColor::rgb(0, 0, 255, 0.5); // Poloprůhledná modrá +``` + +Metoda `ImageColor::hex()` umožňuje definovat barvu pomocí hexadecimálního formátu, podobně jako v CSS. Podporuje formáty `#rgb`, `#rrggbb`, `#rgba` a `#rrggbbaa`: + +```php +$color = ImageColor::hex("#F00"); // Červená +$transparentGreen = ImageColor::hex("#00FF0080"); // Poloprůhledná zelená +``` + +Barvy lze použít v dalších metodách, jako třeba `ellipse()`, `fill()` atd. + + Kreslení a úpravy ================= -Můžeš kreslit, můžeš psát, ale listy netrhat. Jsou vám k dispozici všechny funkce PHP pro práci s obrázky, jako například [imagefilledellipse|https://www.php.net/manual/en/function.imagefilledellipse.php], ale v objektovém hávu: +Můžeš kreslit, můžeš psát, ale listy netrhat. Jsou vám k dispozici všechny funkce PHP pro práci s obrázky, viz [#Přehled metod], ale v objektovém hávu: ```php -$image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63)); +$image->filledEllipse($centerX, $centerY, $width, $height, ImageColor::rgb(255, 0, 0)); ``` -Viz [#Přehled metod]. +Protože PHP funkce pro kreslení obdelníků jsou nepraktické kvůli určení souřadnic, nabízí třída `Image` jejich náhrady v podobě funkcí [#rectangleWH()] a [#filledRectangleWH()]. Spojení více obrázků @@ -210,7 +231,7 @@ Do obrázku lze snadno vložit jiný obrázek: ```php $logo = Image::fromFile('logo.png'); -$blank = Image::fromBlank(320, 240, Image::rgb(52, 132, 210)); +$blank = Image::fromBlank(320, 240, ImageColor::rgb(52, 132, 210)); // souřadnice lze uvést opět v procentech $blank->place($logo, '80%', '80%'); // vložíme poblíž pravého dolního rohu @@ -229,8 +250,8 @@ Přehled metod ============= -static fromBlank(int $width, int $height, array $color=null): Image .[method] ------------------------------------------------------------------------------ +static fromBlank(int $width, int $height, ImageColor $color=null): Image .[method] +---------------------------------------------------------------------------------- Vytvoří nový true color obrázek daných rozměrů. Výchozí barva je černá. @@ -244,9 +265,9 @@ static fromString(string $s, int &$detectedFormat=null): Image .[method] Načte obrázek z řetezce a vrací jeho [typ|#Formáty] v `$detectedFormat`. -static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method] ---------------------------------------------------------------------------------- -Vytvoří barvu, kterou lze použít v dalších metodách, jako třeba `ellipse()`, `fill()` atd. +static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated] +--------------------------------------------------------------------------------------------- +Tuto funkci nahradila třída `ImageColor`, viz [barvy|#Barvy]. static typeToExtension(int $type): string .[method] @@ -279,6 +300,11 @@ static isTypeSupported(int $type): bool .[method] Zjišťuje, zda je podporovaný daný [typ|#Formáty] obrázku. +static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method] +------------------------------------------------------------------------------------------------------------------------ +Spočítá rozměry obdélníku, který obepne text v určitém písmu a velikosti. Vrací asociativní pole obsahující klíče `left`, `top`, `width`, `height`. Levý okraj může být i záporný, pokud text začíná levým podřezáváním. + + affine(array $affine, array $clip=null): Image .[method] -------------------------------------------------------- Vraťte obrázek obsahující afinně transformovaný obraz src pomocí volitelné oblasti oříznutí. ([více |https://www.php.net/manual/en/function.imageaffine]). @@ -306,21 +332,11 @@ Aktivujte kreslení vyhlazených čar a polygonů. Nepodporuje alfa kanály. Fun Použití antialiased primitiv s průhlednou barvou pozadí může skončit s některými neočekávanými výsledky. Metoda prolnutí používá barvu pozadí jako všechny ostatní barvy. ([více |https://www.php.net/manual/en/function.imageantialias]) -arc(int $x, int $y, int $w, int $h, int $start, int $end, int $color): void .[method] -------------------------------------------------------------------------------------- +arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color): void .[method] +--------------------------------------------------------------------------------------------------------------------------- Nakreslí oblouk kruhu se středem v daných souřadnicích. ([více |https://www.php.net/manual/en/function.imagearc]) -char(int $font, int $x, int $y, string $char, int $color): void .[method] -------------------------------------------------------------------------- -Nakreslí první znak `$char` do obrázku s jeho levým horním rohem na `$x`, `$y` (vlevo nahoře je 0, 0) s barvou `$color`. ([více |https://www.php.net/manual/en/function.imagechar]) - - -charUp(int $font, int $x, int $y, string $char, int $color): void .[method] ---------------------------------------------------------------------------- -Nakreslí znak `$char` svisle na určenou souřadnici na daném obrázku. ([více |https://www.php.net/manual/en/function.imagecharup]) - - colorAllocate(int $red, int $green, int $blue): int .[method] ------------------------------------------------------------- Vrací identifikátor barvy představující barvu složenou z daných komponent RGB. Musí být volána pro vytvoření každé barvy, která má být použita v obrázku. ([více |https://www.php.net/manual/en/function.imagecolorallocate]) @@ -447,43 +463,48 @@ crop(int|string $left, int|string $top, int|string $width, int|string $height): Ořízne obrázek do dané obdélníkové oblasti. Rozměry je možné zadávat jako integery v pixelech nebo řetězce v procentech (například `'50%'`). -cropAuto(int $mode=-1, float $threshold=.5, int $color=-1): Image .[method] ---------------------------------------------------------------------------- +cropAuto(int $mode=-1, float $threshold=.5, ?ImageColor $color=null): Image .[method] +------------------------------------------------------------------------------------- Automaticky ořízne obrázek podle daného `$mode`. ([více |https://www.php.net/manual/en/function.imagecropauto]) -ellipse(int $cx, int $cy, int $w, int $h, int $color): void .[method] ---------------------------------------------------------------------- +ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method] +----------------------------------------------------------------------------------------------- Nakreslí elipsu se středem na zadaných souřadnicích. ([více |https://www.php.net/manual/en/function.imageellipse]) -fill(int $x, int $y, int $color): void .[method] ------------------------------------------------- +fill(int $x, int $y, ImageColor $color): void .[method] +------------------------------------------------------- Výplní oblast počínaje danou souřadnicí (vlevo nahoře je 0, 0) s daným `$color`. ([více |https://www.php.net/manual/en/function.imagefill]) -filledArc(int $cx, int $cy, int $w, int $h, int $s, int $e, int $color, int $style): void .[method] ---------------------------------------------------------------------------------------------------- +filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style): void .[method] +--------------------------------------------------------------------------------------------------------------------------------------------- Nakreslí částečný oblouk se středem na zadaných souřadnicích. ([více |https://www.php.net/manual/en/function.imagefilledarc]) -filledEllipse(int $cx, int $cy, int $w, int $h, int $color): void .[method] ---------------------------------------------------------------------------- +filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method] +----------------------------------------------------------------------------------------------------- Nakreslí elipsu se středem na zadaných souřadnicích. ([více |https://www.php.net/manual/en/function.imagefilledellipse]) -filledPolygon(array $points, int $numPoints, int $color): void .[method] ------------------------------------------------------------------------- +filledPolygon(array $points, ImageColor $color): void .[method] +--------------------------------------------------------------- Vytvoří v obraze vyplněný mnohoúhelník. ([více |https://www.php.net/manual/en/function.imagefilledpolygon]) -filledRectangle(int $x1, int $y1, int $x2, int $y2, int $color): void .[method] -------------------------------------------------------------------------------- -Vytvoří obdélník vyplněný `$color` v obrázku počínaje bodem 1 a končící bodem 2. Bod 0, 0 je levý horní roh obrázku. ([více |https://www.php.net/manual/en/function.imagefilledrectangle]) +filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------- +Vytvoří obdélník vyplněný `$color` v obrázku počínaje bodem `$x1` & `$y1` a končící bodem `$x2` & `$y2`. Bod 0, 0 je levý horní roh obrázku. ([více |https://www.php.net/manual/en/function.imagefilledrectangle]) -fillToBorder(int $x, int $y, int $border, int $color): void .[method] ---------------------------------------------------------------------- +filledRectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------------------- +Vytvoří obdélník vyplněný `$color` v obrázku počínaje bodem `$left` & `$top` o šířce `$width` a výšce `$height`. Bod 0, 0 je levý horní roh obrázku. + + +fillToBorder(int $x, int $y, int $border, ImageColor $color): void .[method] +---------------------------------------------------------------------------- Vykreslí výplň, jejíž barva okraje je definována pomocí `$border`. Výchozím bodem výplně je `$x`, `$y` (vlevo nahoře je 0, 0) a oblast je vyplněna barvou `$color`. ([více |https://www.php.net/manual/en/function.imagefilltoborder]) @@ -497,9 +518,9 @@ flip(int $mode): void .[method] Převrátí obrázek pomocí daného `$mode`. ([více |https://www.php.net/manual/en/function.imageflip]) -ftText(int $size, int $angle, int $x, int $y, int $col, string $fontFile, string $text, array $extrainfo=null): array .[method] -------------------------------------------------------------------------------------------------------------------------------- -Napište text do obrázku pomocí písem pomocí FreeType 2. ([více |https://www.php.net/manual/en/function.imagefttext]) +ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method] +---------------------------------------------------------------------------------------------------------------------------------------- +Napište text do obrázku. ([více |https://www.php.net/manual/en/function.imagefttext]) gammaCorrect(float $inputgamma, float $outputgamma): void .[method] @@ -542,13 +563,13 @@ layerEffect(int $effect): void .[method] Nastavte příznak prolnutí alfa tak, aby používal efekty vrstvení. ([více |https://www.php.net/manual/en/function.imagelayereffect]) -line(int $x1, int $y1, int $x2, int $y2, int $color): void .[method] --------------------------------------------------------------------- +line(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +--------------------------------------------------------------------------- Nakreslí čáru mezi dvěma danými body. ([více |https://www.php.net/manual/en/function.imageline]) -openPolygon(array $points, int $numPoints, int $color): void .[method] ----------------------------------------------------------------------- +openPolygon(array $points, ImageColor $color): void .[method] +------------------------------------------------------------- Nakreslí na obrázek otevřený mnohoúhelník. Na rozdíl od `polygon()` není mezi posledním a prvním bodem nakreslena žádná čára. ([více |https://www.php.net/manual/en/function.imageopenpolygon]) @@ -567,16 +588,21 @@ place(Image $image, int|string $left=0, int|string $top=0, int $opacity=100): Im Zkopíruje `$image` do obrázku na souřadnice `$left` a `$top`. Souřadnice je možné zadávat jako integery v pixelech nebo řetězce v procentech (například `'50%'`). -polygon(array $points, int $numPoints, int $color): void .[method] ------------------------------------------------------------------- +polygon(array $points, ImageColor $color): void .[method] +--------------------------------------------------------- Vytvoří v obrazu mnohoúhelník. ([více |https://www.php.net/manual/en/function.imagepolygon]) -rectangle(int $x1, int $y1, int $x2, int $y2, int $col): void .[method] ------------------------------------------------------------------------ +rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +-------------------------------------------------------------------------------- Vytvoří obdélník na zadaných souřadnicích. ([více |https://www.php.net/manual/en/function.imagerectangle]) +rectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------------- +Vytvoří obdélník na zadaných souřadnicích. + + resize(int|string $width, int|string $height, int $flags=Image::OrSmaller): Image .[method] ------------------------------------------------------------------------------------------- Změní velikost obrázku, [více informací|#Změna velikosti]. Rozměry je možné zadávat jako integery v pixelech nebo řetězce v procentech (například `'50%'`). @@ -638,8 +664,8 @@ setInterpolation(int $method=IMG_BILINEAR_FIXED): void .[method] Nastaví metodu interpolace, která ovlivní metody `rotate()` a `affine()`. ([více |https://www.php.net/manual/en/function.imagesetinterpolation]) -setPixel(int $x, int $y, int $color): void .[method] ----------------------------------------------------- +setPixel(int $x, int $y, ImageColor $color): void .[method] +----------------------------------------------------------- Nakreslí pixel na zadané souřadnici. ([více |https://www.php.net/manual/en/function.imagesetpixel]) @@ -668,16 +694,6 @@ Doostří obrázek. Vyžaduje přítomnost *Bundled GD extension*, nemusí tedy fungovat všude. -string(int $font, int $x, int $y, string $str, int $col): void .[method] ------------------------------------------------------------------------- -Vypíše řetězec na zadané souřadnice. ([více |https://www.php.net/manual/en/function.imagestring]) - - -stringUp(int $font, int $x, int $y, string $s, int $col): void .[method] ------------------------------------------------------------------------- -Vypíše řetězec svisle na dané souřadnice. ([více |https://www.php.net/manual/en/function.imagestringup]) - - toString(int $type=ImageType::JPEG, int $quality=null): string .[method] ------------------------------------------------------------------------ Uloží obrázek do řetezce. @@ -690,6 +706,6 @@ trueColorToPalette(bool $dither, int $ncolors): void .[method] Převede obraz truecolor na paletový. ([více |https://www.php.net/manual/en/function.imagetruecolortopalette]) -ttfText(int $size, int $angle, int $x, int $y, int $color, string $fontfile, string $text): array .[method] ------------------------------------------------------------------------------------------------------------ -Vypíše daný text do obrázku pomocí písem TrueType. ([více |https://www.php.net/manual/en/function.imagettftext]) +ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method] +----------------------------------------------------------------------------------------------------------------------------------------- +Vypíše daný text do obrázku. ([více |https://www.php.net/manual/en/function.imagettftext]) diff --git a/utils/de/images.texy b/utils/de/images.texy index d2aabbb60c..5aef1e8eb2 100644 --- a/utils/de/images.texy +++ b/utils/de/images.texy @@ -17,6 +17,7 @@ Die folgenden Beispiele gehen davon aus, dass der folgende Klassenalias definier ```php use Nette\Utils\Image; +use Nette\Utils\ImageColor; use Nette\Utils\ImageType; ``` @@ -33,7 +34,7 @@ $image = Image::fromBlank(100, 200); Optional können Sie eine Hintergrundfarbe angeben (Standard ist schwarz): ```php -$image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0)); +$image = Image::fromBlank(100, 200, ImageColor::rgb(125, 0, 0)); ``` Oder wir laden das Bild aus einer Datei: @@ -191,16 +192,36 @@ $image->cropAuto(IMG_CROP_BLACK); Die Methode `cropAuto()` ist eine Objektkapselung der Funktion `imagecropauto()`, weitere Informationen finden Sie in der [zugehörigen Dokumentation |https://www.php.net/manual/en/function.imagecropauto]. +Farben .[#toc-colors] +===================== + +Mit der Methode `ImageColor::rgb()` können Sie eine Farbe anhand von Rot-, Grün- und Blauwerten (RGB) definieren. Optional können Sie auch einen Transparenzwert angeben, der von 0 (völlig transparent) bis 1 (völlig undurchsichtig) reicht, genau wie in CSS. + +```php +$color = ImageColor::rgb(255, 0, 0); // Red +$transparentBlue = ImageColor::rgb(0, 0, 255, 0.5); // Semi-transparent blue +``` + +Mit der Methode `ImageColor::hex()` können Sie eine Farbe im Hexadezimalformat definieren, ähnlich wie in CSS. Sie unterstützt die Formate `#rgb`, `#rrggbb`, `#rgba` und `#rrggbbaa`: + +```php +$color = ImageColor::hex("#F00"); // Red +$transparentGreen = ImageColor::hex("#00FF0080"); // Semi-transparent green +``` + +Farben können auch in anderen Methoden verwendet werden, z. B. `ellipse()`, `fill()`, usw. + + Zeichnen und Editieren .[#toc-drawing-and-editing] ================================================== -Sie können zeichnen, Sie können schreiben, Sie können alle PHP-Funktionen für die Arbeit mit Bildern verwenden, wie z.B. [imagefilledellipse() |https://www.php.net/manual/en/function.imagefilledellipse.php], aber im Objektstil: +Sie können zeichnen, Sie können schreiben, Sie können alle PHP-Funktionen zur Bildmanipulation verwenden, siehe [Übersicht der Methoden |#Overview of methods], aber in einem objektorientierten Wrapper: ```php -$image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63)); +$image->filledEllipse($centerX, $centerY, $width, $height, ImageColor::rgb(255, 0, 0)); ``` -Siehe [Überblick über die Methoden |#Overview of Methods]. +Da PHP-Funktionen zum Zeichnen von Rechtecken aufgrund der Angabe von Koordinaten unpraktisch sind, bietet die Klasse `Image` deren Ersatz in Form der Funktionen [rectangleWH() |#rectangleWH()] und [filledRectangleWH() |#filledRectangleWH()]. Mehrere Bilder zusammenführen .[#toc-merge-multiple-images] @@ -210,7 +231,7 @@ Sie können problemlos ein anderes Bild in das Bild einfügen: ```php $logo = Image::fromFile('logo.png'); -$blank = Image::fromBlank(320, 240, Image::rgb(52, 132, 210)); +$blank = Image::fromBlank(320, 240, ImageColor::rgb(52, 132, 210)); // Koordinaten können auch in Prozent angegeben werden $blank->place($logo, '80%', '80%'); // in der Nähe der rechten unteren Ecke @@ -229,8 +250,8 @@ Eine solche API ist wirklich ein Vergnügen, nicht wahr? ======================================================= -static fromBlank(int $width, int $height, array $color=null): Image .[method] ------------------------------------------------------------------------------ +static fromBlank(int $width, int $height, ImageColor $color=null): Image .[method] +---------------------------------------------------------------------------------- Erzeugt ein neues Echtfarbbild mit den angegebenen Abmessungen. Die Standardfarbe ist Schwarz. @@ -244,9 +265,9 @@ static fromString(string $s, int &$detectedFormat=null): Image .[method] Liest ein Bild aus einer Zeichenkette und gibt dessen [Typ |#Formats] in `$detectedFormat` zurück. -static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method] ---------------------------------------------------------------------------------- -Erzeugt eine Farbe, die in anderen Methoden verwendet werden kann, z. B. `ellipse()`, `fill()`, usw. +static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated] +--------------------------------------------------------------------------------------------- +Diese Funktion wurde durch die Klasse `ImageColor` ersetzt, siehe [Farben |#Colors]. static typeToExtension(int $type): string .[method] @@ -279,6 +300,11 @@ static isTypeSupported(int $type): bool .[method] Ermittelt, ob der angegebene [Bildtyp |#Formats] unterstützt wird. +static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method] +------------------------------------------------------------------------------------------------------------------------ +Berechnet die Abmessungen des Rechtecks, das den Text in einer bestimmten Schriftart und -größe umschließt. Sie gibt ein assoziatives Array zurück, das die Schlüssel `left`, `top`, `width`, `height` enthält. Der linke Rand kann negativ sein, wenn der Text mit einem linken Überhang beginnt. + + affine(array $affine, array $clip=null): Image .[method] -------------------------------------------------------- Gibt ein Bild zurück, das das affin transformierte Ausgangsbild enthält, wobei ein optionaler Beschneidungsbereich verwendet wird. ([mehr |https://www.php.net/manual/en/function.imageaffine]). @@ -306,21 +332,11 @@ Aktivieren Sie die Methoden zum schnellen Zeichnen von Linien und verdrahteten P Die Verwendung von Primitiven mit Antialiasing und transparenter Hintergrundfarbe kann zu unerwarteten Ergebnissen führen. Bei der Mischmethode wird die Hintergrundfarbe wie jede andere Farbe verwendet. Die fehlende Unterstützung von Alphakomponenten erlaubt keine alphabasierte Antialiasing-Methode. ([mehr |https://www.php.net/manual/en/function.imageantialias]) -arc(int $x, int $y, int $w, int $h, int $start, int $end, int $color): void .[method] -------------------------------------------------------------------------------------- +arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color): void .[method] +--------------------------------------------------------------------------------------------------------------------------- Zeichnet einen Kreisbogen, dessen Mittelpunkt die angegebenen Koordinaten sind. ([mehr |https://www.php.net/manual/en/function.imagearc]) -char(int $font, int $x, int $y, string $char, int $color): void .[method] -------------------------------------------------------------------------- -Zeichnet das erste Zeichen von `$char` im Bild mit seiner oberen linken Seite auf `$x`,`$y` (oben links ist 0, 0) mit der Farbe `$color`. ([mehr |https://www.php.net/manual/en/function.imagechar]) - - -charUp(int $font, int $x, int $y, string $char, int $color): void .[method] ---------------------------------------------------------------------------- -Zeichnet das Zeichen `$char` vertikal an der angegebenen Koordinate auf dem angegebenen Bild. ([mehr |https://www.php.net/manual/en/function.imagecharup]) - - colorAllocate(int $red, int $green, int $blue): int .[method] ------------------------------------------------------------- Gibt einen Farbbezeichner zurück, der die aus den angegebenen RGB-Komponenten zusammengesetzte Farbe darstellt. Sie muss aufgerufen werden, um jede Farbe, die im Bild verwendet werden soll, zu erzeugen. ([mehr |https://www.php.net/manual/en/function.imagecolorallocate]) @@ -447,43 +463,48 @@ crop(int|string $left, int|string $top, int|string $width, int|string $height): Beschneidet ein Bild auf den angegebenen rechteckigen Bereich. Die Abmessungen können als ganze Zahlen in Pixeln oder als Strings in Prozent (z. B. `'50%'`) übergeben werden. -cropAuto(int $mode=-1, float $threshold=.5, int $color=-1): Image .[method] ---------------------------------------------------------------------------- +cropAuto(int $mode=-1, float $threshold=.5, ?ImageColor $color=null): Image .[method] +------------------------------------------------------------------------------------- Beschneidet ein Bild automatisch entsprechend der angegebenen `$mode`. ([mehr |https://www.php.net/manual/en/function.imagecropauto]) -ellipse(int $cx, int $cy, int $w, int $h, int $color): void .[method] ---------------------------------------------------------------------- +ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method] +----------------------------------------------------------------------------------------------- Zeichnet eine Ellipse, deren Mittelpunkt die angegebenen Koordinaten sind. ([mehr |https://www.php.net/manual/en/function.imageellipse]) -fill(int $x, int $y, int $color): void .[method] ------------------------------------------------- +fill(int $x, int $y, ImageColor $color): void .[method] +------------------------------------------------------- Führt eine Flutfüllung durch, beginnend an der angegebenen Koordinate (oben links ist 0, 0) mit der angegebenen `$color` im Bild. ([mehr |https://www.php.net/manual/en/function.imagefill]) -filledArc(int $cx, int $cy, int $w, int $h, int $s, int $e, int $color, int $style): void .[method] ---------------------------------------------------------------------------------------------------- +filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style): void .[method] +--------------------------------------------------------------------------------------------------------------------------------------------- Zeichnet einen Teilbogen, der auf die angegebene Koordinate im Bild zentriert ist. ([mehr |https://www.php.net/manual/en/function.imagefilledarc]) -filledEllipse(int $cx, int $cy, int $w, int $h, int $color): void .[method] ---------------------------------------------------------------------------- +filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method] +----------------------------------------------------------------------------------------------------- Zeichnet eine Ellipse, deren Mittelpunkt die angegebene Koordinate im Bild ist. ([mehr |https://www.php.net/manual/en/function.imagefilledellipse]) -filledPolygon(array $points, int $numPoints, int $color): void .[method] ------------------------------------------------------------------------- +filledPolygon(array $points, ImageColor $color): void .[method] +--------------------------------------------------------------- Erzeugt ein gefülltes Polygon im $image. ([mehr |https://www.php.net/manual/en/function.imagefilledpolygon]) -filledRectangle(int $x1, int $y1, int $x2, int $y2, int $color): void .[method] -------------------------------------------------------------------------------- -Erzeugt ein Rechteck, das im Bild mit `$color` gefüllt ist und bei Punkt 1 beginnt und bei Punkt 2 endet. 0, 0 ist die linke obere Ecke des Bildes. ([mehr |https://www.php.net/manual/en/function.imagefilledrectangle]) +filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------- +Erzeugt ein mit `$color` gefülltes Rechteck im Bild, das bei `$x1` & `$y1` beginnt und bei `$x2` & `$y2` endet. Punkt 0, 0 ist die linke obere Ecke des Bildes. ([mehr |https://www.php.net/manual/en/function.imagefilledrectangle]) -fillToBorder(int $x, int $y, int $border, int $color): void .[method] ---------------------------------------------------------------------- +filledRectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------------------- +Erzeugt ein mit `$color` gefülltes Rechteck im Bild ausgehend von den Punkten `$left` & `$top` mit der Breite `$width` und der Höhe `$height`. Der Punkt 0, 0 ist die linke obere Ecke des Bildes. + + +fillToBorder(int $x, int $y, int $border, ImageColor $color): void .[method] +---------------------------------------------------------------------------- Führt eine Flutfüllung aus, deren Randfarbe durch `$border` definiert ist. Der Startpunkt für die Füllung ist `$x`, `$y` (oben links ist 0, 0) und der Bereich wird mit der Farbe `$color` gefüllt. ([mehr |https://www.php.net/manual/en/function.imagefilltoborder]) @@ -497,9 +518,9 @@ flip(int $mode): void .[method] Spiegelt das Bild unter Verwendung der angegebenen `$mode`. ([mehr |https://www.php.net/manual/en/function.imageflip]) -ftText(int $size, int $angle, int $x, int $y, int $col, string $fontFile, string $text, array $extrainfo=null): array .[method] -------------------------------------------------------------------------------------------------------------------------------- -Schreiben Sie Text in das Bild mit Hilfe von FreeType 2-Schriftarten. ([mehr |https://www.php.net/manual/en/function.imagefttext]) +ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method] +---------------------------------------------------------------------------------------------------------------------------------------- +Schreiben Sie den Text in das Bild. ([mehr |https://www.php.net/manual/en/function.imagefttext]) gammaCorrect(float $inputgamma, float $outputgamma): void .[method] @@ -542,13 +563,13 @@ layerEffect(int $effect): void .[method] Setzen Sie das Alpha-Blending-Flag, um Überlagerungseffekte zu verwenden. ([mehr |https://www.php.net/manual/en/function.imagelayereffect]) -line(int $x1, int $y1, int $x2, int $y2, int $color): void .[method] --------------------------------------------------------------------- +line(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +--------------------------------------------------------------------------- Zeichnet eine Linie zwischen den beiden angegebenen Punkten. ([mehr |https://www.php.net/manual/en/function.imageline]) -openPolygon(array $points, int $numPoints, int $color): void .[method] ----------------------------------------------------------------------- +openPolygon(array $points, ImageColor $color): void .[method] +------------------------------------------------------------- Zeichnet ein offenes Polygon auf das Bild. Im Gegensatz zu `polygon()` wird keine Linie zwischen dem letzten und dem ersten Punkt gezogen. ([mehr |https://www.php.net/manual/en/function.imageopenpolygon]) @@ -567,16 +588,21 @@ place(Image $image, int|string $left=0, int|string $top=0, int $opacity=100): Im Kopiert `$image` in das Bild an den Koordinaten `$left` und `$top`. Die Koordinaten können als ganze Zahlen in Pixeln oder als Zeichenketten in Prozent übergeben werden (z. B. `'50%'`). -polygon(array $points, int $numPoints, int $color): void .[method] ------------------------------------------------------------------- +polygon(array $points, ImageColor $color): void .[method] +--------------------------------------------------------- Erzeugt ein Polygon im Bild. ([mehr |https://www.php.net/manual/en/function.imagepolygon]) -rectangle(int $x1, int $y1, int $x2, int $y2, int $col): void .[method] ------------------------------------------------------------------------ +rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +-------------------------------------------------------------------------------- Erzeugt ein Rechteck, das an den angegebenen Koordinaten beginnt. ([mehr |https://www.php.net/manual/en/function.imagerectangle]) +rectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------------- +Erzeugt ein Rechteck mit den angegebenen Koordinaten. + + resize(int|string $width, int|string $height, int $flags=Image::OrSmaller): Image .[method] ------------------------------------------------------------------------------------------- Skaliert ein Bild, siehe [weitere Informationen |#Image Resize]. Die Abmessungen können als ganze Zahlen in Pixeln oder als Strings in Prozent (z. B. `'50%'`) übergeben werden. @@ -638,8 +664,8 @@ setInterpolation(int $method=IMG_BILINEAR_FIXED): void .[method] Legt die Interpolationsmethode fest, die sich auf die Methoden `rotate()` und `affine()` auswirkt. ([mehr |https://www.php.net/manual/en/function.imagesetinterpolation]) -setPixel(int $x, int $y, int $color): void .[method] ----------------------------------------------------- +setPixel(int $x, int $y, ImageColor $color): void .[method] +----------------------------------------------------------- Zeichnet ein Pixel an der angegebenen Koordinate. (mehr |https://www.php.net/manual/en/function.imagesetpixel]) @@ -668,16 +694,6 @@ Schärft das Bild ein wenig. Erfordert *GD-Erweiterung*, daher ist nicht sicher, dass sie überall funktioniert. -string(int $font, int $x, int $y, string $str, int $col): void .[method] ------------------------------------------------------------------------- -Zeichnet eine Zeichenkette an den angegebenen Koordinaten. ([mehr |https://www.php.net/manual/en/function.imagestring]) - - -stringUp(int $font, int $x, int $y, string $s, int $col): void .[method] ------------------------------------------------------------------------- -Zeichnet eine Zeichenkette vertikal an den angegebenen Koordinaten. ([mehr |https://www.php.net/manual/en/function.imagestringup]) - - toString(int $type=ImageType::JPEG, int $quality=null): string .[method] ------------------------------------------------------------------------ Gibt ein Bild als String aus. @@ -690,6 +706,6 @@ trueColorToPalette(bool $dither, int $ncolors): void .[method] Konvertiert ein Truecolor-Bild in ein Palettenbild. ([mehr |https://www.php.net/manual/en/function.imagetruecolortopalette]) -ttfText(int $size, int $angle, int $x, int $y, int $color, string $fontfile, string $text): array .[method] ------------------------------------------------------------------------------------------------------------ -Schreibt den angegebenen Text mit TrueType-Schriften in das Bild. ([mehr |https://www.php.net/manual/en/function.imagettftext]) +ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method] +----------------------------------------------------------------------------------------------------------------------------------------- +Schreibt den angegebenen Text in das Bild. ([mehr |https://www.php.net/manual/en/function.imagettftext]) diff --git a/utils/el/images.texy b/utils/el/images.texy index e46fd27d6e..6260f68f37 100644 --- a/utils/el/images.texy +++ b/utils/el/images.texy @@ -17,6 +17,7 @@ composer require nette/utils ```php use Nette\Utils\Image; +use Nette\Utils\ImageColor; use Nette\Utils\ImageType; ``` @@ -33,7 +34,7 @@ $image = Image::fromBlank(100, 200); Προαιρετικά, μπορείτε να καθορίσετε ένα χρώμα φόντου (το προεπιλεγμένο είναι μαύρο): ```php -$image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0)); +$image = Image::fromBlank(100, 200, ImageColor::rgb(125, 0, 0)); ``` Ή φορτώνουμε την εικόνα από ένα αρχείο: @@ -191,16 +192,36 @@ $image->cropAuto(IMG_CROP_BLACK); Η μέθοδος `cropAuto()` είναι μια ενθυλάκωση αντικειμένου της συνάρτησης `imagecropauto()`, δείτε [την τεκμηρίωσή της |https://www.php.net/manual/en/function.imagecropauto] για περισσότερες πληροφορίες. +Χρώματα .[#toc-colors] +====================== + +Η μέθοδος `ImageColor::rgb()` σας επιτρέπει να ορίσετε ένα χρώμα χρησιμοποιώντας τιμές κόκκινου, πράσινου και μπλε (RGB). Προαιρετικά, μπορείτε επίσης να καθορίσετε μια τιμή διαφάνειας που κυμαίνεται από 0 (εντελώς διαφανής) έως 1 (πλήρως αδιαφανής), όπως ακριβώς και στα CSS. + +```php +$color = ImageColor::rgb(255, 0, 0); // Red +$transparentBlue = ImageColor::rgb(0, 0, 255, 0.5); // Semi-transparent blue +``` + +Η μέθοδος `ImageColor::hex()` σάς επιτρέπει να ορίσετε ένα χρώμα χρησιμοποιώντας τη δεκαεξαδική μορφή, παρόμοια με τη CSS. Υποστηρίζει τις μορφές `#rgb`, `#rrggbb`, `#rgba` και `#rrggbbaa`: + +```php +$color = ImageColor::hex("#F00"); // Red +$transparentGreen = ImageColor::hex("#00FF0080"); // Semi-transparent green +``` + +Τα χρώματα μπορούν να χρησιμοποιηθούν σε άλλες μεθόδους, όπως `ellipse()`, `fill()`, κ.λπ. + + Σχεδίαση και επεξεργασία .[#toc-drawing-and-editing] ==================================================== -Μπορείτε να σχεδιάσετε, να γράψετε, να χρησιμοποιήσετε όλες τις συναρτήσεις της PHP για την εργασία με εικόνες, όπως η [imagefilledellipse() |https://www.php.net/manual/en/function.imagefilledellipse.php], αλλά χρησιμοποιώντας στυλ αντικειμένου: +Μπορείτε να σχεδιάσετε, να γράψετε, να χρησιμοποιήσετε όλες τις συναρτήσεις της PHP για την επεξεργασία εικόνων, βλέπε [Επισκόπηση μεθόδων |#Overview of methods], αλλά σε ένα αντικειμενοστραφές περιτύλιγμα: ```php -$image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63)); +$image->filledEllipse($centerX, $centerY, $width, $height, ImageColor::rgb(255, 0, 0)); ``` -Βλέπε [Επισκόπηση των μεθόδων |#Overview of Methods]. +Δεδομένου ότι οι συναρτήσεις της PHP για τη σχεδίαση ορθογωνίων δεν είναι πρακτικές λόγω του καθορισμού συντεταγμένων, η κλάση `Image` προσφέρει την αντικατάστασή τους με τη μορφή των συναρτήσεων [rectangleWH() |#rectangleWH()] και [filledRectangleWH() |#filledRectangleWH()]. Συγχώνευση πολλαπλών εικόνων .[#toc-merge-multiple-images] @@ -210,7 +231,7 @@ $image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63)); ```php $logo = Image::fromFile('logo.png'); -$blank = Image::fromBlank(320, 240, Image::rgb(52, 132, 210)); +$blank = Image::fromBlank(320, 240, ImageColor::rgb(52, 132, 210)); // οι συντεταγμένες μπορούν να οριστούν επίσης σε ποσοστό $blank->place($logo, '80%', '80%'); // κοντά στην κάτω δεξιά γωνία @@ -229,8 +250,8 @@ $blank->place($image, '80%', '80%', 25); // η διαφάνεια είναι 25 ================================================== -static fromBlank(int $width, int $height, array $color=null): Image .[method] ------------------------------------------------------------------------------ +static fromBlank(int $width, int $height, ImageColor $color=null): Image .[method] +---------------------------------------------------------------------------------- Δημιουργεί μια νέα έγχρωμη εικόνα με τις δεδομένες διαστάσεις. Το προεπιλεγμένο χρώμα είναι το μαύρο. @@ -244,9 +265,9 @@ static fromString(string $s, int &$detectedFormat=null): Image .[method] Διαβάζει μια εικόνα από μια συμβολοσειρά και επιστρέφει τον [τύπο |#Formats] της σε `$detectedFormat`. -static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method] ---------------------------------------------------------------------------------- -Δημιουργεί ένα χρώμα που μπορεί να χρησιμοποιηθεί σε άλλες μεθόδους, όπως οι `ellipse()`, `fill()` κ.ο.κ. +static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated] +--------------------------------------------------------------------------------------------- +Το χαρακτηριστικό αυτό έχει αντικατασταθεί από την κλάση `ImageColor`, βλέπε [χρώματα |#Colors]. static typeToExtension(int $type): string .[method] @@ -279,6 +300,11 @@ static isTypeSupported(int $type): bool .[method] Καθορίζει αν υποστηρίζεται ο συγκεκριμένος [τύπος |#Formats] εικόνας. +static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method] +------------------------------------------------------------------------------------------------------------------------ +Υπολογίζει τις διαστάσεις του ορθογωνίου που περικλείει το κείμενο σε καθορισμένη γραμματοσειρά και μέγεθος. Επιστρέφει έναν συσχετιστικό πίνακα που περιέχει τα κλειδιά `left`, `top`, `width`, `height`. Το αριστερό περιθώριο μπορεί να είναι αρνητικό εάν το κείμενο ξεκινά με αριστερή προεξοχή. + + affine(array $affine, array $clip=null): Image .[method] -------------------------------------------------------- Επιστρέφει μια εικόνα που περιέχει την affine μετασχηματισμένη εικόνα src, χρησιμοποιώντας μια προαιρετική περιοχή αποκοπής. ([περισσότερα |https://www.php.net/manual/en/function.imageaffine]). @@ -306,21 +332,11 @@ antialias(bool $on): void .[method] Η χρήση primitives με αντιδιαμετρική απεικόνιση και διαφανές χρώμα φόντου μπορεί να οδηγήσει σε απροσδόκητα αποτελέσματα. Η μέθοδος ανάμειξης χρησιμοποιεί το χρώμα φόντου όπως όλα τα άλλα χρώματα. Η έλλειψη υποστήριξης του συστατικού άλφα δεν επιτρέπει μια μέθοδο αντιδιαστολής με βάση το άλφα. ([περισσότερα |https://www.php.net/manual/en/function.imageantialias]) -arc(int $x, int $y, int $w, int $h, int $start, int $end, int $color): void .[method] -------------------------------------------------------------------------------------- +arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color): void .[method] +--------------------------------------------------------------------------------------------------------------------------- Σχεδιάζει ένα τόξο κύκλου με κέντρο τις δεδομένες συντεταγμένες. ([περισσότερα |https://www.php.net/manual/en/function.imagearc]) -char(int $font, int $x, int $y, string $char, int $color): void .[method] -------------------------------------------------------------------------- -Σχεδιάζει τον πρώτο χαρακτήρα του `$char` στην εικόνα με το πάνω αριστερό μέρος του στο `$x`,`$y` (το πάνω αριστερό μέρος είναι 0, 0) με το χρώμα `$color`. ([περισσότερα |https://www.php.net/manual/en/function.imagechar]) - - -charUp(int $font, int $x, int $y, string $char, int $color): void .[method] ---------------------------------------------------------------------------- -Σχεδιάζει τον χαρακτήρα `$char` κάθετα στην καθορισμένη συντεταγμένη της δεδομένης εικόνας. ([περισσότερα |https://www.php.net/manual/en/function.imagecharup]) - - colorAllocate(int $red, int $green, int $blue): int .[method] ------------------------------------------------------------- Επιστρέφει ένα αναγνωριστικό χρώματος που αντιπροσωπεύει το χρώμα που αποτελείται από τις δεδομένες συνιστώσες RGB. Πρέπει να κληθεί για να δημιουργήσει κάθε χρώμα που πρόκειται να χρησιμοποιηθεί στην εικόνα. ([περισσότερα |https://www.php.net/manual/en/function.imagecolorallocate]) @@ -447,43 +463,48 @@ crop(int|string $left, int|string $top, int|string $width, int|string $height): Περικόπτει μια εικόνα στη δεδομένη ορθογώνια περιοχή. Οι διαστάσεις μπορούν να μεταβιβαστούν ως ακέραιοι αριθμοί σε pixels ή συμβολοσειρές σε ποσοστό (π.χ. `'50%'`). -cropAuto(int $mode=-1, float $threshold=.5, int $color=-1): Image .[method] ---------------------------------------------------------------------------- +cropAuto(int $mode=-1, float $threshold=.5, ?ImageColor $color=null): Image .[method] +------------------------------------------------------------------------------------- Αυτόματη περικοπή μιας εικόνας σύμφωνα με το δεδομένο `$mode`. ([περισσότερα |https://www.php.net/manual/en/function.imagecropauto]) -ellipse(int $cx, int $cy, int $w, int $h, int $color): void .[method] ---------------------------------------------------------------------- +ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method] +----------------------------------------------------------------------------------------------- Σχεδιάζει μια έλλειψη με κέντρο τις καθορισμένες συντεταγμένες. ([περισσότερα |https://www.php.net/manual/en/function.imageellipse]) -fill(int $x, int $y, int $color): void .[method] ------------------------------------------------- +fill(int $x, int $y, ImageColor $color): void .[method] +------------------------------------------------------- Εκτελεί ένα γέμισμα πλημμύρας με αφετηρία τη δεδομένη συντεταγμένη (πάνω αριστερά είναι 0, 0) με το δεδομένο `$color` στην εικόνα. ([περισσότερα |https://www.php.net/manual/en/function.imagefill]) -filledArc(int $cx, int $cy, int $w, int $h, int $s, int $e, int $color, int $style): void .[method] ---------------------------------------------------------------------------------------------------- +filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style): void .[method] +--------------------------------------------------------------------------------------------------------------------------------------------- Σχεδιάζει ένα μερικό τόξο με κέντρο την καθορισμένη συντεταγμένη στην εικόνα. ([περισσότερα |https://www.php.net/manual/en/function.imagefilledarc]) -filledEllipse(int $cx, int $cy, int $w, int $h, int $color): void .[method] ---------------------------------------------------------------------------- +filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method] +----------------------------------------------------------------------------------------------------- Σχεδιάζει μια έλλειψη με κέντρο την καθορισμένη συντεταγμένη στην εικόνα. ([περισσότερα |https://www.php.net/manual/en/function.imagefilledellipse]) -filledPolygon(array $points, int $numPoints, int $color): void .[method] ------------------------------------------------------------------------- +filledPolygon(array $points, ImageColor $color): void .[method] +--------------------------------------------------------------- Δημιουργεί ένα γεμάτο πολύγωνο στην εικόνα $image. ([περισσότερα |https://www.php.net/manual/en/function.imagefilledpolygon]) -filledRectangle(int $x1, int $y1, int $x2, int $y2, int $color): void .[method] -------------------------------------------------------------------------------- -Δημιουργεί ένα ορθογώνιο γεμάτο με το `$color` στην εικόνα που ξεκινά από το σημείο 1 και καταλήγει στο σημείο 2. 0, 0 είναι η επάνω αριστερή γωνία της εικόνας. ([περισσότερα |https://www.php.net/manual/en/function.imagefilledrectangle]) +filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------- +Δημιουργεί ένα ορθογώνιο γεμάτο με `$color` στην εικόνα που ξεκινά από τα σημεία `$x1` & `$y1` και καταλήγει στα σημεία `$x2` & `$y2`. Το σημείο 0, 0 είναι η επάνω αριστερή γωνία της εικόνας. ([περισσότερα |https://www.php.net/manual/en/function.imagefilledrectangle]) -fillToBorder(int $x, int $y, int $border, int $color): void .[method] ---------------------------------------------------------------------- +filledRectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------------------- +Δημιουργεί ένα ορθογώνιο γεμάτο με `$color` στην εικόνα ξεκινώντας από τα σημεία `$left` & `$top` με πλάτος `$width` και ύψος `$height`. Το σημείο 0, 0 είναι η επάνω αριστερή γωνία της εικόνας. + + +fillToBorder(int $x, int $y, int $border, ImageColor $color): void .[method] +---------------------------------------------------------------------------- Εκτελεί ένα γέμισμα πλημμύρας του οποίου το χρώμα των ορίων ορίζεται από το `$border`. Το σημείο εκκίνησης για το γέμισμα είναι `$x`, `$y` (πάνω αριστερά είναι 0, 0) και η περιοχή γεμίζεται με το χρώμα `$color`. ([περισσότερα |https://www.php.net/manual/en/function.imagefilltoborder]) @@ -497,9 +518,9 @@ flip(int $mode): void .[method] Αναποδογυρίζει την εικόνα χρησιμοποιώντας το δεδομένο `$mode`. ([περισσότερα |https://www.php.net/manual/en/function.imageflip]) -ftText(int $size, int $angle, int $x, int $y, int $col, string $fontFile, string $text, array $extrainfo=null): array .[method] -------------------------------------------------------------------------------------------------------------------------------- -Γράψτε κείμενο στην εικόνα χρησιμοποιώντας γραμματοσειρές με το FreeType 2. ([περισσότερα |https://www.php.net/manual/en/function.imagefttext]) +ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method] +---------------------------------------------------------------------------------------------------------------------------------------- +Γράψτε το κείμενο στην εικόνα. ([περισσότερα |https://www.php.net/manual/en/function.imagefttext]) gammaCorrect(float $inputgamma, float $outputgamma): void .[method] @@ -542,13 +563,13 @@ layerEffect(int $effect): void .[method] Ορίστε τη σημαία ανάμειξης άλφα για να χρησιμοποιήσετε εφέ διαστρωμάτωσης. ([περισσότερα |https://www.php.net/manual/en/function.imagelayereffect]) -line(int $x1, int $y1, int $x2, int $y2, int $color): void .[method] --------------------------------------------------------------------- +line(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +--------------------------------------------------------------------------- Σχεδιάζει μια γραμμή μεταξύ των δύο δοσμένων σημείων. ([περισσότερα |https://www.php.net/manual/en/function.imageline]) -openPolygon(array $points, int $numPoints, int $color): void .[method] ----------------------------------------------------------------------- +openPolygon(array $points, ImageColor $color): void .[method] +------------------------------------------------------------- Σχεδιάζει ένα ανοιχτό πολύγωνο στην εικόνα. Σε αντίθεση με το `polygon()`, δεν χαράσσεται γραμμή μεταξύ του τελευταίου και του πρώτου σημείου. ([περισσότερα |https://www.php.net/manual/en/function.imageopenpolygon]) @@ -567,16 +588,21 @@ place(Image $image, int|string $left=0, int|string $top=0, int $opacity=100): Im Αντιγράφει το `$image` στην εικόνα στις συντεταγμένες `$left` και `$top`. Οι συντεταγμένες μπορούν να μεταβιβαστούν ως ακέραιοι αριθμοί σε pixels ή συμβολοσειρές σε ποσοστό (π.χ. `'50%'`). -polygon(array $points, int $numPoints, int $color): void .[method] ------------------------------------------------------------------- +polygon(array $points, ImageColor $color): void .[method] +--------------------------------------------------------- Δημιουργεί ένα πολύγωνο στην εικόνα. ([περισσότερα |https://www.php.net/manual/en/function.imagepolygon]) -rectangle(int $x1, int $y1, int $x2, int $y2, int $col): void .[method] ------------------------------------------------------------------------ +rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +-------------------------------------------------------------------------------- Δημιουργεί ένα ορθογώνιο που ξεκινά από τις καθορισμένες συντεταγμένες. ([περισσότερα |https://www.php.net/manual/en/function.imagerectangle]) +rectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------------- +Δημιουργεί ένα ορθογώνιο στις δεδομένες συντεταγμένες. + + resize(int|string $width, int|string $height, int $flags=Image::OrSmaller): Image .[method] ------------------------------------------------------------------------------------------- Κλιμακώνει μια εικόνα, δείτε [περισσότερες πληροφορίες |#Image Resize]. Οι διαστάσεις μπορούν να μεταβιβαστούν ως ακέραιοι αριθμοί σε pixels ή συμβολοσειρές σε ποσοστό (π.χ. `'50%'`). @@ -638,8 +664,8 @@ setInterpolation(int $method=IMG_BILINEAR_FIXED): void .[method] Ορίζει τη μέθοδο παρεμβολής, η οποία επηρεάζει τις μεθόδους `rotate()` και `affine()`. ([περισσότερα |https://www.php.net/manual/en/function.imagesetinterpolation]) -setPixel(int $x, int $y, int $color): void .[method] ----------------------------------------------------- +setPixel(int $x, int $y, ImageColor $color): void .[method] +----------------------------------------------------------- Σχεδιάζει ένα εικονοστοιχείο στην καθορισμένη συντεταγμένη. ([περισσότερα |https://www.php.net/manual/en/function.imagesetpixel]) @@ -668,16 +694,6 @@ sharpen(): Image .[method] Απαιτεί *Επέκταση GD Bundled*, οπότε δεν είναι σίγουρο ότι θα λειτουργήσει παντού. -string(int $font, int $x, int $y, string $str, int $col): void .[method] ------------------------------------------------------------------------- -Σχεδιάζει μια συμβολοσειρά στις δεδομένες συντεταγμένες. ([περισσότερα |https://www.php.net/manual/en/function.imagestring]) - - -stringUp(int $font, int $x, int $y, string $s, int $col): void .[method] ------------------------------------------------------------------------- -Σχεδιάζει μια συμβολοσειρά κάθετα στις δεδομένες συντεταγμένες. ([περισσότερα |https://www.php.net/manual/en/function.imagestringup]) - - toString(int $type=ImageType::JPEG, int $quality=null): string .[method] ------------------------------------------------------------------------ Εξάγει μια εικόνα σε συμβολοσειρά. @@ -690,6 +706,6 @@ trueColorToPalette(bool $dither, int $ncolors): void .[method] Μετατρέπει μια εικόνα πραγματικού χρώματος σε εικόνα παλέτας. ([περισσότερα |https://www.php.net/manual/en/function.imagetruecolortopalette]) -ttfText(int $size, int $angle, int $x, int $y, int $color, string $fontfile, string $text): array .[method] ------------------------------------------------------------------------------------------------------------ -Γράφει το δεδομένο κείμενο στην εικόνα χρησιμοποιώντας γραμματοσειρές TrueType. ([περισσότερα |https://www.php.net/manual/en/function.imagettftext]) +ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method] +----------------------------------------------------------------------------------------------------------------------------------------- +Γράφει το δεδομένο κείμενο στην εικόνα. ([περισσότερα |https://www.php.net/manual/en/function.imagettftext]) diff --git a/utils/en/images.texy b/utils/en/images.texy index d1d5c12c93..214cd3daae 100644 --- a/utils/en/images.texy +++ b/utils/en/images.texy @@ -17,6 +17,7 @@ Following examples assume the following class alias is defined: ```php use Nette\Utils\Image; +use Nette\Utils\ImageColor; use Nette\Utils\ImageType; ``` @@ -33,7 +34,7 @@ $image = Image::fromBlank(100, 200); Optionally, you can specify a background color (default is black): ```php -$image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0)); +$image = Image::fromBlank(100, 200, ImageColor::rgb(125, 0, 0)); ``` Or we load the image from a file: @@ -191,16 +192,36 @@ $image->cropAuto(IMG_CROP_BLACK); Method `cropAuto()` is an object encapsulation of the `imagecropauto()` function, see [its documentation|https://www.php.net/manual/en/function.imagecropauto] for more information. +Colors .{data-version:4.0.2} +============================ + +The `ImageColor::rgb()` method allows you to define a color using red, green, and blue (RGB) values. Optionally, you can also specify a transparency value ranging from 0 (completely transparent) to 1 (fully opaque), just like in CSS. + +```php +$color = ImageColor::rgb(255, 0, 0); // Red +$transparentBlue = ImageColor::rgb(0, 0, 255, 0.5); // Semi-transparent blue +``` + +The `ImageColor::hex()` method allows you to define a color using the hexadecimal format, similar to CSS. It supports the formats `#rgb`, `#rrggbb`, `#rgba`, and `#rrggbbaa`: + +```php +$color = ImageColor::hex("#F00"); // Red +$transparentGreen = ImageColor::hex("#00FF0080"); // Semi-transparent green +``` + +Colors can be used in other methods, such as `ellipse()`, `fill()`, etc. + + Drawing and Editing =================== -You can draw, you can write, you can use all PHP functions for working with images, such as [imagefilledellipse()|https://www.php.net/manual/en/function.imagefilledellipse.php], but using object style: +You can draw, you can write, you can use all PHP functions for image manipulation, see [#Overview of methods], but in an object-oriented wrapper: ```php -$image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63)); +$image->filledEllipse($centerX, $centerY, $width, $height, ImageColor::rgb(255, 0, 0)); ``` -See [#Overview of Methods]. +Since PHP functions for drawing rectangles are impractical due to specifying coordinates, the `Image` class offers their replacements in the form of functions [#rectangleWH()] and [#filledRectangleWH()]. Merge Multiple Images @@ -210,7 +231,7 @@ You can easily place another image into the image: ```php $logo = Image::fromFile('logo.png'); -$blank = Image::fromBlank(320, 240, Image::rgb(52, 132, 210)); +$blank = Image::fromBlank(320, 240, ImageColor::rgb(52, 132, 210)); // coordinates can be set also in percentage $blank->place($logo, '80%', '80%'); // near the right bottom corner @@ -229,8 +250,8 @@ Overview of Methods =================== -static fromBlank(int $width, int $height, array $color=null): Image .[method] ------------------------------------------------------------------------------ +static fromBlank(int $width, int $height, ImageColor $color=null): Image .[method] +---------------------------------------------------------------------------------- Creates a new true color image of the given dimensions. The default color is black. @@ -244,9 +265,9 @@ static fromString(string $s, int &$detectedFormat=null): Image .[method] Reads an image from a string and returns its [type|#Formats] in `$detectedFormat`. -static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method] ---------------------------------------------------------------------------------- -Creates a color that can be used in other methods, such as `ellipse()`, `fill()`, and so on. +static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated] +--------------------------------------------------------------------------------------------- +This feature has been replaced by the `ImageColor` class , see [colors |#Colors]. static typeToExtension(int $type): string .[method] @@ -279,6 +300,11 @@ static isTypeSupported(int $type): bool .[method] Determines if the given image [type|#Formats] is supported. +static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method] +------------------------------------------------------------------------------------------------------------------------ +Calculates the dimensions of the rectangle that encloses the text in a specified font and size. It returns an associative array containing the keys `left`, `top`, `width`, `height`. The left margin can be negative if the text starts with a left overhang. + + affine(array $affine, array $clip=null): Image .[method] -------------------------------------------------------- Return an image containing the affine transformed src image, using an optional clipping area. ([more|https://www.php.net/manual/en/function.imageaffine]). @@ -306,21 +332,11 @@ Activate the fast drawing antialiased methods for lines and wired polygons. It d Using antialiased primitives with transparent background color can end with some unexpected results. The blend method uses the background color as any other colors. The lack of alpha component support does not allow an alpha based antialiasing method. ([more|https://www.php.net/manual/en/function.imageantialias]) -arc(int $x, int $y, int $w, int $h, int $start, int $end, int $color): void .[method] -------------------------------------------------------------------------------------- +arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color): void .[method] +--------------------------------------------------------------------------------------------------------------------------- Draws an arc of circle centered at the given coordinates. ([more|https://www.php.net/manual/en/function.imagearc]) -char(int $font, int $x, int $y, string $char, int $color): void .[method] -------------------------------------------------------------------------- -Draws the first character of `$char` in the image with its upper-left at `$x`,`$y` (top left is 0, 0) with the color `$color`. ([more|https://www.php.net/manual/en/function.imagechar]) - - -charUp(int $font, int $x, int $y, string $char, int $color): void .[method] ---------------------------------------------------------------------------- -Draws the character `$char` vertically at the specified coordinate on the given image. ([more|https://www.php.net/manual/en/function.imagecharup]) - - colorAllocate(int $red, int $green, int $blue): int .[method] ------------------------------------------------------------- Returns a color identifier representing the color composed of the given RGB components. It must be called to create each color that is to be used in the image. ([more|https://www.php.net/manual/en/function.imagecolorallocate]) @@ -447,43 +463,48 @@ crop(int|string $left, int|string $top, int|string $width, int|string $height): Crops an image to the given rectangular area. Dimensions can be passed as integers in pixels or strings in percent (i.e. `'50%'`). -cropAuto(int $mode=-1, float $threshold=.5, int $color=-1): Image .[method] ---------------------------------------------------------------------------- +cropAuto(int $mode=-1, float $threshold=.5, ?ImageColor $color=null): Image .[method] +------------------------------------------------------------------------------------- Automatically crops an image according to the given `$mode`. ([more|https://www.php.net/manual/en/function.imagecropauto]) -ellipse(int $cx, int $cy, int $w, int $h, int $color): void .[method] ---------------------------------------------------------------------- +ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method] +----------------------------------------------------------------------------------------------- Draws an ellipse centered at the specified coordinates. ([more|https://www.php.net/manual/en/function.imageellipse]) -fill(int $x, int $y, int $color): void .[method] ------------------------------------------------- +fill(int $x, int $y, ImageColor $color): void .[method] +------------------------------------------------------- Performs a flood fill starting at the given coordinate (top left is 0, 0) with the given `$color` in the image. ([more|https://www.php.net/manual/en/function.imagefill]) -filledArc(int $cx, int $cy, int $w, int $h, int $s, int $e, int $color, int $style): void .[method] ---------------------------------------------------------------------------------------------------- +filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style): void .[method] +--------------------------------------------------------------------------------------------------------------------------------------------- Draws a partial arc centered at the specified coordinate in the image. ([more|https://www.php.net/manual/en/function.imagefilledarc]) -filledEllipse(int $cx, int $cy, int $w, int $h, int $color): void .[method] ---------------------------------------------------------------------------- +filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method] +----------------------------------------------------------------------------------------------------- Draws an ellipse centered at the specified coordinate in the image. ([more|https://www.php.net/manual/en/function.imagefilledellipse]) -filledPolygon(array $points, int $numPoints, int $color): void .[method] ------------------------------------------------------------------------- +filledPolygon(array $points, ImageColor $color): void .[method] +--------------------------------------------------------------- Creates a filled polygon in the $image. ([more|https://www.php.net/manual/en/function.imagefilledpolygon]) -filledRectangle(int $x1, int $y1, int $x2, int $y2, int $color): void .[method] -------------------------------------------------------------------------------- -Creates a rectangle filled with `$color` in the image starting at point 1 and ending at point 2. 0, 0 is the top left corner of the image. ([more|https://www.php.net/manual/en/function.imagefilledrectangle]) +filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------- +Creates a rectangle filled with `$color` in the image starting at `$x1` & `$y1` and ending at `$x2` & `$y2`. Point 0, 0 is the top left corner of the image. ([more |https://www.php.net/manual/en/function.imagefilledrectangle]) -fillToBorder(int $x, int $y, int $border, int $color): void .[method] ---------------------------------------------------------------------- +filledRectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------------------- +Creates a rectangle filled with `$color` in the image starting from point `$left` & `$top` with width `$width` and height `$height`. Point 0, 0 is the top left corner of the image. + + +fillToBorder(int $x, int $y, int $border, ImageColor $color): void .[method] +---------------------------------------------------------------------------- Performs a flood fill whose border color is defined by `$border`. The starting point for the fill is `$x`, `$y` (top left is 0, 0) and the region is filled with color `$color`. ([more|https://www.php.net/manual/en/function.imagefilltoborder]) @@ -497,9 +518,9 @@ flip(int $mode): void .[method] Flips the image using the given `$mode`. ([more|https://www.php.net/manual/en/function.imageflip]) -ftText(int $size, int $angle, int $x, int $y, int $col, string $fontFile, string $text, array $extrainfo=null): array .[method] -------------------------------------------------------------------------------------------------------------------------------- -Write text to the image using fonts using FreeType 2. ([more|https://www.php.net/manual/en/function.imagefttext]) +ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method] +---------------------------------------------------------------------------------------------------------------------------------------- +Write the text in the picture. ([more |https://www.php.net/manual/en/function.imagefttext]) gammaCorrect(float $inputgamma, float $outputgamma): void .[method] @@ -542,13 +563,13 @@ layerEffect(int $effect): void .[method] Set the alpha blending flag to use layering effects. ([more|https://www.php.net/manual/en/function.imagelayereffect]) -line(int $x1, int $y1, int $x2, int $y2, int $color): void .[method] --------------------------------------------------------------------- +line(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +--------------------------------------------------------------------------- Draws a line between the two given points. ([more|https://www.php.net/manual/en/function.imageline]) -openPolygon(array $points, int $numPoints, int $color): void .[method] ----------------------------------------------------------------------- +openPolygon(array $points, ImageColor $color): void .[method] +------------------------------------------------------------- Draws an open polygon on the image. Contrary to `polygon()`, no line is drawn between the last and the first point. ([more|https://www.php.net/manual/en/function.imageopenpolygon]) @@ -567,16 +588,21 @@ place(Image $image, int|string $left=0, int|string $top=0, int $opacity=100): Im Copies `$image` to the image at the coordinates `$left` and `$top`. Coordinates can be passed as integers in pixels or strings in percent (i.e. `'50%'`). -polygon(array $points, int $numPoints, int $color): void .[method] ------------------------------------------------------------------- +polygon(array $points, ImageColor $color): void .[method] +--------------------------------------------------------- Creates a polygon in the image. ([more|https://www.php.net/manual/en/function.imagepolygon]) -rectangle(int $x1, int $y1, int $x2, int $y2, int $col): void .[method] ------------------------------------------------------------------------ +rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +-------------------------------------------------------------------------------- Creates a rectangle starting at the specified coordinates. ([more|https://www.php.net/manual/en/function.imagerectangle]) +rectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------------- +Creates a rectangle at the given coordinates. + + resize(int|string $width, int|string $height, int $flags=Image::OrSmaller): Image .[method] ------------------------------------------------------------------------------------------- Scales an image, see [more info|#Image Resize]. Dimensions can be passed as integers in pixels or strings in percent (i.e. `'50%'`). @@ -638,8 +664,8 @@ setInterpolation(int $method=IMG_BILINEAR_FIXED): void .[method] Sets the interpolation method which affects methods `rotate()` and `affine()`. ([more|https://www.php.net/manual/en/function.imagesetinterpolation]) -setPixel(int $x, int $y, int $color): void .[method] ----------------------------------------------------- +setPixel(int $x, int $y, ImageColor $color): void .[method] +----------------------------------------------------------- Draws a pixel at the specified coordinate. ([more|https://www.php.net/manual/en/function.imagesetpixel]) @@ -668,16 +694,6 @@ Sharpens image a little bit. Requires *Bundled GD extension*, so it is not sure it will work everywhere. -string(int $font, int $x, int $y, string $str, int $col): void .[method] ------------------------------------------------------------------------- -Draws a string at the given coordinates. ([more|https://www.php.net/manual/en/function.imagestring]) - - -stringUp(int $font, int $x, int $y, string $s, int $col): void .[method] ------------------------------------------------------------------------- -Draws a string vertically at the given coordinates. ([more|https://www.php.net/manual/en/function.imagestringup]) - - toString(int $type=ImageType::JPEG, int $quality=null): string .[method] ------------------------------------------------------------------------ Outputs an image to string. @@ -690,6 +706,6 @@ trueColorToPalette(bool $dither, int $ncolors): void .[method] Converts a truecolor image to a palette image. ([more|https://www.php.net/manual/en/function.imagetruecolortopalette]) -ttfText(int $size, int $angle, int $x, int $y, int $color, string $fontfile, string $text): array .[method] ------------------------------------------------------------------------------------------------------------ -Writes the given text into the image using TrueType fonts. ([more|https://www.php.net/manual/en/function.imagettftext]) +ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method] +----------------------------------------------------------------------------------------------------------------------------------------- +Writes the given text into the image. ([more |https://www.php.net/manual/en/function.imagettftext]) diff --git a/utils/es/images.texy b/utils/es/images.texy index f48770b3fb..3d34e6f2c0 100644 --- a/utils/es/images.texy +++ b/utils/es/images.texy @@ -17,6 +17,7 @@ Los siguientes ejemplos suponen que se ha definido el siguiente alias de clase: ```php use Nette\Utils\Image; +use Nette\Utils\ImageColor; use Nette\Utils\ImageType; ``` @@ -33,7 +34,7 @@ $image = Image::fromBlank(100, 200); Opcionalmente, puede especificar un color de fondo (por defecto es negro): ```php -$image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0)); +$image = Image::fromBlank(100, 200, ImageColor::rgb(125, 0, 0)); ``` O cargamos la imagen desde un archivo: @@ -191,16 +192,36 @@ $image->cropAuto(IMG_CROP_BLACK); El método `cropAuto()` es una encapsulación de objeto de la función `imagecropauto()`, consulte [su documentación |https://www.php.net/manual/en/function.imagecropauto] para obtener más información. +Colores .[#toc-colors] +====================== + +El método `ImageColor::rgb()` le permite definir un color utilizando los valores rojo, verde y azul (RGB). Opcionalmente, también puede especificar un valor de transparencia que va de 0 (completamente transparente) a 1 (completamente opaco), igual que en CSS. + +```php +$color = ImageColor::rgb(255, 0, 0); // Red +$transparentBlue = ImageColor::rgb(0, 0, 255, 0.5); // Semi-transparent blue +``` + +El método `ImageColor::hex()` permite definir un color utilizando el formato hexadecimal, de forma similar a CSS. Admite los formatos `#rgb`, `#rrggbb`, `#rgba`, y `#rrggbbaa`: + +```php +$color = ImageColor::hex("#F00"); // Red +$transparentGreen = ImageColor::hex("#00FF0080"); // Semi-transparent green +``` + +Los colores pueden utilizarse en otros métodos, como `ellipse()`, `fill()`, etc. + + Dibujo y edición .[#toc-drawing-and-editing] ============================================ -Puedes dibujar, puedes escribir, puedes usar todas las funciones PHP para trabajar con imágenes, como [imagefilledellipse() |https://www.php.net/manual/en/function.imagefilledellipse.php], pero usando el estilo objeto: +Puedes dibujar, puedes escribir, puedes usar todas las funciones PHP para la manipulación de imágenes, ver [Resumen de métodos |#Overview of methods], pero en una envoltura orientada a objetos: ```php -$image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63)); +$image->filledEllipse($centerX, $centerY, $width, $height, ImageColor::rgb(255, 0, 0)); ``` -Véase el [resumen de métodos |#Overview of Methods]. +Dado que las funciones PHP para dibujar rectángulos son poco prácticas debido a la especificación de coordenadas, la clase `Image` ofrece sus sustitutos en forma de funciones [rectangleWH() |#rectangleWH()] y [filledRectangleWH() |#filledRectangleWH()]. Fusionar varias imágenes .[#toc-merge-multiple-images] @@ -210,7 +231,7 @@ Puedes colocar fácilmente otra imagen dentro de la imagen: ```php $logo = Image::fromFile('logo.png'); -$blank = Image::fromBlank(320, 240, Image::rgb(52, 132, 210)); +$blank = Image::fromBlank(320, 240, ImageColor::rgb(52, 132, 210)); // coordinates can be set also in percentage $blank->place($logo, '80%', '80%'); // near the right bottom corner @@ -229,8 +250,8 @@ Métodos .[#toc-overview-of-methods] =================================== -static fromBlank(int $width, int $height, array $color=null): Image .[method] ------------------------------------------------------------------------------ +static fromBlank(int $width, int $height, ImageColor $color=null): Image .[method] +---------------------------------------------------------------------------------- Crea una nueva imagen en color verdadero de las dimensiones dadas. El color por defecto es el negro. @@ -244,9 +265,9 @@ static fromString(string $s, int &$detectedFormat=null): Image .[method] Lee una imagen de una cadena y devuelve su [tipo |#Formats] en `$detectedFormat`. -static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method] ---------------------------------------------------------------------------------- -Crea un color que puede utilizarse en otros métodos, como `ellipse()`, `fill()`, etc. +static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated] +--------------------------------------------------------------------------------------------- +Esta función ha sido sustituida por la clase `ImageColor`, ver [colores |#Colors]. static typeToExtension(int $type): string .[method] @@ -279,6 +300,11 @@ static isTypeSupported(int $type): bool .[method] Determina si el [tipo de |#Formats] imagen dado es compatible. +static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method] +------------------------------------------------------------------------------------------------------------------------ +Calcula las dimensiones del rectángulo que encierra el texto en una fuente y tamaño especificados. Devuelve una matriz asociativa que contiene las claves `left`, `top`, `width`, `height`. El margen izquierdo puede ser negativo si el texto comienza con un saliente a la izquierda. + + affine(array $affine, array $clip=null): Image .[method] -------------------------------------------------------- Devuelve una imagen que contiene la imagen src transformada afinadamente, utilizando un área de recorte opcional. ([más |https://www.php.net/manual/en/function.imageaffine]). @@ -306,21 +332,11 @@ Activa los métodos de dibujo rápido antialiasing para líneas y polígonos al El uso de primitivas con antialiasing y color de fondo transparente puede dar lugar a resultados inesperados. El método de mezcla utiliza el color de fondo como cualquier otro color. La falta de soporte de componentes alfa no permite un método de antialiasing basado en alfa. ([más |https://www.php.net/manual/en/function.imageantialias]) -arc(int $x, int $y, int $w, int $h, int $start, int $end, int $color): void .[method] -------------------------------------------------------------------------------------- +arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color): void .[method] +--------------------------------------------------------------------------------------------------------------------------- Dibuja un arco de círculo centrado en las coordenadas dadas. ([más |https://www.php.net/manual/en/function.imagearc]) -char(int $font, int $x, int $y, string $char, int $color): void .[method] -------------------------------------------------------------------------- -Dibuja el primer carácter de `$char` en la imagen con su parte superior izquierda en `$x`,`$y` (la parte superior izquierda es 0, 0) con el color `$color`. ([más |https://www.php.net/manual/en/function.imagechar]) - - -charUp(int $font, int $x, int $y, string $char, int $color): void .[method] ---------------------------------------------------------------------------- -Dibuja el carácter `$char` verticalmente en la coordenada especificada en la imagen dada. ([más |https://www.php.net/manual/en/function.imagecharup]) - - colorAllocate(int $red, int $green, int $blue): int .[method] ------------------------------------------------------------- Devuelve un identificador de color que representa el color compuesto por los componentes RGB dados. Debe llamarse para crear cada color que se vaya a utilizar en la imagen. ([más |https://www.php.net/manual/en/function.imagecolorallocate]) @@ -447,43 +463,48 @@ crop(int|string $left, int|string $top, int|string $width, int|string $height): Recorta una imagen en el área rectangular dada. Las dimensiones pueden pasarse como números enteros en píxeles o cadenas en porcentaje (es decir, `'50%'`). -cropAuto(int $mode=-1, float $threshold=.5, int $color=-1): Image .[method] ---------------------------------------------------------------------------- +cropAuto(int $mode=-1, float $threshold=.5, ?ImageColor $color=null): Image .[method] +------------------------------------------------------------------------------------- Recorta automáticamente una imagen según la dirección `$mode`. ([más |https://www.php.net/manual/en/function.imagecropauto]) -ellipse(int $cx, int $cy, int $w, int $h, int $color): void .[method] ---------------------------------------------------------------------- +ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method] +----------------------------------------------------------------------------------------------- Dibuja una elipse centrada en las coordenadas especificadas. ([más |https://www.php.net/manual/en/function.imageellipse]) -fill(int $x, int $y, int $color): void .[method] ------------------------------------------------- +fill(int $x, int $y, ImageColor $color): void .[method] +------------------------------------------------------- Realiza un relleno de inundación comenzando en la coordenada dada (arriba a la izquierda es 0, 0) con el `$color` dado en la imagen. ([más |https://www.php.net/manual/en/function.imagefill]) -filledArc(int $cx, int $cy, int $w, int $h, int $s, int $e, int $color, int $style): void .[method] ---------------------------------------------------------------------------------------------------- +filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style): void .[method] +--------------------------------------------------------------------------------------------------------------------------------------------- Dibuja un arco parcial centrado en la coordenada especificada en la imagen. ([más |https://www.php.net/manual/en/function.imagefilledarc]) -filledEllipse(int $cx, int $cy, int $w, int $h, int $color): void .[method] ---------------------------------------------------------------------------- +filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method] +----------------------------------------------------------------------------------------------------- Dibuja una elipse centrada en la coordenada especificada en la imagen. ([más |https://www.php.net/manual/en/function.imagefilledellipse]) -filledPolygon(array $points, int $numPoints, int $color): void .[method] ------------------------------------------------------------------------- +filledPolygon(array $points, ImageColor $color): void .[method] +--------------------------------------------------------------- Crea un polígono relleno en la $imagen. ([más |https://www.php.net/manual/en/function.imagefilledpolygon]) -filledRectangle(int $x1, int $y1, int $x2, int $y2, int $color): void .[method] -------------------------------------------------------------------------------- -Crea un rectángulo relleno con `$color` en la imagen comenzando en el punto 1 y terminando en el punto 2. 0, 0 es la esquina superior izquierda de la imagen. ([más |https://www.php.net/manual/en/function.imagefilledrectangle]) +filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------- +Crea un rectángulo relleno con `$color` en la imagen comenzando en `$x1` & `$y1` y terminando en `$x2` & `$y2`. El punto 0, 0 es la esquina superior izquierda de la imagen. ([más |https://www.php.net/manual/en/function.imagefilledrectangle]) -fillToBorder(int $x, int $y, int $border, int $color): void .[method] ---------------------------------------------------------------------- +filledRectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------------------- +Crea un rectángulo relleno de `$color` en la imagen a partir del punto `$left` & `$top` con anchura `$width` y altura `$height`. El punto 0, 0 es la esquina superior izquierda de la imagen. + + +fillToBorder(int $x, int $y, int $border, ImageColor $color): void .[method] +---------------------------------------------------------------------------- Realiza un relleno de inundación cuyo color de borde está definido por `$border`. El punto de partida del relleno es `$x`, `$y` (arriba a la izquierda es 0, 0) y la región se rellena con el color `$color`. ([más |https://www.php.net/manual/en/function.imagefilltoborder]) @@ -497,9 +518,9 @@ flip(int $mode): void .[method] Voltea la imagen utilizando la dirección `$mode`. ([más |https://www.php.net/manual/en/function.imageflip]) -ftText(int $size, int $angle, int $x, int $y, int $col, string $fontFile, string $text, array $extrainfo=null): array .[method] -------------------------------------------------------------------------------------------------------------------------------- -Escribe texto en la imagen utilizando fuentes con FreeType 2. ([más |https://www.php.net/manual/en/function.imagefttext]) +ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method] +---------------------------------------------------------------------------------------------------------------------------------------- +Escribe el texto de la imagen. ([más |https://www.php.net/manual/en/function.imagefttext]) gammaCorrect(float $inputgamma, float $outputgamma): void .[method] @@ -542,13 +563,13 @@ layerEffect(int $effect): void .[method] Establezca la bandera de mezcla alfa para utilizar efectos de estratificación. ([más |https://www.php.net/manual/en/function.imagelayereffect]) -line(int $x1, int $y1, int $x2, int $y2, int $color): void .[method] --------------------------------------------------------------------- +line(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +--------------------------------------------------------------------------- Dibuja una línea entre los dos puntos dados. ([más |https://www.php.net/manual/en/function.imageline]) -openPolygon(array $points, int $numPoints, int $color): void .[method] ----------------------------------------------------------------------- +openPolygon(array $points, ImageColor $color): void .[method] +------------------------------------------------------------- Dibuja un polígono abierto en la imagen. Contrariamente a `polygon()`, no se traza ninguna línea entre el último y el primer punto. ([más |https://www.php.net/manual/en/function.imageopenpolygon]) @@ -567,16 +588,21 @@ place(Image $image, int|string $left=0, int|string $top=0, int $opacity=100): Im Copia `$image` en la imagen en las coordenadas `$left` y `$top`. Las coordenadas pueden pasarse como números enteros en píxeles o cadenas en porcentaje (es decir, `'50%'`). -polygon(array $points, int $numPoints, int $color): void .[method] ------------------------------------------------------------------- +polygon(array $points, ImageColor $color): void .[method] +--------------------------------------------------------- Crea un polígono en la imagen. ([más |https://www.php.net/manual/en/function.imagepolygon]) -rectangle(int $x1, int $y1, int $x2, int $y2, int $col): void .[method] ------------------------------------------------------------------------ +rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +-------------------------------------------------------------------------------- Crea un rectángulo que comienza en las coordenadas especificadas. ([más |https://www.php.net/manual/en/function.imagerectangle]) +rectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------------- +Crea un rectángulo en las coordenadas dadas. + + resize(int|string $width, int|string $height, int $flags=Image::OrSmaller): Image .[method] ------------------------------------------------------------------------------------------- Escala una imagen, ver [más info |#Image Resize]. Las dimensiones pueden pasarse como números enteros en píxeles o cadenas en porcentaje (es decir, `'50%'`). @@ -638,8 +664,8 @@ setInterpolation(int $method=IMG_BILINEAR_FIXED): void .[method] Establece el método de interpolación que afecta a los métodos `rotate()` y `affine()`. ([más |https://www.php.net/manual/en/function.imagesetinterpolation]) -setPixel(int $x, int $y, int $color): void .[method] ----------------------------------------------------- +setPixel(int $x, int $y, ImageColor $color): void .[method] +----------------------------------------------------------- Dibuja un píxel en la coordenada especificada. ([más |https://www.php.net/manual/en/function.imagesetpixel]) @@ -668,16 +694,6 @@ Enfoca un poco la imagen. Requiere la extensión *Bundled GD*, por lo que no es seguro que funcione en todas partes. -string(int $font, int $x, int $y, string $str, int $col): void .[method] ------------------------------------------------------------------------- -Dibuja una cadena en las coordenadas dadas. ([más |https://www.php.net/manual/en/function.imagestring]) - - -stringUp(int $font, int $x, int $y, string $s, int $col): void .[method] ------------------------------------------------------------------------- -Dibuja una cadena verticalmente en las coordenadas dadas. ([más |https://www.php.net/manual/en/function.imagestringup]) - - toString(int $type=ImageType::JPEG, int $quality=null): string .[method] ------------------------------------------------------------------------ Muestra una imagen en una cadena. @@ -690,6 +706,6 @@ trueColorToPalette(bool $dither, int $ncolors): void .[method] Convierte una imagen truecolor en una imagen de paleta. ([más |https://www.php.net/manual/en/function.imagetruecolortopalette]) -ttfText(int $size, int $angle, int $x, int $y, int $color, string $fontfile, string $text): array .[method] ------------------------------------------------------------------------------------------------------------ -Escribe el texto dado en la imagen utilizando fuentes TrueType. ([más |https://www.php.net/manual/en/function.imagettftext]) +ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method] +----------------------------------------------------------------------------------------------------------------------------------------- +Escribe el texto dado en la imagen. ([más |https://www.php.net/manual/en/function.imagettftext]) diff --git a/utils/fr/images.texy b/utils/fr/images.texy index 2ec50576cf..293f68cb22 100644 --- a/utils/fr/images.texy +++ b/utils/fr/images.texy @@ -17,6 +17,7 @@ Les exemples suivants supposent que l'alias de classe suivant est défini : ```php use Nette\Utils\Image; +use Nette\Utils\ImageColor; use Nette\Utils\ImageType; ``` @@ -33,7 +34,7 @@ $image = Image::fromBlank(100, 200); En option, vous pouvez spécifier une couleur de fond (noir par défaut) : ```php -$image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0)); +$image = Image::fromBlank(100, 200, ImageColor::rgb(125, 0, 0)); ``` Ou nous chargeons l'image depuis un fichier : @@ -191,16 +192,36 @@ $image->cropAuto(IMG_CROP_BLACK); La méthode `cropAuto()` est une encapsulation objet de la fonction `imagecropauto()`, voir [sa documentation |https://www.php.net/manual/en/function.imagecropauto] pour plus d'informations. +Couleurs .[#toc-colors] +======================= + +La méthode `ImageColor::rgb()` permet de définir une couleur à l'aide des valeurs rouge, vert et bleu (RVB). En option, vous pouvez également spécifier une valeur de transparence allant de 0 (complètement transparent) à 1 (complètement opaque), comme dans les CSS. + +```php +$color = ImageColor::rgb(255, 0, 0); // Red +$transparentBlue = ImageColor::rgb(0, 0, 255, 0.5); // Semi-transparent blue +``` + +La méthode `ImageColor::hex()` vous permet de définir une couleur en utilisant le format hexadécimal, comme dans CSS. Elle prend en charge les formats `#rgb`, `#rrggbb`, `#rgba`, et `#rrggbbaa`: + +```php +$color = ImageColor::hex("#F00"); // Red +$transparentGreen = ImageColor::hex("#00FF0080"); // Semi-transparent green +``` + +Les couleurs peuvent être utilisées dans d'autres méthodes, telles que `ellipse()`, `fill()`, etc. + + Dessin et édition .[#toc-drawing-and-editing] ============================================= -Vous pouvez dessiner, vous pouvez écrire, vous pouvez utiliser toutes les fonctions PHP pour travailler avec des images, comme [imagefilledellipse() |https://www.php.net/manual/en/function.imagefilledellipse.php], mais en utilisant le style objet : +Vous pouvez dessiner, vous pouvez écrire, vous pouvez utiliser toutes les fonctions PHP pour la manipulation d'images, voir [Aperçu des méthodes |#Overview of methods], mais dans une enveloppe orientée objet : ```php -$image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63)); +$image->filledEllipse($centerX, $centerY, $width, $height, ImageColor::rgb(255, 0, 0)); ``` -Voir l'[aperçu des méthodes |#Overview of Methods]. +Puisque les fonctions PHP pour dessiner des rectangles ne sont pas pratiques en raison de la spécification des coordonnées, la classe `Image` offre leurs remplacements sous la forme de fonctions [rectangleWH() |#rectangleWH()] et [filledRectangleWH() |#filledRectangleWH()]. Fusionner plusieurs images .[#toc-merge-multiple-images] @@ -210,7 +231,7 @@ Vous pouvez facilement placer une autre image dans l'image : ```php $logo = Image::fromFile('logo.png'); -$blank = Image::fromBlank(320, 240, Image::rgb(52, 132, 210)); +$blank = Image::fromBlank(320, 240, ImageColor::rgb(52, 132, 210)); // les coordonnées peuvent également être définies en pourcentage $blank->place($logo, '80%', '80%'); // près du coin inférieur droit de l'image @@ -229,8 +250,8 @@ Aperçu des méthodes .[#toc-overview-of-methods] =============================================== -static fromBlank(int $width, int $height, array $color=null): Image .[method] ------------------------------------------------------------------------------ +static fromBlank(int $width, int $height, ImageColor $color=null): Image .[method] +---------------------------------------------------------------------------------- Crée une nouvelle image en couleurs réelles avec les dimensions données. La couleur par défaut est le noir. @@ -244,9 +265,9 @@ static fromString(string $s, int &$detectedFormat=null): Image .[method] Lit une image à partir d'une chaîne de caractères et renvoie son [type |#Formats] à `$detectedFormat`. -static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method] ---------------------------------------------------------------------------------- -Crée une couleur qui peut être utilisée dans d'autres méthodes, telles que `ellipse()`, `fill()`, etc. +static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated] +--------------------------------------------------------------------------------------------- +Cette fonctionnalité a été remplacée par la classe `ImageColor`, voir les [couleurs |#Colors]. static typeToExtension(int $type): string .[method] @@ -279,6 +300,11 @@ static isTypeSupported(int $type): bool .[method] Détermine si le [type d' |#Formats] image donné est pris en charge. +static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method] +------------------------------------------------------------------------------------------------------------------------ +Calcule les dimensions du rectangle qui entoure le texte d'une police et d'une taille spécifiées. Il renvoie un tableau associatif contenant les clés `left`, `top`, `width`, `height`. La marge de gauche peut être négative si le texte commence avec un débordement à gauche. + + affine(array $affine, array $clip=null): Image .[method] -------------------------------------------------------- Renvoie une image contenant l'image src transformée affine, en utilisant une zone de découpage optionnelle. ([plus |https://www.php.net/manual/en/function.imageaffine]). @@ -306,21 +332,11 @@ Activez les méthodes de dessin rapide avec anticrénelage pour les lignes et le L'utilisation de primitives anticrénelées avec une couleur de fond transparente peut donner des résultats inattendus. La méthode de fusion utilise la couleur de fond comme n'importe quelle autre couleur. L'absence de prise en charge de la composante alpha ne permet pas d'utiliser une méthode d'anticrénelage basée sur l'alpha. ([plus |https://www.php.net/manual/en/function.imageantialias]) -arc(int $x, int $y, int $w, int $h, int $start, int $end, int $color): void .[method] -------------------------------------------------------------------------------------- +arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color): void .[method] +--------------------------------------------------------------------------------------------------------------------------- Dessine un arc de cercle centré sur les coordonnées données. ([plus |https://www.php.net/manual/en/function.imagearc]) -char(int $font, int $x, int $y, string $char, int $color): void .[method] -------------------------------------------------------------------------- -Dessine le premier caractère de `$char` dans l'image avec son haut gauche à `$x`,`$y` (haut gauche est 0, 0) avec la couleur `$color`. ([plus |https://www.php.net/manual/en/function.imagechar]) - - -charUp(int $font, int $x, int $y, string $char, int $color): void .[method] ---------------------------------------------------------------------------- -Dessine le caractère `$char` verticalement à la coordonnée spécifiée sur l'image donnée. ([plus |https://www.php.net/manual/en/function.imagecharup]) - - colorAllocate(int $red, int $green, int $blue): int .[method] ------------------------------------------------------------- Renvoie un identifiant de couleur représentant la couleur composée des composantes RVB données. Elle doit être appelée pour créer chaque couleur qui doit être utilisée dans l'image. ([plus |https://www.php.net/manual/en/function.imagecolorallocate]) @@ -447,43 +463,48 @@ crop(int|string $left, int|string $top, int|string $width, int|string $height): Recadrer une image dans une zone rectangulaire donnée. Les dimensions peuvent être transmises sous forme d'entiers en pixels ou de chaînes de caractères en pourcentage (par exemple, `'50%'`). -cropAuto(int $mode=-1, float $threshold=.5, int $color=-1): Image .[method] ---------------------------------------------------------------------------- +cropAuto(int $mode=-1, float $threshold=.5, ?ImageColor $color=null): Image .[method] +------------------------------------------------------------------------------------- Recadrage automatique d'une image en fonction de l'adresse `$mode`. ([plus |https://www.php.net/manual/en/function.imagecropauto]) -ellipse(int $cx, int $cy, int $w, int $h, int $color): void .[method] ---------------------------------------------------------------------- +ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method] +----------------------------------------------------------------------------------------------- Dessine une ellipse centrée sur les coordonnées spécifiées. ([plus |https://www.php.net/manual/en/function.imageellipse]) -fill(int $x, int $y, int $color): void .[method] ------------------------------------------------- +fill(int $x, int $y, ImageColor $color): void .[method] +------------------------------------------------------- Effectue un remplissage par inondation à partir de la coordonnée donnée (en haut à gauche, c'est 0, 0) avec le `$color` donné dans l'image. ([plus |https://www.php.net/manual/en/function.imagefill]) -filledArc(int $cx, int $cy, int $w, int $h, int $s, int $e, int $color, int $style): void .[method] ---------------------------------------------------------------------------------------------------- +filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style): void .[method] +--------------------------------------------------------------------------------------------------------------------------------------------- Dessine un arc partiel centré sur la coordonnée spécifiée dans l'image. ([plus |https://www.php.net/manual/en/function.imagefilledarc]) -filledEllipse(int $cx, int $cy, int $w, int $h, int $color): void .[method] ---------------------------------------------------------------------------- +filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method] +----------------------------------------------------------------------------------------------------- Dessine une ellipse centrée sur la coordonnée spécifiée dans l'image. ([plus |https://www.php.net/manual/en/function.imagefilledellipse]) -filledPolygon(array $points, int $numPoints, int $color): void .[method] ------------------------------------------------------------------------- +filledPolygon(array $points, ImageColor $color): void .[method] +--------------------------------------------------------------- Crée un polygone rempli dans l'image $. ([plus |https://www.php.net/manual/en/function.imagefilledpolygon]) -filledRectangle(int $x1, int $y1, int $x2, int $y2, int $color): void .[method] -------------------------------------------------------------------------------- -Crée un rectangle rempli de `$color` dans l'image en commençant au point 1 et en terminant au point 2. 0, 0 est le coin supérieur gauche de l'image. ([plus |https://www.php.net/manual/en/function.imagefilledrectangle]) +filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------- +Crée un rectangle rempli de `$color` dans l'image commençant à `$x1` & `$y1` et se terminant à `$x2` & `$y2`. Le point 0, 0 est le coin supérieur gauche de l'image. ([plus |https://www.php.net/manual/en/function.imagefilledrectangle]) -fillToBorder(int $x, int $y, int $border, int $color): void .[method] ---------------------------------------------------------------------- +filledRectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------------------- +Crée un rectangle rempli de `$color` dans l'image à partir des points `$left` & `$top` avec la largeur `$width` et la hauteur `$height`. Le point 0, 0 est le coin supérieur gauche de l'image. + + +fillToBorder(int $x, int $y, int $border, ImageColor $color): void .[method] +---------------------------------------------------------------------------- Effectue un remplissage par inondation dont la couleur de la bordure est définie par `$border`. Le point de départ du remplissage est `$x`, `$y` (en haut à gauche, 0, 0) et la région est remplie de la couleur `$color`. ([plus |https://www.php.net/manual/en/function.imagefilltoborder]) @@ -497,9 +518,9 @@ flip(int $mode): void .[method] Retourne l'image en utilisant l'adresse `$mode`. ([plus |https://www.php.net/manual/en/function.imageflip]) -ftText(int $size, int $angle, int $x, int $y, int $col, string $fontFile, string $text, array $extrainfo=null): array .[method] -------------------------------------------------------------------------------------------------------------------------------- -Écrivez du texte sur l'image à l'aide de polices de caractères utilisant FreeType 2. ([plus |https://www.php.net/manual/en/function.imagefttext]) +ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method] +---------------------------------------------------------------------------------------------------------------------------------------- +Écrivez le texte dans l'image. ([plus |https://www.php.net/manual/en/function.imagefttext]) gammaCorrect(float $inputgamma, float $outputgamma): void .[method] @@ -542,13 +563,13 @@ layerEffect(int $effect): void .[method] Définissez le drapeau de mélange alpha pour utiliser les effets de superposition. ([plus |https://www.php.net/manual/en/function.imagelayereffect]) -line(int $x1, int $y1, int $x2, int $y2, int $color): void .[method] --------------------------------------------------------------------- +line(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +--------------------------------------------------------------------------- Trace une ligne entre les deux points donnés. ([plus |https://www.php.net/manual/en/function.imageline]) -openPolygon(array $points, int $numPoints, int $color): void .[method] ----------------------------------------------------------------------- +openPolygon(array $points, ImageColor $color): void .[method] +------------------------------------------------------------- Dessine un polygone ouvert sur l'image. Contrairement à `polygon()`, aucune ligne n'est tracée entre le dernier et le premier point. ([plus |https://www.php.net/manual/en/function.imageopenpolygon]) @@ -567,16 +588,21 @@ place(Image $image, int|string $left=0, int|string $top=0, int $opacity=100): Im Copie `$image` sur l'image aux coordonnées `$left` et `$top`. Les coordonnées peuvent être transmises sous forme d'entiers en pixels ou de chaînes de caractères en pourcentage (par exemple `'50%'`). -polygon(array $points, int $numPoints, int $color): void .[method] ------------------------------------------------------------------- +polygon(array $points, ImageColor $color): void .[method] +--------------------------------------------------------- Crée un polygone dans l'image. ([plus |https://www.php.net/manual/en/function.imagepolygon]) -rectangle(int $x1, int $y1, int $x2, int $y2, int $col): void .[method] ------------------------------------------------------------------------ +rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +-------------------------------------------------------------------------------- Crée un rectangle à partir des coordonnées spécifiées. ([plus |https://www.php.net/manual/en/function.imagerectangle]) +rectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------------- +Crée un rectangle aux coordonnées données. + + resize(int|string $width, int|string $height, int $flags=Image::OrSmaller): Image .[method] ------------------------------------------------------------------------------------------- Mise à l'échelle d'une image, voir [plus d'infos |#Image Resize]. Les dimensions peuvent être transmises sous forme d'entiers en pixels ou de chaînes de caractères en pourcentage (par exemple, `'50%'`). @@ -638,8 +664,8 @@ setInterpolation(int $method=IMG_BILINEAR_FIXED): void .[method] Définit la méthode d'interpolation qui affecte les méthodes `rotate()` et `affine()`. ([plus |https://www.php.net/manual/en/function.imagesetinterpolation]) -setPixel(int $x, int $y, int $color): void .[method] ----------------------------------------------------- +setPixel(int $x, int $y, ImageColor $color): void .[method] +----------------------------------------------------------- Dessine un pixel à la coordonnée spécifiée. ([plus |https://www.php.net/manual/en/function.imagesetpixel]) @@ -668,16 +694,6 @@ Affine un peu l'image. Nécessite l'extension *Bundled GD*, il n'est donc pas sûr que cela fonctionne partout. -string(int $font, int $x, int $y, string $str, int $col): void .[method] ------------------------------------------------------------------------- -Dessine une chaîne aux coordonnées données. ([plus |https://www.php.net/manual/en/function.imagestring]) - - -stringUp(int $font, int $x, int $y, string $s, int $col): void .[method] ------------------------------------------------------------------------- -Dessine une chaîne verticalement aux coordonnées données. ([plus |https://www.php.net/manual/en/function.imagestringup]) - - toString(int $type=ImageType::JPEG, int $quality=null): string .[method] ------------------------------------------------------------------------ Produit une image sous forme de chaîne. @@ -690,6 +706,6 @@ trueColorToPalette(bool $dither, int $ncolors): void .[method] Convertit une image truecolor en une image palette. ([plus |https://www.php.net/manual/en/function.imagetruecolortopalette]) -ttfText(int $size, int $angle, int $x, int $y, int $color, string $fontfile, string $text): array .[method] ------------------------------------------------------------------------------------------------------------ -Écrit le texte donné dans l'image en utilisant les polices TrueType. ([plus |https://www.php.net/manual/en/function.imagettftext]) +ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method] +----------------------------------------------------------------------------------------------------------------------------------------- +Écrit le texte donné dans l'image. ([plus |https://www.php.net/manual/en/function.imagettftext]) diff --git a/utils/hu/images.texy b/utils/hu/images.texy index cbd13836c8..7c8be60c3b 100644 --- a/utils/hu/images.texy +++ b/utils/hu/images.texy @@ -17,6 +17,7 @@ A következő példák feltételezik, hogy a következő osztály alias van defi ```php use Nette\Utils\Image; +use Nette\Utils\ImageColor; use Nette\Utils\ImageType; ``` @@ -33,7 +34,7 @@ $image = Image::fromBlank(100, 200); Opcionálisan megadhat egy háttérszínt (alapértelmezett a fekete): ```php -$image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0)); +$image = Image::fromBlank(100, 200, ImageColor::rgb(125, 0, 0)); ``` Vagy betöltjük a képet egy fájlból: @@ -191,16 +192,36 @@ $image->cropAuto(IMG_CROP_BLACK); A `cropAuto()` metódus a `imagecropauto()` függvény objektumkapszulázása, további információkért lásd [a dokumentációját |https://www.php.net/manual/en/function.imagecropauto]. +Színek .[#toc-colors] +===================== + +A `ImageColor::rgb()` módszer lehetővé teszi a színek meghatározását a vörös, zöld és kék (RGB) értékek segítségével. Opcionálisan egy átlátszósági értéket is megadhat 0 (teljesen átlátszó) és 1 (teljesen átlátszatlan) között, akárcsak a CSS-ben. + +```php +$color = ImageColor::rgb(255, 0, 0); // Red +$transparentBlue = ImageColor::rgb(0, 0, 255, 0.5); // Semi-transparent blue +``` + +A `ImageColor::hex()` módszerrel a CSS-hez hasonlóan hexadecimális formátumban adhat meg egy színt. Támogatja a `#rgb`, `#rrggbb`, `#rgba` és `#rrggbbaa` formátumokat: + +```php +$color = ImageColor::hex("#F00"); // Red +$transparentGreen = ImageColor::hex("#00FF0080"); // Semi-transparent green +``` + +A színeket más módszerekben is lehet használni, mint például a `ellipse()`, `fill()`, stb. + + Rajzolás és szerkesztés .[#toc-drawing-and-editing] =================================================== -Rajzolhatsz, írhatsz, használhatod az összes PHP függvényt a képekkel való munkához, mint például az [imagefilledellipse() |https://www.php.net/manual/en/function.imagefilledellipse.php], de objektum stílusban: +Rajzolhatsz, írhatsz, használhatod az összes PHP függvényt a képmanipulációhoz, lásd: [A módszerek áttekintése |#Overview of methods], de egy objektumorientált burkolatban: ```php -$image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63)); +$image->filledEllipse($centerX, $centerY, $width, $height, ImageColor::rgb(255, 0, 0)); ``` -Lásd [a módszerek áttekintését |#Overview of Methods]. +Mivel a téglalapok rajzolására szolgáló PHP függvények a koordináták megadása miatt nem praktikusak, a `Image` osztály a [rectangleWH() |#rectangleWH()] és a [filledRectangleWH() |#filledRectangleWH()] függvények formájában helyettesíti őket. Több kép egyesítése .[#toc-merge-multiple-images] @@ -210,7 +231,7 @@ Könnyedén elhelyezhet egy másik képet a képbe: ```php $logo = Image::fromFile('logo.png'); -$blank = Image::fromBlank(320, 240, Image::rgb(52, 132, 210)); +$blank = Image::fromBlank(320, 240, ImageColor::rgb(52, 132, 210)); // a koordináták százalékban is megadhatók $blank->place($logo, '80%', '80%'); // közel a jobb alsó sarokhoz @@ -229,8 +250,8 @@ A módszerek áttekintése .[#toc-overview-of-methods] =================================================== -static fromBlank(int $width, int $height, array $color=null): Image .[method] ------------------------------------------------------------------------------ +static fromBlank(int $width, int $height, ImageColor $color=null): Image .[method] +---------------------------------------------------------------------------------- Új, valós színű képet hoz létre a megadott méretekkel. Az alapértelmezett szín a fekete. @@ -244,9 +265,9 @@ static fromString(string $s, int &$detectedFormat=null): Image .[method] Beolvas egy képet egy karakterláncból, és visszaadja [a típusát |#Formats] a `$detectedFormat` címen. -static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method] ---------------------------------------------------------------------------------- -Létrehoz egy színt, amely más módszerekben, például a `ellipse()`, `fill()`, stb. használható. +static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated] +--------------------------------------------------------------------------------------------- +Ezt a funkciót a `ImageColor` osztály váltotta fel, lásd a [színeket |#Colors]. static typeToExtension(int $type): string .[method] @@ -279,6 +300,11 @@ static isTypeSupported(int $type): bool .[method] Megállapítja, hogy az adott [képtípus |#Formats] támogatott-e. +static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method] +------------------------------------------------------------------------------------------------------------------------ +Kiszámítja a megadott betűtípusú és méretű szöveget körülvevő téglalap méreteit. Egy asszociatív tömböt ad vissza, amely a `left`, `top`, `width`, `height` kulcsokat tartalmazza. A bal oldali margó negatív lehet, ha a szöveg bal oldali túlnyúlással kezdődik. + + affine(array $affine, array $clip=null): Image .[method] -------------------------------------------------------- Visszaad egy képet, amely az affin transzformált src képet tartalmazza, egy opcionális vágási terület használatával. ([tovább |https://www.php.net/manual/en/function.imageaffine]). @@ -306,21 +332,11 @@ Aktiválja a gyors rajzolás antializált módszereit a vonalak és a vezetékes Az antialiased primitívek átlátszó háttérszínnel történő használata nem várt eredményekkel járhat. A keverési módszer a háttérszínt ugyanúgy használja, mint bármely más színt. Az alfa komponens támogatás hiánya nem teszi lehetővé az alfa alapú antialiasing módszert. ([tovább |https://www.php.net/manual/en/function.imageantialias]) -arc(int $x, int $y, int $w, int $h, int $start, int $end, int $color): void .[method] -------------------------------------------------------------------------------------- +arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color): void .[method] +--------------------------------------------------------------------------------------------------------------------------- A megadott koordináták középpontjában lévő körív rajzolása. ([tovább |https://www.php.net/manual/en/function.imagearc]) -char(int $font, int $x, int $y, string $char, int $color): void .[method] -------------------------------------------------------------------------- -A `$char` első karakterét a képen a `$x`,`$y` (a bal felső rész 0, 0) színnel rajzolja meg a `$color` színnel a első karakterét. ([tovább |https://www.php.net/manual/en/function.imagechar]) - - -charUp(int $font, int $x, int $y, string $char, int $color): void .[method] ---------------------------------------------------------------------------- -A `$char` karaktert függőlegesen rajzolja a megadott koordinátán a megadott képen. ([tovább |https://www.php.net/manual/en/function.imagecharup]) - - colorAllocate(int $red, int $green, int $blue): int .[method] ------------------------------------------------------------- Visszaad egy színazonosítót, amely a megadott RGB-komponensekből álló színt reprezentálja. Minden egyes, a képen használni kívánt szín létrehozásához meg kell hívni. ([tovább |https://www.php.net/manual/en/function.imagecolorallocate]) @@ -447,43 +463,48 @@ crop(int|string $left, int|string $top, int|string $width, int|string $height): A képet a megadott téglalap alakú területre vágja. A méretek átadhatók egész számokként pixelben vagy karakterláncokként százalékban (pl. `'50%'`). -cropAuto(int $mode=-1, float $threshold=.5, int $color=-1): Image .[method] ---------------------------------------------------------------------------- +cropAuto(int $mode=-1, float $threshold=.5, ?ImageColor $color=null): Image .[method] +------------------------------------------------------------------------------------- Automatikusan levágja a képet a megadott `$mode` címnek megfelelően. ([tovább |https://www.php.net/manual/en/function.imagecropauto]) -ellipse(int $cx, int $cy, int $w, int $h, int $color): void .[method] ---------------------------------------------------------------------- +ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method] +----------------------------------------------------------------------------------------------- Egy ellipszist rajzol a megadott koordináták középpontjába. ([tovább |https://www.php.net/manual/en/function.imageellipse]) -fill(int $x, int $y, int $color): void .[method] ------------------------------------------------- +fill(int $x, int $y, ImageColor $color): void .[method] +------------------------------------------------------- A megadott koordinátánál (balra fent 0, 0) kezdődő áradásos kitöltést hajt végre a megadott `$color` címen a képen. ([tovább |https://www.php.net/manual/en/function.imagefill]) -filledArc(int $cx, int $cy, int $w, int $h, int $s, int $e, int $color, int $style): void .[method] ---------------------------------------------------------------------------------------------------- +filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style): void .[method] +--------------------------------------------------------------------------------------------------------------------------------------------- Egy részleges ívet rajzol, amelynek középpontja a kép megadott koordinátája. ([tovább |https://www.php.net/manual/en/function.imagefilledarc]) -filledEllipse(int $cx, int $cy, int $w, int $h, int $color): void .[method] ---------------------------------------------------------------------------- +filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method] +----------------------------------------------------------------------------------------------------- Egy ellipszist rajzol, amelynek középpontja a kép megadott koordinátája. ([tovább |https://www.php.net/manual/en/function.imagefilledellipse]) -filledPolygon(array $points, int $numPoints, int $color): void .[method] ------------------------------------------------------------------------- +filledPolygon(array $points, ImageColor $color): void .[method] +--------------------------------------------------------------- Egy kitöltött sokszöget hoz létre a $image-ben. ([tovább |https://www.php.net/manual/en/function.imagefilledpolygon]) -filledRectangle(int $x1, int $y1, int $x2, int $y2, int $color): void .[method] -------------------------------------------------------------------------------- -Egy téglalapot hoz létre a képen a `$color` címmel, amely az 1. pontban kezdődik és a 2. pontban végződik. 0, 0 a kép bal felső sarka. ([tovább |https://www.php.net/manual/en/function.imagefilledrectangle]) +filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------- +Egy téglalapot hoz létre a képen a `$color` címmel, amely a `$x1` és a `$y1` címen kezdődik és a `$x2` és a `$y2` címen végződik. 0, 0 pont a kép bal felső sarka. ([tovább |https://www.php.net/manual/en/function.imagefilledrectangle]) -fillToBorder(int $x, int $y, int $border, int $color): void .[method] ---------------------------------------------------------------------- +filledRectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------------------- +Létrehoz egy téglalapot, amely a `$color` képen a `$left` és a `$top` pontból kiindulva `$width` szélességű és `$height` magasságú téglalapot hoz létre. A 0,0 pont a kép bal felső sarka. + + +fillToBorder(int $x, int $y, int $border, ImageColor $color): void .[method] +---------------------------------------------------------------------------- Olyan áradásos kitöltést végez, amelynek határszínét a `$border` határozza meg. A kitöltés kezdőpontja a `$x`, `$y` (balra fent 0, 0), és a régiót a `$color` színnel töltjük ki. ([tovább |https://www.php.net/manual/en/function.imagefilltoborder]) @@ -497,9 +518,9 @@ flip(int $mode): void .[method] Megfordítja a képet a megadott `$mode` segítségével. ([tovább |https://www.php.net/manual/en/function.imageflip]) -ftText(int $size, int $angle, int $x, int $y, int $col, string $fontFile, string $text, array $extrainfo=null): array .[method] -------------------------------------------------------------------------------------------------------------------------------- -Írjon szöveget a képre a FreeType 2 betűtípusok segítségével. ([tovább |https://www.php.net/manual/en/function.imagefttext]) +ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method] +---------------------------------------------------------------------------------------------------------------------------------------- +Írja a képen látható szöveget. ([tovább |https://www.php.net/manual/en/function.imagefttext]) gammaCorrect(float $inputgamma, float $outputgamma): void .[method] @@ -542,13 +563,13 @@ layerEffect(int $effect): void .[method] Állítsa be az alpha blending flaget a réteghatások használatához. ([tovább |https://www.php.net/manual/en/function.imagelayereffect]) -line(int $x1, int $y1, int $x2, int $y2, int $color): void .[method] --------------------------------------------------------------------- +line(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +--------------------------------------------------------------------------- Vonalat húz a két megadott pont közé. ([tovább |https://www.php.net/manual/en/function.imageline]) -openPolygon(array $points, int $numPoints, int $color): void .[method] ----------------------------------------------------------------------- +openPolygon(array $points, ImageColor $color): void .[method] +------------------------------------------------------------- Egy nyitott sokszöget rajzol a képre. A `polygon()` címmel ellentétben az utolsó és az első pont között nem húzódik vonal. ([tovább |https://www.php.net/manual/en/function.imageopenpolygon]) @@ -567,16 +588,21 @@ place(Image $image, int|string $left=0, int|string $top=0, int $opacity=100): Im Másolja a `$image` címet a képre a `$left` és a `$top` koordinátáknál. A koordináták átadhatók egész számokként pixelben vagy karakterláncokként százalékban (pl. `'50%'`). -polygon(array $points, int $numPoints, int $color): void .[method] ------------------------------------------------------------------- +polygon(array $points, ImageColor $color): void .[method] +--------------------------------------------------------- Egy sokszöget hoz létre a képen. ([tovább |https://www.php.net/manual/en/function.imagepolygon]) -rectangle(int $x1, int $y1, int $x2, int $y2, int $col): void .[method] ------------------------------------------------------------------------ +rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +-------------------------------------------------------------------------------- A megadott koordinátáknál kezdődő téglalapot hoz létre. ([tovább |https://www.php.net/manual/en/function.imagerectangle]) +rectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------------- +Egy téglalapot hoz létre a megadott koordinátákon. + + resize(int|string $width, int|string $height, int $flags=Image::OrSmaller): Image .[method] ------------------------------------------------------------------------------------------- Méretezi a képet, [további információk |#Image Resize]. A méretek átadhatók egész számokként pixelben vagy karakterláncokként százalékban (pl. `'50%'`). @@ -638,8 +664,8 @@ setInterpolation(int $method=IMG_BILINEAR_FIXED): void .[method] Beállítja az interpolációs módszert, amely hatással van a `rotate()` és a `affine()` módszerekre. ([tovább |https://www.php.net/manual/en/function.imagesetinterpolation]) -setPixel(int $x, int $y, int $color): void .[method] ----------------------------------------------------- +setPixel(int $x, int $y, ImageColor $color): void .[method] +----------------------------------------------------------- Egy pixelt rajzol a megadott koordinátára. ([tovább |https://www.php.net/manual/en/function.imagesetpixel]) @@ -668,16 +694,6 @@ Egy kicsit élesíti a képet. Igényli a *Bundled GD kiterjesztést*, így nem biztos, hogy mindenhol működik. -string(int $font, int $x, int $y, string $str, int $col): void .[method] ------------------------------------------------------------------------- -Egy karakterláncot rajzol a megadott koordinátákhoz. ([tovább |https://www.php.net/manual/en/function.imagestring]) - - -stringUp(int $font, int $x, int $y, string $s, int $col): void .[method] ------------------------------------------------------------------------- -Egy sztringet rajzol függőlegesen a megadott koordinátákhoz. ([tovább |https://www.php.net/manual/en/function.imagestringup]) - - toString(int $type=ImageType::JPEG, int $quality=null): string .[method] ------------------------------------------------------------------------ Kimeneti képet ad ki stringként. @@ -690,6 +706,6 @@ trueColorToPalette(bool $dither, int $ncolors): void .[method] Egy valódi színű képet palettaképpé alakít át. ([tovább |https://www.php.net/manual/en/function.imagetruecolortopalette]) -ttfText(int $size, int $angle, int $x, int $y, int $color, string $fontfile, string $text): array .[method] ------------------------------------------------------------------------------------------------------------ -A megadott szöveget TrueType betűtípusok használatával írja a képbe. ([tovább |https://www.php.net/manual/en/function.imagettftext]) +ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method] +----------------------------------------------------------------------------------------------------------------------------------------- +A megadott szöveget írja a képbe. ([tovább |https://www.php.net/manual/en/function.imagettftext]) diff --git a/utils/it/images.texy b/utils/it/images.texy index fe8b6ec2c0..6db8f308cb 100644 --- a/utils/it/images.texy +++ b/utils/it/images.texy @@ -17,6 +17,7 @@ Gli esempi seguenti presuppongono che sia stato definito il seguente alias di cl ```php use Nette\Utils\Image; +use Nette\Utils\ImageColor; use Nette\Utils\ImageType; ``` @@ -33,7 +34,7 @@ $image = Image::fromBlank(100, 200); Opzionalmente, è possibile specificare un colore di sfondo (l'impostazione predefinita è il nero): ```php -$image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0)); +$image = Image::fromBlank(100, 200, ImageColor::rgb(125, 0, 0)); ``` Oppure si carica l'immagine da un file: @@ -191,16 +192,36 @@ $image->cropAuto(IMG_CROP_BLACK); Il metodo `cropAuto()` è un oggetto che incapsula la funzione `imagecropauto()`; per ulteriori informazioni, consultare la [relativa documentazione |https://www.php.net/manual/en/function.imagecropauto]. +Colori .[#toc-colors] +===================== + +Il metodo `ImageColor::rgb()` consente di definire un colore utilizzando i valori rosso, verde e blu (RGB). Opzionalmente, si può anche specificare un valore di trasparenza che va da 0 (completamente trasparente) a 1 (completamente opaco), proprio come nei CSS. + +```php +$color = ImageColor::rgb(255, 0, 0); // Red +$transparentBlue = ImageColor::rgb(0, 0, 255, 0.5); // Semi-transparent blue +``` + +Il metodo `ImageColor::hex()` consente di definire un colore utilizzando il formato esadecimale, come nei CSS. Supporta i formati `#rgb`, `#rrggbb`, `#rgba` e `#rrggbbaa`: + +```php +$color = ImageColor::hex("#F00"); // Red +$transparentGreen = ImageColor::hex("#00FF0080"); // Semi-transparent green +``` + +I colori possono essere utilizzati in altri metodi, come `ellipse()`, `fill()`, ecc. + + Disegno e modifica .[#toc-drawing-and-editing] ============================================== -Si può disegnare, si può scrivere, si possono usare tutte le funzioni PHP per lavorare con le immagini, come [imagefilledellipse() |https://www.php.net/manual/en/function.imagefilledellipse.php], ma utilizzando lo stile a oggetti: +Si può disegnare, si può scrivere, si possono usare tutte le funzioni PHP per la manipolazione delle immagini, vedi [Panoramica dei metodi |#Overview of methods], ma in un involucro orientato agli oggetti: ```php -$image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63)); +$image->filledEllipse($centerX, $centerY, $width, $height, ImageColor::rgb(255, 0, 0)); ``` -Vedere [Panoramica dei metodi |#Overview of Methods]. +Poiché le funzioni PHP per disegnare i rettangoli sono poco pratiche a causa della necessità di specificare le coordinate, la classe `Image` le sostituisce con le funzioni [rectangleWH() |#rectangleWH()] e [filledRectangleWH() |#filledRectangleWH()]. Unire più immagini .[#toc-merge-multiple-images] @@ -210,7 +231,7 @@ Unire più immagini .[#toc-merge-multiple-images] ```php $logo = Image::fromFile('logo.png'); -$blank = Image::fromBlank(320, 240, Image::rgb(52, 132, 210)); +$blank = Image::fromBlank(320, 240, ImageColor::rgb(52, 132, 210)); // le coordinate possono essere impostate anche in percentuale $blank->place($logo, '80%', '80%'); // vicino all'angolo destro in basso @@ -229,8 +250,8 @@ Panoramica dei metodi .[#toc-overview-of-methods] ================================================= -static fromBlank(int $width, int $height, array $color=null): Image .[method] ------------------------------------------------------------------------------ +static fromBlank(int $width, int $height, ImageColor $color=null): Image .[method] +---------------------------------------------------------------------------------- Crea una nuova immagine a colori reali delle dimensioni indicate. Il colore predefinito è il nero. @@ -244,9 +265,9 @@ static fromString(string $s, int &$detectedFormat=null): Image .[method] Legge un'immagine da una stringa e ne restituisce il [tipo |#Formats] in `$detectedFormat`. -static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method] ---------------------------------------------------------------------------------- -Crea un colore che può essere utilizzato in altri metodi, come `ellipse()`, `fill()`, e così via. +static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated] +--------------------------------------------------------------------------------------------- +Questa funzione è stata sostituita dalla classe `ImageColor`, vedi [colori |#Colors]. static typeToExtension(int $type): string .[method] @@ -279,6 +300,11 @@ static isTypeSupported(int $type): bool .[method] Determina se il [tipo di |#Formats] immagine dato è supportato. +static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method] +------------------------------------------------------------------------------------------------------------------------ +Calcola le dimensioni del rettangolo che racchiude il testo in un font e in una dimensione specificati. Restituisce un array associativo contenente le chiavi `left`, `top`, `width`, `height`. Il margine sinistro può essere negativo se il testo inizia con una sporgenza a sinistra. + + affine(array $affine, array $clip=null): Image .[method] -------------------------------------------------------- Restituisce un'immagine contenente l'immagine src trasformata affine, utilizzando un'area di ritaglio opzionale. ([altro |https://www.php.net/manual/en/function.imageaffine]). @@ -306,21 +332,11 @@ Attivare i metodi di disegno rapido antialias per linee e poligoni cablati. Non L'uso di primitive con antialias e colore di sfondo trasparente può portare a risultati inaspettati. Il metodo blend utilizza il colore di sfondo come qualsiasi altro colore. La mancanza del supporto per i componenti alfa non consente un metodo di antialiasing basato su alfa. ([altro |https://www.php.net/manual/en/function.imageantialias]) -arc(int $x, int $y, int $w, int $h, int $start, int $end, int $color): void .[method] -------------------------------------------------------------------------------------- +arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color): void .[method] +--------------------------------------------------------------------------------------------------------------------------- Disegna un arco di cerchio centrato sulle coordinate date. ([altro |https://www.php.net/manual/en/function.imagearc]) -char(int $font, int $x, int $y, string $char, int $color): void .[method] -------------------------------------------------------------------------- -Disegna il primo carattere di `$char` nell'immagine con la parte superiore sinistra a `$x`,`$y` (in alto a sinistra è 0, 0) con il colore `$color`. ([altro |https://www.php.net/manual/en/function.imagechar]) - - -charUp(int $font, int $x, int $y, string $char, int $color): void .[method] ---------------------------------------------------------------------------- -Disegna il carattere `$char` verticalmente alla coordinata specificata sull'immagine data. ([altro |https://www.php.net/manual/en/function.imagecharup]) - - colorAllocate(int $red, int $green, int $blue): int .[method] ------------------------------------------------------------- Restituisce un identificatore di colore che rappresenta il colore composto dalle componenti RGB indicate. Deve essere richiamato per creare ogni colore da utilizzare nell'immagine. ([altro |https://www.php.net/manual/en/function.imagecolorallocate]) @@ -447,43 +463,48 @@ crop(int|string $left, int|string $top, int|string $width, int|string $height): Ritaglia un'immagine nell'area rettangolare indicata. Le dimensioni possono essere passate come numeri interi in pixel o come stringhe in percentuale (ad esempio `'50%'`). -cropAuto(int $mode=-1, float $threshold=.5, int $color=-1): Image .[method] ---------------------------------------------------------------------------- +cropAuto(int $mode=-1, float $threshold=.5, ?ImageColor $color=null): Image .[method] +------------------------------------------------------------------------------------- Ritaglia automaticamente un'immagine in base all'indirizzo `$mode`. ([altro |https://www.php.net/manual/en/function.imagecropauto]) -ellipse(int $cx, int $cy, int $w, int $h, int $color): void .[method] ---------------------------------------------------------------------- +ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method] +----------------------------------------------------------------------------------------------- Disegna un'ellisse centrata sulle coordinate specificate. ([altro |https://www.php.net/manual/en/function.imageellipse]) -fill(int $x, int $y, int $color): void .[method] ------------------------------------------------- +fill(int $x, int $y, ImageColor $color): void .[method] +------------------------------------------------------- Esegue un riempimento a tappeto a partire dalla coordinata data (in alto a sinistra è 0, 0) con il dato `$color` nell'immagine. ([altro |https://www.php.net/manual/en/function.imagefill]) -filledArc(int $cx, int $cy, int $w, int $h, int $s, int $e, int $color, int $style): void .[method] ---------------------------------------------------------------------------------------------------- +filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style): void .[method] +--------------------------------------------------------------------------------------------------------------------------------------------- Disegna un arco parziale centrato nella coordinata specificata dell'immagine. ([altro |https://www.php.net/manual/en/function.imagefilledarc]) -filledEllipse(int $cx, int $cy, int $w, int $h, int $color): void .[method] ---------------------------------------------------------------------------- +filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method] +----------------------------------------------------------------------------------------------------- Disegna un'ellisse centrata sulla coordinata specificata nell'immagine. ([altro |https://www.php.net/manual/en/function.imagefilledellipse]) -filledPolygon(array $points, int $numPoints, int $color): void .[method] ------------------------------------------------------------------------- +filledPolygon(array $points, ImageColor $color): void .[method] +--------------------------------------------------------------- Crea un poligono riempito nell'immagine $. ([altro |https://www.php.net/manual/en/function.imagefilledpolygon]) -filledRectangle(int $x1, int $y1, int $x2, int $y2, int $color): void .[method] -------------------------------------------------------------------------------- -Crea un rettangolo riempito con `$color` nell'immagine a partire dal punto 1 e fino al punto 2. 0, 0 è l'angolo superiore sinistro dell'immagine. ([altro |https://www.php.net/manual/en/function.imagefilledrectangle]) +filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------- +Crea un rettangolo riempito con `$color` nell'immagine che inizia con `$x1` e `$y1` e termina con `$x2` e `$y2`. Il punto 0, 0 è l'angolo superiore sinistro dell'immagine. ([altro |https://www.php.net/manual/en/function.imagefilledrectangle]) -fillToBorder(int $x, int $y, int $border, int $color): void .[method] ---------------------------------------------------------------------- +filledRectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------------------- +Crea un rettangolo riempito con `$color` nell'immagine a partire dai punti `$left` e `$top` con larghezza `$width` e altezza `$height`. Il punto 0, 0 è l'angolo superiore sinistro dell'immagine. + + +fillToBorder(int $x, int $y, int $border, ImageColor $color): void .[method] +---------------------------------------------------------------------------- Esegue un riempimento a tappeto il cui colore del bordo è definito da `$border`. Il punto di partenza per il riempimento è `$x`, `$y` (in alto a sinistra 0, 0) e la regione viene riempita con il colore `$color`. ([altro |https://www.php.net/manual/en/function.imagefilltoborder]) @@ -497,9 +518,9 @@ flip(int $mode): void .[method] Capovolge l'immagine utilizzando l'indirizzo `$mode`. ([altro |https://www.php.net/manual/en/function.imageflip]) -ftText(int $size, int $angle, int $x, int $y, int $col, string $fontFile, string $text, array $extrainfo=null): array .[method] -------------------------------------------------------------------------------------------------------------------------------- -Scrivere il testo sull'immagine usando i font di FreeType 2. ([altro |https://www.php.net/manual/en/function.imagefttext]) +ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method] +---------------------------------------------------------------------------------------------------------------------------------------- +Scrivere il testo nell'immagine. ([altro |https://www.php.net/manual/en/function.imagefttext]) gammaCorrect(float $inputgamma, float $outputgamma): void .[method] @@ -542,13 +563,13 @@ layerEffect(int $effect): void .[method] Impostare il flag di fusione alfa per utilizzare gli effetti di stratificazione. ([altro |https://www.php.net/manual/en/function.imagelayereffect]) -line(int $x1, int $y1, int $x2, int $y2, int $color): void .[method] --------------------------------------------------------------------- +line(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +--------------------------------------------------------------------------- Disegna una linea tra i due punti dati. ([altro |https://www.php.net/manual/en/function.imageline]) -openPolygon(array $points, int $numPoints, int $color): void .[method] ----------------------------------------------------------------------- +openPolygon(array $points, ImageColor $color): void .[method] +------------------------------------------------------------- Disegna un poligono aperto sull'immagine. Contrariamente a `polygon()`, non viene tracciata una linea tra l'ultimo e il primo punto. ([altro |https://www.php.net/manual/en/function.imageopenpolygon]) @@ -567,16 +588,21 @@ place(Image $image, int|string $left=0, int|string $top=0, int $opacity=100): Im Copia `$image` nell'immagine alle coordinate `$left` e `$top`. Le coordinate possono essere passate come numeri interi in pixel o come stringhe in percentuale (ad esempio `'50%'`). -polygon(array $points, int $numPoints, int $color): void .[method] ------------------------------------------------------------------- +polygon(array $points, ImageColor $color): void .[method] +--------------------------------------------------------- Crea un poligono nell'immagine. ([altro |https://www.php.net/manual/en/function.imagepolygon]) -rectangle(int $x1, int $y1, int $x2, int $y2, int $col): void .[method] ------------------------------------------------------------------------ +rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +-------------------------------------------------------------------------------- Crea un rettangolo a partire dalle coordinate specificate. ([altro |https://www.php.net/manual/en/function.imagerectangle]) +rectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------------- +Crea un rettangolo alle coordinate date. + + resize(int|string $width, int|string $height, int $flags=Image::OrSmaller): Image .[method] ------------------------------------------------------------------------------------------- Scala un'immagine, vedi [maggiori informazioni |#Image Resize]. Le dimensioni possono essere passate come numeri interi in pixel o come stringhe in percentuale (ad esempio `'50%'`). @@ -638,8 +664,8 @@ setInterpolation(int $method=IMG_BILINEAR_FIXED): void .[method] Imposta il metodo di interpolazione che influisce sui metodi `rotate()` e `affine()`. ([altro |https://www.php.net/manual/en/function.imagesetinterpolation]) -setPixel(int $x, int $y, int $color): void .[method] ----------------------------------------------------- +setPixel(int $x, int $y, ImageColor $color): void .[method] +----------------------------------------------------------- Disegna un pixel alla coordinata specificata. ([altro |https://www.php.net/manual/en/function.imagesetpixel]) @@ -668,16 +694,6 @@ Rende l'immagine un po' più nitida. Richiede l'estensione *Bundled GD*, quindi non è sicuro che funzioni ovunque. -string(int $font, int $x, int $y, string $str, int $col): void .[method] ------------------------------------------------------------------------- -Disegna una stringa alle coordinate date. ([altro |https://www.php.net/manual/en/function.imagestring]) - - -stringUp(int $font, int $x, int $y, string $s, int $col): void .[method] ------------------------------------------------------------------------- -Disegna una stringa in verticale alle coordinate date. ([altro |https://www.php.net/manual/en/function.imagestringup]) - - toString(int $type=ImageType::JPEG, int $quality=null): string .[method] ------------------------------------------------------------------------ Emette un'immagine in stringa. @@ -690,6 +706,6 @@ trueColorToPalette(bool $dither, int $ncolors): void .[method] Converte un'immagine truecolor in un'immagine palette. ([altro |https://www.php.net/manual/en/function.imagetruecolortopalette]) -ttfText(int $size, int $angle, int $x, int $y, int $color, string $fontfile, string $text): array .[method] ------------------------------------------------------------------------------------------------------------ -Scrive il testo dato nell'immagine usando i font TrueType. ([altro |https://www.php.net/manual/en/function.imagettftext]) +ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method] +----------------------------------------------------------------------------------------------------------------------------------------- +Scrive il testo dato nell'immagine. ([altro |https://www.php.net/manual/en/function.imagettftext]) diff --git a/utils/pl/images.texy b/utils/pl/images.texy index 419a9a011e..c21623a869 100644 --- a/utils/pl/images.texy +++ b/utils/pl/images.texy @@ -17,6 +17,7 @@ Wszystkie przykłady zakładają, że alias został utworzony: ```php use Nette\Utils\Image; +use Nette\Utils\ImageColor; use Nette\Utils\ImageType; ``` @@ -33,7 +34,7 @@ $image = Image::fromBlank(100, 200); Możesz opcjonalnie określić kolor tła (domyślnie jest to kolor czarny): ```php -$image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0)); +$image = Image::fromBlank(100, 200, ImageColor::rgb(125, 0, 0)); ``` Albo załadować obraz z pliku: @@ -191,16 +192,36 @@ $image->cropAuto(IMG_CROP_BLACK); Metoda `cropAuto()` jest obiektowym zamiennikiem funkcji `imagecropauto()`, więcej informacji można znaleźć w [jej dokumentacji |https://www.php.net/manual/en/function.imagecropauto]. +Kolory .[#toc-colors] +===================== + +Metoda `ImageColor::rgb()` umożliwia zdefiniowanie koloru przy użyciu wartości czerwonego, zielonego i niebieskiego (RGB). Opcjonalnie można również określić wartość przezroczystości w zakresie od 0 (całkowicie przezroczysty) do 1 (całkowicie nieprzezroczysty), podobnie jak w CSS. + +```php +$color = ImageColor::rgb(255, 0, 0); // Red +$transparentBlue = ImageColor::rgb(0, 0, 255, 0.5); // Semi-transparent blue +``` + +Metoda `ImageColor::hex()` umożliwia zdefiniowanie koloru przy użyciu formatu szesnastkowego, podobnie jak w CSS. Obsługuje formaty `#rgb`, `#rrggbb`, `#rgba` i `#rrggbbaa`: + +```php +$color = ImageColor::hex("#F00"); // Red +$transparentGreen = ImageColor::hex("#00FF0080"); // Semi-transparent green +``` + +Kolory mogą być używane w innych metodach, takich jak `ellipse()`, `fill()`, itp. + + Rysowanie i edycja .[#toc-drawing-and-editing] ============================================== -Możesz rysować, możesz pisać, ale nie drzyj kartek. Wszystkie funkcje PHP do pracy z obrazami, takie jak [imagefilledellipse |https://www.php.net/manual/en/function.imagefilledellipse.php], są dostępne dla Ciebie, ale w obiektowym domyśle: +Możesz rysować, możesz pisać, możesz używać wszystkich funkcji PHP do manipulacji obrazem, patrz [Przegląd metod |#Overview of methods], ale w opakowaniu obiektowym: ```php -$image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63)); +$image->filledEllipse($centerX, $centerY, $width, $height, ImageColor::rgb(255, 0, 0)); ``` -Zobacz [Przegląd metod |#Overview-of-Methods]. +Ponieważ funkcje PHP do rysowania prostokątów są niepraktyczne ze względu na konieczność określania współrzędnych, klasa `Image` oferuje ich zamienniki w postaci funkcji [rectangleWH |#rectangleWH()] [( |#filledRectangleWH()] [) |#rectangleWH()] i [filledRectangleWH() |#filledRectangleWH()]. Łączenie wielu obrazów .[#toc-merge-multiple-images] @@ -210,7 +231,7 @@ Możesz łatwo wstawić inny obraz do obrazu: ```php $logo = Image::fromFile('logo.png'); -$blank = Image::fromBlank(320, 240, Image::rgb(52, 132, 210)); +$blank = Image::fromBlank(320, 240, ImageColor::rgb(52, 132, 210)); // współrzędne mogą być ponownie podane w procentach $blank->place($logo, '80%', '80%'); // wstawiamy w pobliżu prawego dolnego rogu @@ -229,8 +250,8 @@ Przegląd metod .[#toc-overview-of-methods] ========================================== -static fromBlank(int $width, int $height, array $color=null): Image .[method] ------------------------------------------------------------------------------ +static fromBlank(int $width, int $height, ImageColor $color=null): Image .[method] +---------------------------------------------------------------------------------- Tworzy nowy obraz w kolorze rzeczywistym o podanych wymiarach. Domyślnym kolorem jest czarny. @@ -244,9 +265,9 @@ static fromString(string $s, int &$detectedFormat=null): Image .[method] Odczytuje obraz z ciągu znaków i zwraca jego [typ |#Formats] w `$detectedFormat`. -static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method] ---------------------------------------------------------------------------------- -Tworzy kolor, który może być używany w innych metodach, takich jak `ellipse()`, `fill()`, itp. +static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated] +--------------------------------------------------------------------------------------------- +Funkcja ta została zastąpiona przez klasę `ImageColor`, patrz [kolory |#Colors]. static typeToExtension(int $type): string .[method] @@ -279,6 +300,11 @@ static isTypeSupported(int $type): bool .[method] Określa, czy dany [typ |#Formats] obrazu jest obsługiwany. +static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method] +------------------------------------------------------------------------------------------------------------------------ +Oblicza wymiary prostokąta otaczającego tekst o określonej czcionce i rozmiarze. Zwraca tablicę asocjacyjną zawierającą klucze `left`, `top`, `width`, `height`. Lewy margines może być ujemny, jeśli tekst zaczyna się od lewego nawisu. + + affine(array $affine, array $clip=null): Image .[method] -------------------------------------------------------- Zwróć obraz zawierający affine-transformed src image używając opcjonalnego regionu przycinania ([więcej |https://www.php.net/manual/en/function.imageaffine]). @@ -306,21 +332,11 @@ Aktywuj rysowanie linii wygładzonych i wielokątów. Nie obsługuje kanałów a Użycie antyaliasowanego prymitywu z przezroczystym kolorem tła może skończyć się nieoczekiwanymi rezultatami. Metoda blend wykorzystuje kolor tła jak każdy inny kolor. ([więcej |https://www.php.net/manual/en/function.imageantialias]) -arc(int $x, int $y, int $w, int $h, int $start, int $end, int $color): void .[method] -------------------------------------------------------------------------------------- +arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color): void .[method] +--------------------------------------------------------------------------------------------------------------------------- Rysuje łuk okręgu o środku w podanych współrzędnych. ([więcej |https://www.php.net/manual/en/function.imagearc]) -char(int $font, int $x, int $y, string $char, int $color): void .[method] -------------------------------------------------------------------------- -Rysuje pierwszy znak `$char` w obrazie z lewym górnym rogiem na `$x`, `$y` (lewy górny to 0, 0) w kolorze `$color`. ([więcej |https://www.php.net/manual/en/function.imagechar]) - - -charUp(int $font, int $x, int $y, string $char, int $color): void .[method] ---------------------------------------------------------------------------- -Rysuje znak `$char` w pionie na określonej współrzędnej w podanym obrazie. ([więcej |https://www.php.net/manual/en/function.imagecharup]) - - colorAllocate(int $red, int $green, int $blue): int .[method] ------------------------------------------------------------- Zwraca identyfikator koloru reprezentujący kolor złożony z podanych składowych RGB. Musi być wywołany, aby stworzyć każdy kolor, który ma być użyty w obrazie. ([więcej |https://www.php.net/manual/en/function.imagecolorallocate]) @@ -447,43 +463,48 @@ crop(int|string $left, int|string $top, int|string $width, int|string $height): Przycina obraz do zadanego prostokątnego obszaru. Wymiary mogą być określone jako liczby całkowite w pikselach lub ciągi znaków w procentach (na przykład `'50%'`). -cropAuto(int $mode=-1, float $threshold=.5, int $color=-1): Image .[method] ---------------------------------------------------------------------------- +cropAuto(int $mode=-1, float $threshold=.5, ?ImageColor $color=null): Image .[method] +------------------------------------------------------------------------------------- Automatycznie przycina obraz zgodnie z podanym `$mode`. ([więcej |https://www.php.net/manual/en/function.imagecropauto]) -ellipse(int $cx, int $cy, int $w, int $h, int $color): void .[method] ---------------------------------------------------------------------- +ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method] +----------------------------------------------------------------------------------------------- Rysuje elipsę wyśrodkowaną na podanych współrzędnych. ([więcej |https://www.php.net/manual/en/function.imageellipse]) -fill(int $x, int $y, int $color): void .[method] ------------------------------------------------- +fill(int $x, int $y, ImageColor $color): void .[method] +------------------------------------------------------- Wypełnia obszar zaczynający się na podanej współrzędnej (lewa górna to 0, 0) podaną `$color`. ([więcej |https://www.php.net/manual/en/function.imagefill]) -filledArc(int $cx, int $cy, int $w, int $h, int $s, int $e, int $color, int $style): void .[method] ---------------------------------------------------------------------------------------------------- +filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style): void .[method] +--------------------------------------------------------------------------------------------------------------------------------------------- Rysuje częściowy łuk o środku w podanych współrzędnych. ([więcej |https://www.php.net/manual/en/function.imagefilledarc]) -filledEllipse(int $cx, int $cy, int $w, int $h, int $color): void .[method] ---------------------------------------------------------------------------- +filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method] +----------------------------------------------------------------------------------------------------- Rysuje elipsę wyśrodkowaną na podanych współrzędnych. ([więcej |https://www.php.net/manual/en/function.imagefilledellipse]) -filledPolygon(array $points, int $numPoints, int $color): void .[method] ------------------------------------------------------------------------- +filledPolygon(array $points, ImageColor $color): void .[method] +--------------------------------------------------------------- Tworzy wypełniony wielokąt w obrazie. ([więcej |https://www.php.net/manual/en/function.imagefilledpolygon]) -filledRectangle(int $x1, int $y1, int $x2, int $y2, int $color): void .[method] -------------------------------------------------------------------------------- -Tworzy prostokąt wypełniony stroną `$color` w obrazie zaczynając od punktu 1 i kończąc w punkcie 2. Punkt 0, 0 jest lewym górnym rogiem obrazu. ([więcej |https://www.php.net/manual/en/function.imagefilledrectangle]) +filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------- +Tworzy prostokąt wypełniony `$color` na obrazie, zaczynając od `$x1` i `$y1`, a kończąc na `$x2` i `$y2`. Punkt 0, 0 to lewy górny róg obrazu. ([więcej |https://www.php.net/manual/en/function.imagefilledrectangle]) -fillToBorder(int $x, int $y, int $border, int $color): void .[method] ---------------------------------------------------------------------- +filledRectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------------------- +Tworzy prostokąt wypełniony `$color` na obrazie, zaczynając od punktów `$left` i `$top` o szerokości `$width` i wysokości `$height`. Punkt 0, 0 to lewy górny róg obrazu. + + +fillToBorder(int $x, int $y, int $border, ImageColor $color): void .[method] +---------------------------------------------------------------------------- Tworzy wypełnienie, którego kolor jest określony przez `$border`. Punktem początkowym wypełnienia jest `$x`, `$y` (lewa górna część to 0, 0), a obszar jest wypełniony kolorem `$color`. ([więcej |https://www.php.net/manual/en/function.imagefilltoborder]) @@ -497,9 +518,9 @@ flip(int $mode): void .[method] Odwraca obraz za pomocą podanego `$mode`. ([więcej |https://www.php.net/manual/en/function.imageflip]) -ftText(int $size, int $angle, int $x, int $y, int $col, string $fontFile, string $text, array $extrainfo=null): array .[method] -------------------------------------------------------------------------------------------------------------------------------- -Napisz tekst w obrazie za pomocą czcionek z FreeType 2. ([więcej |https://www.php.net/manual/en/function.imagefttext]) +ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method] +---------------------------------------------------------------------------------------------------------------------------------------- +Wpisz tekst na obrazku. ([więcej |https://www.php.net/manual/en/function.imagefttext]) gammaCorrect(float $inputgamma, float $outputgamma): void .[method] @@ -542,13 +563,13 @@ layerEffect(int $effect): void .[method] Ustaw flagę alfa blend, aby użyć efektów warstwowych. ([więcej |https://www.php.net/manual/en/function.imagelayereffect]) -line(int $x1, int $y1, int $x2, int $y2, int $color): void .[method] --------------------------------------------------------------------- +line(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +--------------------------------------------------------------------------- Rysuje linię pomiędzy dwoma podanymi punktami. ([więcej |https://www.php.net/manual/en/function.imageline]) -openPolygon(array $points, int $numPoints, int $color): void .[method] ----------------------------------------------------------------------- +openPolygon(array $points, ImageColor $color): void .[method] +------------------------------------------------------------- Rysuje na obrazie otwarty wielokąt. W odróżnieniu od `polygon()`, między ostatnim a pierwszym punktem nie rysuje się linii. ([więcej |https://www.php.net/manual/en/function.imageopenpolygon]) @@ -567,16 +588,21 @@ place(Image $image, int|string $left=0, int|string $top=0, int $opacity=100): Im Kopiuje stronę `$image` do obrazu na współrzędnych `$left` i `$top`. Współrzędne mogą być określone jako liczby całkowite w pikselach lub łańcuchy w procentach (na przykład `'50%'`). -polygon(array $points, int $numPoints, int $color): void .[method] ------------------------------------------------------------------- +polygon(array $points, ImageColor $color): void .[method] +--------------------------------------------------------- Tworzy wielokąt w obrazie. ([więcej |https://www.php.net/manual/en/function.imagepolygon]) -rectangle(int $x1, int $y1, int $x2, int $y2, int $col): void .[method] ------------------------------------------------------------------------ +rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +-------------------------------------------------------------------------------- Tworzy prostokąt na podanych współrzędnych ([więcej |https://www.php.net/manual/en/function.imagerectangle]). +rectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------------- +Tworzy prostokąt o podanych współrzędnych. + + resize(int|string $width, int|string $height, int $flags=Image::OrSmaller): Image .[method] ------------------------------------------------------------------------------------------- Zmienia rozmiar obrazu, [więcej informacji |#Image-Resize]. Wymiary mogą być określone jako liczby całkowite w pikselach lub ciągi znaków w procentach (na przykład `'50%'`). @@ -638,8 +664,8 @@ setInterpolation(int $method=IMG_BILINEAR_FIXED): void .[method] Ustawia metodę interpolacji, która wpływa na metody `rotate()` i `affine()`. ([więcej |https://www.php.net/manual/en/function.imagesetinterpolation]) -setPixel(int $x, int $y, int $color): void .[method] ----------------------------------------------------- +setPixel(int $x, int $y, ImageColor $color): void .[method] +----------------------------------------------------------- Rysuje piksel na określonej współrzędnej. ([więcej |https://www.php.net/manual/en/function.imagesetpixel]) @@ -668,16 +694,6 @@ Wyostrza obraz. Wymaga obecności rozszerzenia *Bundled GD*, więc może nie działać wszędzie. -string(int $font, int $x, int $y, string $str, int $col): void .[method] ------------------------------------------------------------------------- -Wypisuje ciąg znaków na podane współrzędne. ([więcej |https://www.php.net/manual/en/function.imagestring]) - - -stringUp(int $font, int $x, int $y, string $s, int $col): void .[method] ------------------------------------------------------------------------- -Wypisuje ciąg znaków w pionie na podane współrzędne. ([więcej |https://www.php.net/manual/en/function.imagestringup]) - - toString(int $type=ImageType::JPEG, int $quality=null): string .[method] ------------------------------------------------------------------------ Zapisuje obraz w postaci ciągu znaków. @@ -690,6 +706,6 @@ trueColorToPalette(bool $dither, int $ncolors): void .[method] Konwertuje obraz truecolor na obraz palety. ([więcej |https://www.php.net/manual/en/function.imagetruecolortopalette]) -ttfText(int $size, int $angle, int $x, int $y, int $color, string $fontfile, string $text): array .[method] ------------------------------------------------------------------------------------------------------------ -Drukuje podany tekst do obrazu przy użyciu czcionek TrueType. ([więcej |https://www.php.net/manual/en/function.imagettftext]) +ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method] +----------------------------------------------------------------------------------------------------------------------------------------- +Zapisuje podany tekst na obrazie. ([więcej |https://www.php.net/manual/en/function.imagettftext]) diff --git a/utils/pt/images.texy b/utils/pt/images.texy index 9344efed84..20a1f45b09 100644 --- a/utils/pt/images.texy +++ b/utils/pt/images.texy @@ -17,6 +17,7 @@ Os exemplos a seguir assumem que a seguinte classe está definida: ```php use Nette\Utils\Image; +use Nette\Utils\ImageColor; use Nette\Utils\ImageType; ``` @@ -33,7 +34,7 @@ $image = Image::fromBlank(100, 200); Opcionalmente, você pode especificar uma cor de fundo (o padrão é preto): ```php -$image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0)); +$image = Image::fromBlank(100, 200, ImageColor::rgb(125, 0, 0)); ``` Ou carregamos a imagem de um arquivo: @@ -191,16 +192,36 @@ $image->cropAuto(IMG_CROP_BLACK); O método `cropAuto()` é um encapsulamento de objeto da função `imagecropauto()`, veja [sua documentação |https://www.php.net/manual/en/function.imagecropauto] para mais informações. +Cores .[#toc-colors] +==================== + +O método `ImageColor::rgb()` permite que você defina uma cor usando valores de vermelho, verde e azul (RGB). Opcionalmente, você também pode especificar um valor de transparência que varia de 0 (totalmente transparente) a 1 (totalmente opaco), assim como no CSS. + +```php +$color = ImageColor::rgb(255, 0, 0); // Red +$transparentBlue = ImageColor::rgb(0, 0, 255, 0.5); // Semi-transparent blue +``` + +O método `ImageColor::hex()` permite que você defina uma cor usando o formato hexadecimal, semelhante ao CSS. Ele é compatível com os formatos `#rgb`, `#rrggbb`, `#rgba` e `#rrggbbaa`: + +```php +$color = ImageColor::hex("#F00"); // Red +$transparentGreen = ImageColor::hex("#00FF0080"); // Semi-transparent green +``` + +As cores podem ser usadas em outros métodos, como `ellipse()`, `fill()`, etc. + + Desenho e Edição .[#toc-drawing-and-editing] ============================================ -Você pode desenhar, você pode escrever, você pode usar todas as funções PHP para trabalhar com imagens, tais como [imagefilledellipse() |https://www.php.net/manual/en/function.imagefilledellipse.php], mas usando o estilo de objeto: +Você pode desenhar, escrever e usar todas as funções do PHP para manipulação de imagens, consulte [Visão geral dos métodos |#Overview of methods], mas em um invólucro orientado a objetos: ```php -$image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63)); +$image->filledEllipse($centerX, $centerY, $width, $height, ImageColor::rgb(255, 0, 0)); ``` -Veja [Visão geral dos métodos |#Overview of Methods]. +Como as funções PHP para desenhar retângulos são impraticáveis devido à especificação de coordenadas, a classe `Image` oferece seus substitutos na forma das funções [rectangleWH() |#rectangleWH()] e [filledRectangleWH() |#filledRectangleWH()]. Fundir várias imagens .[#toc-merge-multiple-images] @@ -210,7 +231,7 @@ Você pode facilmente colocar outra imagem dentro da imagem: ```php $logo = Image::fromFile('logo.png'); -$blank = Image::fromBlank(320, 240, Image::rgb(52, 132, 210)); +$blank = Image::fromBlank(320, 240, ImageColor::rgb(52, 132, 210)); // as coordenadas também podem ser definidas em porcentagem $blank->place($logo, '80%', '80%'); // perto do canto inferior direito @@ -229,8 +250,8 @@ Visão geral dos métodos .[#toc-overview-of-methods] =================================================== -static fromBlank(int $width, int $height, array $color=null): Image .[method] ------------------------------------------------------------------------------ +static fromBlank(int $width, int $height, ImageColor $color=null): Image .[method] +---------------------------------------------------------------------------------- Cria uma nova imagem colorida verdadeira das dimensões dadas. A cor padrão é o preto. @@ -244,9 +265,9 @@ static fromString(string $s, int &$detectedFormat=null): Image .[method] Lê uma imagem de uma string e retorna seu [tipo |#Formats] em `$detectedFormat`. -static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method] ---------------------------------------------------------------------------------- -Cria uma cor que pode ser usada em outros métodos, tais como `ellipse()`, `fill()` e assim por diante. +static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated] +--------------------------------------------------------------------------------------------- +Esse recurso foi substituído pela classe `ImageColor`, consulte [cores |#Colors]. static typeToExtension(int $type): string .[method] @@ -279,6 +300,11 @@ static isTypeSupported(int $type): bool .[method] Determina se o [tipo |#Formats] de imagem fornecido é compatível. +static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method] +------------------------------------------------------------------------------------------------------------------------ +Calcula as dimensões do retângulo que envolve o texto em uma fonte e tamanho especificados. Retorna uma matriz associativa contendo as chaves `left`, `top`, `width`, `height`. A margem esquerda pode ser negativa se o texto começar com uma saliência à esquerda. + + affine(array $affine, array $clip=null): Image .[method] -------------------------------------------------------- Retorna uma imagem contendo a imagem src transformada afim, usando uma área de recorte opcional. ([mais |https://www.php.net/manual/en/function.imageaffine]). @@ -306,21 +332,11 @@ Ativar os métodos de desenho rápido antialiased para linhas e polígonos com f O uso de primitivos antialiased com cor de fundo transparente pode terminar com alguns resultados inesperados. O método de mistura utiliza a cor de fundo como qualquer outra cor. A falta de suporte de componentes alfa não permite um método antialiasing baseado em alfa. ([mais |https://www.php.net/manual/en/function.imageantialias]) -arc(int $x, int $y, int $w, int $h, int $start, int $end, int $color): void .[method] -------------------------------------------------------------------------------------- +arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color): void .[method] +--------------------------------------------------------------------------------------------------------------------------- Desenha um arco de círculo centrado nas coordenadas dadas. ([mais |https://www.php.net/manual/en/function.imagearc]) -char(int $font, int $x, int $y, string $char, int $color): void .[method] -------------------------------------------------------------------------- -Traça o primeiro caractere de `$char` na imagem com sua parte superior esquerda em `$x`,`$y` (parte superior esquerda é 0, 0) com a cor `$color`. ([mais |https://www.php.net/manual/en/function.imagechar]) - - -charUp(int $font, int $x, int $y, string $char, int $color): void .[method] ---------------------------------------------------------------------------- -Traça o caracter `$char` verticalmente na coordenada especificada na imagem dada. ([mais |https://www.php.net/manual/en/function.imagecharup]) - - colorAllocate(int $red, int $green, int $blue): int .[method] ------------------------------------------------------------- Retorna um identificador de cor que representa a cor composta dos componentes RGB. Ela deve ser chamada para criar cada cor a ser usada na imagem. ([mais |https://www.php.net/manual/en/function.imagecolorallocate]) @@ -447,43 +463,48 @@ crop(int|string $left, int|string $top, int|string $width, int|string $height): Cortar uma imagem para a área retangular dada. As dimensões podem ser passadas como números inteiros em pixels ou cadeias em porcentagem (ou seja, `'50%'`). -cropAuto(int $mode=-1, float $threshold=.5, int $color=-1): Image .[method] ---------------------------------------------------------------------------- +cropAuto(int $mode=-1, float $threshold=.5, ?ImageColor $color=null): Image .[method] +------------------------------------------------------------------------------------- Automaticamente cultiva uma imagem de acordo com o dado `$mode`. ([mais |https://www.php.net/manual/en/function.imagecropauto]) -ellipse(int $cx, int $cy, int $w, int $h, int $color): void .[method] ---------------------------------------------------------------------- +ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method] +----------------------------------------------------------------------------------------------- Desenha uma elipse centrada nas coordenadas especificadas. ([mais |https://www.php.net/manual/en/function.imageellipse]) -fill(int $x, int $y, int $color): void .[method] ------------------------------------------------- +fill(int $x, int $y, ImageColor $color): void .[method] +------------------------------------------------------- Realiza um enchimento de inundação a partir da coordenada dada (no canto superior esquerdo é 0, 0) com o dado `$color` na imagem. ([mais |https://www.php.net/manual/en/function.imagefill]) -filledArc(int $cx, int $cy, int $w, int $h, int $s, int $e, int $color, int $style): void .[method] ---------------------------------------------------------------------------------------------------- +filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style): void .[method] +--------------------------------------------------------------------------------------------------------------------------------------------- Desenha um arco parcial centrado na coordenada especificada na imagem. ([mais |https://www.php.net/manual/en/function.imagefilledarc]) -filledEllipse(int $cx, int $cy, int $w, int $h, int $color): void .[method] ---------------------------------------------------------------------------- +filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method] +----------------------------------------------------------------------------------------------------- Desenha uma elipse centrada na coordenada especificada na imagem. ([mais |https://www.php.net/manual/en/function.imagefilledellipse]) -filledPolygon(array $points, int $numPoints, int $color): void .[method] ------------------------------------------------------------------------- +filledPolygon(array $points, ImageColor $color): void .[method] +--------------------------------------------------------------- Cria um polígono cheio na imagem de $. ([mais |https://www.php.net/manual/en/function.imagefilledpolygon]) -filledRectangle(int $x1, int $y1, int $x2, int $y2, int $color): void .[method] -------------------------------------------------------------------------------- -Cria um retângulo preenchido com `$color` na imagem começando no ponto 1 e terminando no ponto 2. 0, 0 é o canto superior esquerdo da imagem. ([mais |https://www.php.net/manual/en/function.imagefilledrectangle]) +filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------- +Cria um retângulo preenchido com `$color` na imagem, começando em `$x1` e `$y1` e terminando em `$x2` e `$y2`. O ponto 0, 0 é o canto superior esquerdo da imagem. ([Mais |https://www.php.net/manual/en/function.imagefilledrectangle]) -fillToBorder(int $x, int $y, int $border, int $color): void .[method] ---------------------------------------------------------------------- +filledRectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------------------- +Cria um retângulo preenchido com `$color` na imagem a partir dos pontos `$left` e `$top` com largura `$width` e altura `$height`. O ponto 0, 0 é o canto superior esquerdo da imagem. + + +fillToBorder(int $x, int $y, int $border, ImageColor $color): void .[method] +---------------------------------------------------------------------------- Realiza um enchimento de inundação cuja cor da borda é definida por `$border`. O ponto de partida para o preenchimento é `$x`, `$y` (canto superior esquerdo é 0, 0) e a região é preenchida com a cor `$color`. ([mais |https://www.php.net/manual/en/function.imagefilltoborder]) @@ -497,9 +518,9 @@ flip(int $mode): void .[method] Vira a imagem usando o dado `$mode`. ([mais |https://www.php.net/manual/en/function.imageflip]) -ftText(int $size, int $angle, int $x, int $y, int $col, string $fontFile, string $text, array $extrainfo=null): array .[method] -------------------------------------------------------------------------------------------------------------------------------- -Escrever texto na imagem usando fontes usando FreeType 2. ([mais |https://www.php.net/manual/en/function.imagefttext]) +ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method] +---------------------------------------------------------------------------------------------------------------------------------------- +Escreva o texto na figura. ([mais |https://www.php.net/manual/en/function.imagefttext]) gammaCorrect(float $inputgamma, float $outputgamma): void .[method] @@ -542,13 +563,13 @@ layerEffect(int $effect): void .[method] Coloque a bandeira de mistura alfa para usar efeitos de camadas. ([mais |https://www.php.net/manual/en/function.imagelayereffect]) -line(int $x1, int $y1, int $x2, int $y2, int $color): void .[method] --------------------------------------------------------------------- +line(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +--------------------------------------------------------------------------- Traça uma linha entre os dois pontos dados. ([mais |https://www.php.net/manual/en/function.imageline]) -openPolygon(array $points, int $numPoints, int $color): void .[method] ----------------------------------------------------------------------- +openPolygon(array $points, ImageColor $color): void .[method] +------------------------------------------------------------- Desenha um polígono aberto sobre a imagem. Ao contrário de `polygon()`, nenhuma linha é traçada entre o último e o primeiro ponto. ([mais |https://www.php.net/manual/en/function.imageopenpolygon]) @@ -567,16 +588,21 @@ place(Image $image, int|string $left=0, int|string $top=0, int $opacity=100): Im Copia `$image` para a imagem nas coordenadas `$left` e `$top`. As coordenadas podem ser passadas como números inteiros em pixels ou cadeias em porcentagem (ou seja, `'50%'`). -polygon(array $points, int $numPoints, int $color): void .[method] ------------------------------------------------------------------- +polygon(array $points, ImageColor $color): void .[method] +--------------------------------------------------------- Cria um polígono na imagem. ([mais |https://www.php.net/manual/en/function.imagepolygon]) -rectangle(int $x1, int $y1, int $x2, int $y2, int $col): void .[method] ------------------------------------------------------------------------ +rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +-------------------------------------------------------------------------------- Cria um retângulo começando nas coordenadas especificadas. ([mais |https://www.php.net/manual/en/function.imagerectangle]) +rectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------------- +Cria um retângulo nas coordenadas fornecidas. + + resize(int|string $width, int|string $height, int $flags=Image::OrSmaller): Image .[method] ------------------------------------------------------------------------------------------- Escala uma imagem, veja [mais informações |#Image Resize]. As dimensões podem ser passadas como números inteiros em pixels ou cadeias em porcentagem (ou seja, `'50%'`). @@ -638,8 +664,8 @@ setInterpolation(int $method=IMG_BILINEAR_FIXED): void .[method] Define o método de interpolação que afeta os métodos `rotate()` e `affine()`. ([mais |https://www.php.net/manual/en/function.imagesetinterpolation]) -setPixel(int $x, int $y, int $color): void .[method] ----------------------------------------------------- +setPixel(int $x, int $y, ImageColor $color): void .[method] +----------------------------------------------------------- Traça um pixel na coordenada especificada. ([mais |https://www.php.net/manual/en/function.imagesetpixel]) @@ -668,16 +694,6 @@ Aguça um pouco a imagem. Requer uma extensão GD *Bundled GD, por isso não é certo que funcione em todos os lugares. -string(int $font, int $x, int $y, string $str, int $col): void .[method] ------------------------------------------------------------------------- -Traça um fio nas coordenadas dadas. ([mais |https://www.php.net/manual/en/function.imagestring]) - - -stringUp(int $font, int $x, int $y, string $s, int $col): void .[method] ------------------------------------------------------------------------- -Traça um cordel verticalmente nas coordenadas dadas. ([mais |https://www.php.net/manual/en/function.imagestringup]) - - toString(int $type=ImageType::JPEG, int $quality=null): string .[method] ------------------------------------------------------------------------ Produz uma imagem a fio. @@ -690,6 +706,6 @@ trueColorToPalette(bool $dither, int $ncolors): void .[method] Converte uma imagem truecolor em uma imagem de paleta. ([mais |https://www.php.net/manual/en/function.imagetruecolortopalette]) -ttfText(int $size, int $angle, int $x, int $y, int $color, string $fontfile, string $text): array .[method] ------------------------------------------------------------------------------------------------------------ -Escreve o texto dado na imagem usando fontes TrueType. ([mais |https://www.php.net/manual/en/function.imagettftext]) +ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method] +----------------------------------------------------------------------------------------------------------------------------------------- +Grava o texto fornecido na imagem. ([mais |https://www.php.net/manual/en/function.imagettftext]) diff --git a/utils/ro/images.texy b/utils/ro/images.texy index 7098656312..0444c318a0 100644 --- a/utils/ro/images.texy +++ b/utils/ro/images.texy @@ -17,6 +17,7 @@ Următoarele exemple presupun că este definit următorul alias de clasă: ```php use Nette\Utils\Image; +use Nette\Utils\ImageColor; use Nette\Utils\ImageType; ``` @@ -33,7 +34,7 @@ $image = Image::fromBlank(100, 200); Opțional, puteți specifica o culoare de fundal (culoarea implicită este negru): ```php -$image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0)); +$image = Image::fromBlank(100, 200, ImageColor::rgb(125, 0, 0)); ``` Sau încărcăm imaginea dintr-un fișier: @@ -191,16 +192,36 @@ $image->cropAuto(IMG_CROP_BLACK); Metoda `cropAuto()` este o încapsulare în obiect a funcției `imagecropauto()`, a se vedea [documentația acesteia |https://www.php.net/manual/en/function.imagecropauto] pentru mai multe informații. +Culori .[#toc-colors] +===================== + +Metoda `ImageColor::rgb()` vă permite să definiți o culoare folosind valorile roșu, verde și albastru (RGB). Opțional, puteți specifica, de asemenea, o valoare de transparență de la 0 (complet transparent) la 1 (complet opac), la fel ca în CSS. + +```php +$color = ImageColor::rgb(255, 0, 0); // Red +$transparentBlue = ImageColor::rgb(0, 0, 255, 0.5); // Semi-transparent blue +``` + +Metoda `ImageColor::hex()` vă permite să definiți o culoare utilizând formatul hexazecimal, similar cu CSS. Aceasta acceptă formatele `#rgb`, `#rrggbb`, `#rgba` și `#rrggbbaa`: + +```php +$color = ImageColor::hex("#F00"); // Red +$transparentGreen = ImageColor::hex("#00FF0080"); // Semi-transparent green +``` + +Culorile pot fi utilizate în alte metode, cum ar fi `ellipse()`, `fill()`, etc. + + Desen și editare .[#toc-drawing-and-editing] ============================================ -Puteți desena, puteți scrie, puteți utiliza toate funcțiile PHP pentru a lucra cu imagini, cum ar fi [imagefilledellipse() |https://www.php.net/manual/en/function.imagefilledellipse.php], dar folosind stilul obiect: +Puteți desena, puteți scrie, puteți utiliza toate funcțiile PHP pentru manipularea imaginilor, vedeți [Prezentare generală a metodelor |#Overview of methods], dar într-o învelitoare orientată pe obiecte: ```php -$image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63)); +$image->filledEllipse($centerX, $centerY, $width, $height, ImageColor::rgb(255, 0, 0)); ``` -A se vedea [Prezentare generală a metodelor |#Overview of Methods]. +Deoarece funcțiile PHP pentru desenarea [dreptunghiurilor |#filledRectangleWH()] sunt nepractice din cauza specificării coordonatelor, clasa `Image` oferă înlocuitori sub forma funcțiilor [rectangleWH() |#rectangleWH()] și [filledRectangleWH() |#filledRectangleWH()]. Îmbinarea mai multor imagini .[#toc-merge-multiple-images] @@ -210,7 +231,7 @@ Puteți plasa cu ușurință o altă imagine în imagine: ```php $logo = Image::fromFile('logo.png'); -$blank = Image::fromBlank(320, 240, Image::rgb(52, 132, 210)); +$blank = Image::fromBlank(320, 240, ImageColor::rgb(52, 132, 210)); // coordonatele pot fi stabilite și în procente $blank->place($logo, '80%', '80%'); // lângă colțul din dreapta jos @@ -229,8 +250,8 @@ Prezentare generală a metodelor .[#toc-overview-of-methods] =========================================================== -static fromBlank(int $width, int $height, array $color=null): Image .[method] ------------------------------------------------------------------------------ +static fromBlank(int $width, int $height, ImageColor $color=null): Image .[method] +---------------------------------------------------------------------------------- Creează o nouă imagine în culori reale cu dimensiunile date. Culoarea implicită este negru. @@ -244,9 +265,9 @@ static fromString(string $s, int &$detectedFormat=null): Image .[method] Citește o imagine dintr-un șir de caractere și returnează [tipul |#Formats] acesteia în `$detectedFormat`. -static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method] ---------------------------------------------------------------------------------- -Creează o culoare care poate fi utilizată în alte metode, cum ar fi `ellipse()`, `fill()`, etc. +static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated] +--------------------------------------------------------------------------------------------- +Această caracteristică a fost înlocuită de clasa `ImageColor`, a se vedea [culori |#Colors]. static typeToExtension(int $type): string .[method] @@ -279,6 +300,11 @@ static isTypeSupported(int $type): bool .[method] Determină dacă [tipul de |#Formats] imagine dat este acceptat. +static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method] +------------------------------------------------------------------------------------------------------------------------ +Calculează dimensiunile dreptunghiului care înconjoară textul cu un font și o dimensiune specificate. Se returnează un tablou asociativ care conține cheile `left`, `top`, `width`, `height`. Marja stângă poate fi negativă dacă textul începe cu o depășire la stânga. + + affine(array $affine, array $clip=null): Image .[method] -------------------------------------------------------- Returnează o imagine care conține imaginea sursă transformată afine, folosind o zonă de tăiere opțională. ([mai mult |https://www.php.net/manual/en/function.imageaffine]). @@ -306,21 +332,11 @@ Activați metodele de desenare rapidă antialiasată pentru linii și poligoane Utilizarea primitivelor antialiasate cu o culoare de fundal transparentă poate avea rezultate neașteptate. Metoda de amestecare utilizează culoarea de fundal ca orice altă culoare. Lipsa suportului pentru componenta alfa nu permite o metodă de antialiasing bazată pe alfa. ([mai mult |https://www.php.net/manual/en/function.imageantialias]) -arc(int $x, int $y, int $w, int $h, int $start, int $end, int $color): void .[method] -------------------------------------------------------------------------------------- +arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color): void .[method] +--------------------------------------------------------------------------------------------------------------------------- Desenează un arc de cerc centrat pe coordonatele date. ([mai mult |https://www.php.net/manual/en/function.imagearc]) -char(int $font, int $x, int $y, string $char, int $color): void .[method] -------------------------------------------------------------------------- -Desenează primul caracter din `$char` în imagine cu partea superioară stângă la `$x`,`$y` (partea superioară stângă este 0, 0) cu culoarea `$color`. ([mai mult |https://www.php.net/manual/en/function.imagechar]) - - -charUp(int $font, int $x, int $y, string $char, int $color): void .[method] ---------------------------------------------------------------------------- -Desenează caracterul `$char` pe verticală la coordonatele specificate pe imaginea dată. ([mai mult |https://www.php.net/manual/en/function.imagecharup]) - - colorAllocate(int $red, int $green, int $blue): int .[method] ------------------------------------------------------------- Returnează un identificator de culoare care reprezintă culoarea compusă din componentele RGB date. Acesta trebuie apelat pentru a crea fiecare culoare care urmează să fie utilizată în imagine. ([mai mult |https://www.php.net/manual/en/function.imagecolorallocate]) @@ -447,43 +463,48 @@ crop(int|string $left, int|string $top, int|string $width, int|string $height): Recuperează o imagine în zona dreptunghiulară dată. Dimensiunile pot fi transmise ca numere întregi în pixeli sau ca șiruri de caractere în procente (de exemplu, `'50%'`). -cropAuto(int $mode=-1, float $threshold=.5, int $color=-1): Image .[method] ---------------------------------------------------------------------------- +cropAuto(int $mode=-1, float $threshold=.5, ?ImageColor $color=null): Image .[method] +------------------------------------------------------------------------------------- Recuperează automat o imagine în funcție de datele furnizate `$mode`. ([mai mult |https://www.php.net/manual/en/function.imagecropauto]) -ellipse(int $cx, int $cy, int $w, int $h, int $color): void .[method] ---------------------------------------------------------------------- +ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method] +----------------------------------------------------------------------------------------------- Desenează o elipsă centrată la coordonatele specificate. ([mai mult |https://www.php.net/manual/en/function.imageellipse]) -fill(int $x, int $y, int $color): void .[method] ------------------------------------------------- +fill(int $x, int $y, ImageColor $color): void .[method] +------------------------------------------------------- Efectuează o umplere de inundație începând de la coordonata dată (stânga sus este 0, 0) cu `$color` în imagine. ([mai mult |https://www.php.net/manual/en/function.imagefill]) -filledArc(int $cx, int $cy, int $w, int $h, int $s, int $e, int $color, int $style): void .[method] ---------------------------------------------------------------------------------------------------- +filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style): void .[method] +--------------------------------------------------------------------------------------------------------------------------------------------- Desenează un arc parțial centrat pe coordonata specificată în imagine. ([mai mult |https://www.php.net/manual/en/function.imagefilledarc]) -filledEllipse(int $cx, int $cy, int $w, int $h, int $color): void .[method] ---------------------------------------------------------------------------- +filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method] +----------------------------------------------------------------------------------------------------- Desenează o elipsă centrată la coordonatele specificate în imagine. ([mai mult |https://www.php.net/manual/en/function.imagefilledellipse]) -filledPolygon(array $points, int $numPoints, int $color): void .[method] ------------------------------------------------------------------------- +filledPolygon(array $points, ImageColor $color): void .[method] +--------------------------------------------------------------- Creează un poligon umplut în imaginea $image. ([mai mult |https://www.php.net/manual/en/function.imagefilledpolygon]) -filledRectangle(int $x1, int $y1, int $x2, int $y2, int $color): void .[method] -------------------------------------------------------------------------------- -Creează un dreptunghi umplut cu `$color` în imagine începând cu punctul 1 și terminând cu punctul 2. 0, 0 este colțul din stânga sus al imaginii. ([mai mult |https://www.php.net/manual/en/function.imagefilledrectangle]) +filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------- +Creează un dreptunghi umplut cu `$color` în imagine, începând cu `$x1` & `$y1` și terminând cu `$x2` & `$y2`. Punctul 0, 0 este colțul din stânga sus al imaginii. ([mai mult |https://www.php.net/manual/en/function.imagefilledrectangle]) -fillToBorder(int $x, int $y, int $border, int $color): void .[method] ---------------------------------------------------------------------- +filledRectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------------------- +Creează un dreptunghi umplut cu `$color` în imagine pornind de la punctul `$left` & `$top` cu lățimea `$width` și înălțimea `$height`. Punctul 0, 0 este colțul din stânga sus al imaginii. + + +fillToBorder(int $x, int $y, int $border, ImageColor $color): void .[method] +---------------------------------------------------------------------------- Efectuează o umplere de inundație a cărei culoare a marginii este definită de `$border`. Punctul de plecare pentru umplere este `$x`, `$y` (stânga sus este 0, 0) și regiunea este umplută cu culoarea `$color`. ([mai mult |https://www.php.net/manual/en/function.imagefilltoborder]) @@ -497,9 +518,9 @@ flip(int $mode): void .[method] Întoarce imaginea folosind datele `$mode`. ([mai mult |https://www.php.net/manual/en/function.imageflip]) -ftText(int $size, int $angle, int $x, int $y, int $col, string $fontFile, string $text, array $extrainfo=null): array .[method] -------------------------------------------------------------------------------------------------------------------------------- -Scrieți text pe imagine folosind fonturi cu FreeType 2. ([mai mult |https://www.php.net/manual/en/function.imagefttext]) +ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method] +---------------------------------------------------------------------------------------------------------------------------------------- +Scrieți textul din imagine. ([mai mult |https://www.php.net/manual/en/function.imagefttext]) gammaCorrect(float $inputgamma, float $outputgamma): void .[method] @@ -542,13 +563,13 @@ layerEffect(int $effect): void .[method] Setați indicatorul de amestecare alfa pentru a utiliza efectele de stratificare. ([mai mult |https://www.php.net/manual/en/function.imagelayereffect]) -line(int $x1, int $y1, int $x2, int $y2, int $color): void .[method] --------------------------------------------------------------------- +line(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +--------------------------------------------------------------------------- Trasează o linie între cele două puncte date. ([mai mult |https://www.php.net/manual/en/function.imageline]) -openPolygon(array $points, int $numPoints, int $color): void .[method] ----------------------------------------------------------------------- +openPolygon(array $points, ImageColor $color): void .[method] +------------------------------------------------------------- Desenează un poligon deschis pe imagine. Spre deosebire de `polygon()`, nu se trasează nicio linie între ultimul și primul punct. ([mai mult |https://www.php.net/manual/en/function.imageopenpolygon]) @@ -567,16 +588,21 @@ place(Image $image, int|string $left=0, int|string $top=0, int $opacity=100): Im Copiază `$image` în imagine la coordonatele `$left` și `$top`. Coordonatele pot fi transmise ca numere întregi în pixeli sau ca șiruri de caractere în procente (de exemplu, `'50%'`). -polygon(array $points, int $numPoints, int $color): void .[method] ------------------------------------------------------------------- +polygon(array $points, ImageColor $color): void .[method] +--------------------------------------------------------- Creează un poligon în imagine. ([mai mult |https://www.php.net/manual/en/function.imagepolygon]) -rectangle(int $x1, int $y1, int $x2, int $y2, int $col): void .[method] ------------------------------------------------------------------------ +rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +-------------------------------------------------------------------------------- Creează un dreptunghi care începe la coordonatele specificate. ([mai mult |https://www.php.net/manual/en/function.imagerectangle]) +rectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------------- +Creează un dreptunghi la coordonatele date. + + resize(int|string $width, int|string $height, int $flags=Image::OrSmaller): Image .[method] ------------------------------------------------------------------------------------------- Scală o imagine, vezi [mai multe informații |#Image Resize]. Dimensiunile pot fi transmise ca numere întregi în pixeli sau ca șiruri de caractere în procente (de exemplu, `'50%'`). @@ -638,8 +664,8 @@ setInterpolation(int $method=IMG_BILINEAR_FIXED): void .[method] Stabilește metoda de interpolare care afectează metodele `rotate()` și `affine()`. ([mai mult |https://www.php.net/manual/en/function.imagesetinterpolation]) -setPixel(int $x, int $y, int $color): void .[method] ----------------------------------------------------- +setPixel(int $x, int $y, ImageColor $color): void .[method] +----------------------------------------------------------- Desenează un pixel la coordonatele specificate. ([mai mult |https://www.php.net/manual/en/function.imagesetpixel]) @@ -668,16 +694,6 @@ Acutizează puțin imaginea. Necesită *Extensie GD la pachet*, deci nu este sigur că va funcționa peste tot. -string(int $font, int $x, int $y, string $str, int $col): void .[method] ------------------------------------------------------------------------- -Desenează un șir de caractere la coordonatele date. ([mai mult |https://www.php.net/manual/en/function.imagestring]) - - -stringUp(int $font, int $x, int $y, string $s, int $col): void .[method] ------------------------------------------------------------------------- -Desenează un șir pe verticală la coordonatele date. ([mai mult |https://www.php.net/manual/en/function.imagestringup]) - - toString(int $type=ImageType::JPEG, int $quality=null): string .[method] ------------------------------------------------------------------------ Produce o imagine în șir de caractere. @@ -690,6 +706,6 @@ trueColorToPalette(bool $dither, int $ncolors): void .[method] Convertește o imagine truecolor într-o imagine paletă. ([mai mult |https://www.php.net/manual/en/function.imagetruecolortopalette]) -ttfText(int $size, int $angle, int $x, int $y, int $color, string $fontfile, string $text): array .[method] ------------------------------------------------------------------------------------------------------------ -Scrie textul dat în imagine folosind fonturi TrueType. ([mai mult |https://www.php.net/manual/en/function.imagettftext]) +ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method] +----------------------------------------------------------------------------------------------------------------------------------------- +Scrie textul dat în imagine. ([mai mult |https://www.php.net/manual/en/function.imagettftext]) diff --git a/utils/ru/images.texy b/utils/ru/images.texy index fb7e92e7de..e73a3dc303 100644 --- a/utils/ru/images.texy +++ b/utils/ru/images.texy @@ -17,6 +17,7 @@ composer require nette/utils ```php use Nette\Utils\Image; +use Nette\Utils\ImageColor; use Nette\Utils\ImageType; ``` @@ -33,7 +34,7 @@ $image = Image::fromBlank(100, 200); По желанию можно указать цвет фона (по умолчанию черный): ```php -$image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0)); +$image = Image::fromBlank(100, 200, ImageColor::rgb(125, 0, 0)); ``` Или загрузите изображение из файла: @@ -191,16 +192,36 @@ $image->cropAuto(IMG_CROP_BLACK); Метод `cropAuto()` является объектной заменой функции `imagecropauto()`, более подробную информацию см. в [документации к ней |https://www.php.net/manual/en/function.imagecropauto]. +Цвета .[#toc-colors] +==================== + +Метод `ImageColor::rgb()` позволяет задать цвет, используя значения красного, зеленого и синего цветов (RGB). Опционально можно указать значение прозрачности от 0 (полностью прозрачный) до 1 (полностью непрозрачный), как в CSS. + +```php +$color = ImageColor::rgb(255, 0, 0); // Red +$transparentBlue = ImageColor::rgb(0, 0, 255, 0.5); // Semi-transparent blue +``` + +Метод `ImageColor::hex()` позволяет задать цвет, используя шестнадцатеричный формат, аналогично CSS. Он поддерживает форматы `#rgb`, `#rrggbb`, `#rgba` и `#rrggbbaa`: + +```php +$color = ImageColor::hex("#F00"); // Red +$transparentGreen = ImageColor::hex("#00FF0080"); // Semi-transparent green +``` + +Цвета могут использоваться и в других методах, таких как `ellipse()`, `fill()` и т.д. + + Рисование и редактирование .[#toc-drawing-and-editing] ====================================================== -Вы можете рисовать, можете писать, но не рвите страницы. Все функции PHP для работы с изображениями, такие как [imagefilledellipse |https://www.php.net/manual/en/function.imagefilledellipse.php], доступны вам, но в объектно-ориентированном обличье: +Можно рисовать, можно писать, можно использовать все функции PHP для работы с изображениями, см. раздел " [Обзор методов |#Overview of methods]", но в объектно-ориентированной обертке: ```php -$image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63)); +$image->filledEllipse($centerX, $centerY, $width, $height, ImageColor::rgb(255, 0, 0)); ``` -См. раздел [Обзор методов |#Overview-of-Methods]. +Поскольку функции PHP для рисования прямоугольников непрактичны из-за необходимости указания координат, класс `Image` предлагает их замену в виде функций [rectangleWH() |#rectangleWH()] и [filledRectangleWH() |#filledRectangleWH()]. Объединение нескольких изображений .[#toc-merge-multiple-images] @@ -210,7 +231,7 @@ $image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63)); ```php $logo = Image::fromFile('logo.png'); -$blank = Image::fromBlank(320, 240, Image::rgb(52, 132, 210)); +$blank = Image::fromBlank(320, 240, ImageColor::rgb(52, 132, 210)); // координаты могут быть снова заданы в процентах $blank->place($logo, '80%', '80%'); // вставьте в правый нижний угол @@ -229,8 +250,8 @@ $blank->place($image, '80%', '80%', 25); // прозрачность соста ========================================= -static fromBlank(int $width, int $height, array $color=null): Image .[method] ------------------------------------------------------------------------------ +static fromBlank(int $width, int $height, ImageColor $color=null): Image .[method] +---------------------------------------------------------------------------------- Создает новое истинно цветное изображение заданных размеров. По умолчанию используется черный цвет. @@ -244,9 +265,9 @@ static fromString(string $s, int &$detectedFormat=null): Image .[method] Считывает изображение из строки и возвращает его [тип |#Formats] в формате `$detectedFormat`. -static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method] ---------------------------------------------------------------------------------- -Создает цвет, который может быть использован в других методах, таких как `ellipse()`, `fill()` и т.д. +static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated] +--------------------------------------------------------------------------------------------- +Эта функция была заменена классом `ImageColor`, см. [цвета |#Colors]. static typeToExtension(int $type): string .[method] @@ -279,6 +300,11 @@ static isTypeSupported(int $type): bool .[method] Определяет, поддерживается ли заданный [тип |#Formats] изображения. +static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method] +------------------------------------------------------------------------------------------------------------------------ +Вычисляет размеры прямоугольника, в который заключен текст заданного шрифта и размера. Возвращается ассоциативный массив, содержащий ключи `left`, `top`, `width`, `height`. Левое поле может быть отрицательным, если текст начинается с левого свеса. + + affine(array $affine, array $clip=null): Image .[method] -------------------------------------------------------- Возвращает изображение, содержащее аффинно-трансформированное изображение src с использованием необязательной области обрезания. ([подробнее |https://www.php.net/manual/en/function.imageaffine]). @@ -306,21 +332,11 @@ antialias(bool $on): void .[method] Использование сглаженного примитива с прозрачным цветом фона может привести к неожиданным результатам. Метод смешивания использует цвет фона как любой другой цвет. ([подробнее |https://www.php.net/manual/en/function.imageantialias]) -arc(int $x, int $y, int $w, int $h, int $start, int $end, int $color): void .[method] -------------------------------------------------------------------------------------- +arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color): void .[method] +--------------------------------------------------------------------------------------------------------------------------- Рисует дугу окружности с центром в заданных координатах. ([подробнее |https://www.php.net/manual/en/function.imagearc]) -char(int $font, int $x, int $y, string $char, int $color): void .[method] -------------------------------------------------------------------------- -Нарисует первый символ `$char` в изображении с левым верхним углом `$x`, `$y` (левый верхний угол равен 0, 0) цветом `$color`. ([подробнее |https://www.php.net/manual/en/function.imagechar]) - - -charUp(int $font, int $x, int $y, string $char, int $color): void .[method] ---------------------------------------------------------------------------- -Рисует символ `$char` вертикально по указанной координате в заданном изображении. ([подробнее |https://www.php.net/manual/en/function.imagecharup]) - - colorAllocate(int $red, int $green, int $blue): int .[method] ------------------------------------------------------------- Возвращает идентификатор цвета, представляющий цвет, состоящий из заданных компонентов RGB. Должен быть вызван для создания каждого цвета, который будет использоваться в изображении. ([подробнее |https://www.php.net/manual/en/function.imagecolorallocate]) @@ -447,43 +463,48 @@ crop(int|string $left, int|string $top, int|string $width, int|string $height): Обрезает изображение до заданной прямоугольной области. Размеры могут быть указаны как целые числа в пикселях или строки в процентах (например, `'50%'`). -cropAuto(int $mode=-1, float $threshold=.5, int $color=-1): Image .[method] ---------------------------------------------------------------------------- +cropAuto(int $mode=-1, float $threshold=.5, ?ImageColor $color=null): Image .[method] +------------------------------------------------------------------------------------- Автоматическое кадрирование изображения в соответствии с заданным `$mode`. ([подробнее |https://www.php.net/manual/en/function.imagecropauto]) -ellipse(int $cx, int $cy, int $w, int $h, int $color): void .[method] ---------------------------------------------------------------------- +ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method] +----------------------------------------------------------------------------------------------- Рисует эллипс с центром в заданных координатах. ([подробнее |https://www.php.net/manual/en/function.imageellipse]) -fill(int $x, int $y, int $color): void .[method] ------------------------------------------------- +fill(int $x, int $y, ImageColor $color): void .[method] +------------------------------------------------------- Заполняет область, начинающуюся в заданной координате (слева вверху 0, 0), заданным `$color`. ([подробнее |https://www.php.net/manual/en/function.imagefill]) -filledArc(int $cx, int $cy, int $w, int $h, int $s, int $e, int $color, int $style): void .[method] ---------------------------------------------------------------------------------------------------- +filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style): void .[method] +--------------------------------------------------------------------------------------------------------------------------------------------- Рисует неполную дугу с центром в заданных координатах. ([подробнее |https://www.php.net/manual/en/function.imagefilledarc]) -filledEllipse(int $cx, int $cy, int $w, int $h, int $color): void .[method] ---------------------------------------------------------------------------- +filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method] +----------------------------------------------------------------------------------------------------- Рисует эллипс с центром в заданных координатах. ([подробнее |https://www.php.net/manual/en/function.imagefilledellipse]) -filledPolygon(array $points, int $numPoints, int $color): void .[method] ------------------------------------------------------------------------- +filledPolygon(array $points, ImageColor $color): void .[method] +--------------------------------------------------------------- Создает заполненный многоугольник на изображении. ([подробнее |https://www.php.net/manual/en/function.imagefilledpolygon]) -filledRectangle(int $x1, int $y1, int $x2, int $y2, int $color): void .[method] -------------------------------------------------------------------------------- -Создает прямоугольник, заполненный `$color` на изображении, начиная с точки 1 и заканчивая точкой 2. Точка 0, 0 - левый верхний угол изображения. ([подробнее |https://www.php.net/manual/en/function.imagefilledrectangle]) +filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------- +Создает прямоугольник, заполненный `$color` на изображении, начиная с точек `$x1` и `$y1` и заканчивая точками `$x2` и `$y2`. Точка 0, 0 - левый верхний угол изображения. ([подробнее |https://www.php.net/manual/en/function.imagefilledrectangle]) -fillToBorder(int $x, int $y, int $border, int $color): void .[method] ---------------------------------------------------------------------- +filledRectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------------------- +Создает на растре прямоугольник с заливкой `$color`, начиная с точек `$left` и `$top`, шириной `$width` и высотой `$height`. Точка 0, 0 - левый верхний угол изображения. + + +fillToBorder(int $x, int $y, int $border, ImageColor $color): void .[method] +---------------------------------------------------------------------------- Создает заливку, цвет границы которой определяется `$border`. Начальная точка заливки - `$x`, `$y` (левый верхний угол - 0, 0), а область заливается цветом `$color`. ([подробнее |https://www.php.net/manual/en/function.imagefilltoborder]) @@ -497,9 +518,9 @@ flip(int $mode): void .[method] Инвертирует изображение по заданному адресу `$mode`. ([подробнее |https://www.php.net/manual/en/function.imageflip]) -ftText(int $size, int $angle, int $x, int $y, int $col, string $fontFile, string $text, array $extrainfo=null): array .[method] -------------------------------------------------------------------------------------------------------------------------------- -Пишите текст на изображении, используя шрифты FreeType 2. ([подробнее |https://www.php.net/manual/en/function.imagefttext]) +ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method] +---------------------------------------------------------------------------------------------------------------------------------------- +Напишите текст по картинке. ([подробнее |https://www.php.net/manual/en/function.imagefttext]) gammaCorrect(float $inputgamma, float $outputgamma): void .[method] @@ -542,13 +563,13 @@ layerEffect(int $effect): void .[method] Установите флаг альфа-смешения для использования эффектов наслоения. ([подробнее |https://www.php.net/manual/en/function.imagelayereffect]) -line(int $x1, int $y1, int $x2, int $y2, int $color): void .[method] --------------------------------------------------------------------- +line(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +--------------------------------------------------------------------------- Проводит линию между двумя заданными точками. ([подробнее |https://www.php.net/manual/en/function.imageline]) -openPolygon(array $points, int $numPoints, int $color): void .[method] ----------------------------------------------------------------------- +openPolygon(array $points, ImageColor $color): void .[method] +------------------------------------------------------------- Рисует открытый многоугольник на изображении. В отличие от `polygon()`, между последней и первой точкой не проводится линия. ([подробнее |https://www.php.net/manual/en/function.imageopenpolygon]) @@ -567,16 +588,21 @@ place(Image $image, int|string $left=0, int|string $top=0, int $opacity=100): Im Копирует `$image` в изображение по координатам `$left` и `$top`. Координаты могут быть указаны как целые числа в пикселях или строки в процентах (например, `'50%'`). -polygon(array $points, int $numPoints, int $color): void .[method] ------------------------------------------------------------------- +polygon(array $points, ImageColor $color): void .[method] +--------------------------------------------------------- Создает многоугольник на изображении. ([подробнее |https://www.php.net/manual/en/function.imagepolygon]) -rectangle(int $x1, int $y1, int $x2, int $y2, int $col): void .[method] ------------------------------------------------------------------------ +rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +-------------------------------------------------------------------------------- Создает прямоугольник по заданным координатам. ([подробнее |https://www.php.net/manual/en/function.imagerectangle]) +rectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------------- +Создает прямоугольник по заданным координатам. + + resize(int|string $width, int|string $height, int $flags=Image::OrSmaller): Image .[method] ------------------------------------------------------------------------------------------- Изменение размеров изображения, [дополнительная информация |#Image-Resize]. Размеры могут быть указаны как целые числа в пикселях или строки в процентах (например, `'50%'`). @@ -638,8 +664,8 @@ setInterpolation(int $method=IMG_BILINEAR_FIXED): void .[method] Задает метод интерполяции, который влияет на методы `rotate()` и `affine()`. ([подробнее |https://www.php.net/manual/en/function.imagesetinterpolation]) -setPixel(int $x, int $y, int $color): void .[method] ----------------------------------------------------- +setPixel(int $x, int $y, ImageColor $color): void .[method] +----------------------------------------------------------- Рисует пиксель в указанной координате. ([подробнее |https://www.php.net/manual/en/function.imagesetpixel]) @@ -668,16 +694,6 @@ sharpen(): Image .[method] Требует наличия *Bundled GD extension*, поэтому может работать не везде. -string(int $font, int $x, int $y, string $str, int $col): void .[method] ------------------------------------------------------------------------- -Выводит строку по заданным координатам. ([подробнее |https://www.php.net/manual/en/function.imagestring]) - - -stringUp(int $font, int $x, int $y, string $s, int $col): void .[method] ------------------------------------------------------------------------- -Выводит строку по вертикали в заданных координатах. ([подробнее |https://www.php.net/manual/en/function.imagestringup]) - - toString(int $type=ImageType::JPEG, int $quality=null): string .[method] ------------------------------------------------------------------------ Сохраняет изображение в строке. @@ -690,6 +706,6 @@ trueColorToPalette(bool $dither, int $ncolors): void .[method] Преобразует truecolor изображение в палитру. ([подробнее |https://www.php.net/manual/en/function.imagetruecolortopalette]) -ttfText(int $size, int $angle, int $x, int $y, int $color, string $fontfile, string $text): array .[method] ------------------------------------------------------------------------------------------------------------ -Печатает заданный текст в изображение с использованием шрифтов TrueType. ([подробнее |https://www.php.net/manual/en/function.imagettftext]) +ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method] +----------------------------------------------------------------------------------------------------------------------------------------- +Записывает заданный текст в изображение. ([подробнее |https://www.php.net/manual/en/function.imagettftext]) diff --git a/utils/sl/images.texy b/utils/sl/images.texy index 79bed05a2f..3af7d1c59d 100644 --- a/utils/sl/images.texy +++ b/utils/sl/images.texy @@ -17,6 +17,7 @@ Naslednji primeri predpostavljajo, da je definiran naslednji vzdevek razreda: ```php use Nette\Utils\Image; +use Nette\Utils\ImageColor; use Nette\Utils\ImageType; ``` @@ -33,7 +34,7 @@ $image = Image::fromBlank(100, 200); Po želji lahko določite barvo ozadja (privzeto je črna): ```php -$image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0)); +$image = Image::fromBlank(100, 200, ImageColor::rgb(125, 0, 0)); ``` Sliko lahko naložimo iz datoteke: @@ -191,16 +192,36 @@ $image->cropAuto(IMG_CROP_BLACK); Metoda `cropAuto()` je objektna enkapsulacija funkcije `imagecropauto()`, za več informacij si oglejte [njeno dokumentacijo |https://www.php.net/manual/en/function.imagecropauto]. +Barve .[#toc-colors] +==================== + +Z metodo `ImageColor::rgb()` lahko barvo določite z uporabo rdeče, zelene in modre (RGB) vrednosti. Po želji lahko določite tudi vrednost prosojnosti od 0 (popolnoma prosojno) do 1 (popolnoma neprosojno), tako kot v CSS. + +```php +$color = ImageColor::rgb(255, 0, 0); // Red +$transparentBlue = ImageColor::rgb(0, 0, 255, 0.5); // Semi-transparent blue +``` + +Metoda `ImageColor::hex()` vam omogoča, da barvo določite z uporabo šestnajstiške oblike, podobno kot v CSS. Podpira oblike `#rgb`, `#rrggbb`, `#rgba` in `#rrggbbaa`: + +```php +$color = ImageColor::hex("#F00"); // Red +$transparentGreen = ImageColor::hex("#00FF0080"); // Semi-transparent green +``` + +Barve lahko uporabite tudi v drugih metodah, kot so `ellipse()`, `fill()` itd. + + Risanje in urejanje .[#toc-drawing-and-editing] =============================================== -Lahko rišete, pišete, uporabljate vse funkcije PHP za delo s slikami, kot je [imagefilledellipse() |https://www.php.net/manual/en/function.imagefilledellipse.php], vendar v objektnem slogu: +Lahko rišete, pišete, uporabljate vse funkcije PHP za manipulacijo s slikami, glejte [Pregled metod |#Overview of methods], vendar v objektno usmerjenem ovoju: ```php -$image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63)); +$image->filledEllipse($centerX, $centerY, $width, $height, ImageColor::rgb(255, 0, 0)); ``` -Glejte [Pregled metod |#Overview of Methods]. +Ker so funkcije PHP za risanje pravokotnikov zaradi določanja koordinat nepraktične, razred `Image` ponuja njihove nadomestke v obliki funkcij [rectangleWH() |#rectangleWH()] in [filledRectangleWH() |#filledRectangleWH()]. Združitev več slik .[#toc-merge-multiple-images] @@ -210,7 +231,7 @@ V sliko lahko preprosto vstavite drugo sliko: ```php $logo = Image::fromFile('logo.png'); -$blank = Image::fromBlank(320, 240, Image::rgb(52, 132, 210)); +$blank = Image::fromBlank(320, 240, ImageColor::rgb(52, 132, 210)); // koordinate lahko nastavite tudi v odstotkih. $blank->place($logo, '80%', '80%'); // v desnem spodnjem kotu @@ -229,8 +250,8 @@ Pregled metod .[#toc-overview-of-methods] ========================================= -static fromBlank(int $width, int $height, array $color=null): Image .[method] ------------------------------------------------------------------------------ +static fromBlank(int $width, int $height, ImageColor $color=null): Image .[method] +---------------------------------------------------------------------------------- Ustvari novo pravo barvno sliko danih dimenzij. Privzeta barva je črna. @@ -244,9 +265,9 @@ static fromString(string $s, int &$detectedFormat=null): Image .[method] Preberi sliko iz niza in vrne njeno [vrsto |#Formats] v `$detectedFormat`. -static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method] ---------------------------------------------------------------------------------- -Ustvari barvo, ki jo lahko uporabite v drugih metodah, kot so `ellipse()`, `fill()` in tako naprej. +static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated] +--------------------------------------------------------------------------------------------- +To funkcijo je nadomestil razred `ImageColor`, glejte [barve |#Colors]. static typeToExtension(int $type): string .[method] @@ -279,6 +300,11 @@ static isTypeSupported(int $type): bool .[method] Ugotovi, ali je dana [vrsta |#Formats] slike podprta. +static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method] +------------------------------------------------------------------------------------------------------------------------ +Izračuna dimenzije pravokotnika, ki obkroža besedilo v določeni pisavi in velikosti. Vrne asociativno polje, ki vsebuje ključe `left`, `top`, `width`, `height`. Levi rob je lahko negativen, če se besedilo začne z levim previsom. + + affine(array $affine, array $clip=null): Image .[method] -------------------------------------------------------- Vrne sliko, ki vsebuje afino transformirano sliko src z uporabo neobveznega območja obrezovanja. ([več |https://www.php.net/manual/en/function.imageaffine]). @@ -306,21 +332,11 @@ Aktivirajte metode hitrega risanja z izravnavo za črte in žične poligone. Ne Uporaba izravnanih primitivov s prozorno barvo ozadja lahko privede do nepričakovanih rezultatov. Metoda mešanja uporablja barvo ozadja kot vse druge barve. Pomanjkanje podpore za komponento alfa ne omogoča metode za izravnavo na podlagi alfa. ([več |https://www.php.net/manual/en/function.imageantialias]) -arc(int $x, int $y, int $w, int $h, int $start, int $end, int $color): void .[method] -------------------------------------------------------------------------------------- +arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color): void .[method] +--------------------------------------------------------------------------------------------------------------------------- Nariše lok kroga s središčem na danih koordinatah. ([več |https://www.php.net/manual/en/function.imagearc]) -char(int $font, int $x, int $y, string $char, int $color): void .[method] -------------------------------------------------------------------------- -Nariše prvi znak `$char` na sliki z zgornjim levim delom na `$x`,`$y` (zgornji levi del je 0, 0) z barvo `$color`. ([več |https://www.php.net/manual/en/function.imagechar]) - - -charUp(int $font, int $x, int $y, string $char, int $color): void .[method] ---------------------------------------------------------------------------- -Nariše znak `$char` navpično na določeno koordinato na dani sliki. ([več |https://www.php.net/manual/en/function.imagecharup]) - - colorAllocate(int $red, int $green, int $blue): int .[method] ------------------------------------------------------------- Vrne identifikator barve, ki predstavlja barvo, sestavljeno iz danih komponent RGB. Klicati ga je treba za ustvarjanje vsake barve, ki bo uporabljena v sliki. ([več |https://www.php.net/manual/en/function.imagecolorallocate]) @@ -447,43 +463,48 @@ crop(int|string $left, int|string $top, int|string $width, int|string $height): Obreže sliko na podano pravokotno območje. Dimenzije lahko posredujete kot cela števila v pikslih ali kot nize v odstotkih (npr. `'50%'`). -cropAuto(int $mode=-1, float $threshold=.5, int $color=-1): Image .[method] ---------------------------------------------------------------------------- +cropAuto(int $mode=-1, float $threshold=.5, ?ImageColor $color=null): Image .[method] +------------------------------------------------------------------------------------- Samodejno obreže sliko v skladu z danim `$mode`. ([več |https://www.php.net/manual/en/function.imagecropauto]) -ellipse(int $cx, int $cy, int $w, int $h, int $color): void .[method] ---------------------------------------------------------------------- +ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method] +----------------------------------------------------------------------------------------------- Nariše elipso s središčem na določenih koordinatah. ([več |https://www.php.net/manual/en/function.imageellipse]) -fill(int $x, int $y, int $color): void .[method] ------------------------------------------------- +fill(int $x, int $y, ImageColor $color): void .[method] +------------------------------------------------------- Izvede zapolnitev z zalivko, ki se začne na dani koordinati (levo zgoraj je 0, 0) z danim `$color` v sliki. ([več |https://www.php.net/manual/en/function.imagefill]) -filledArc(int $cx, int $cy, int $w, int $h, int $s, int $e, int $color, int $style): void .[method] ---------------------------------------------------------------------------------------------------- +filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style): void .[method] +--------------------------------------------------------------------------------------------------------------------------------------------- Nariše delni lok s središčem na določeni koordinati na sliki. ([več |https://www.php.net/manual/en/function.imagefilledarc]) -filledEllipse(int $cx, int $cy, int $w, int $h, int $color): void .[method] ---------------------------------------------------------------------------- +filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method] +----------------------------------------------------------------------------------------------------- Nariše elipso s središčem na določeni koordinati na sliki. ([več |https://www.php.net/manual/en/function.imagefilledellipse]) -filledPolygon(array $points, int $numPoints, int $color): void .[method] ------------------------------------------------------------------------- +filledPolygon(array $points, ImageColor $color): void .[method] +--------------------------------------------------------------- Ustvari zapolnjen poligon v $sliki. ([več |https://www.php.net/manual/en/function.imagefilledpolygon]) -filledRectangle(int $x1, int $y1, int $x2, int $y2, int $color): void .[method] -------------------------------------------------------------------------------- -Ustvari pravokotnik, zapolnjen s `$color` na sliki, ki se začne v točki 1 in konča v točki 2. 0, 0 je zgornji levi kot slike. ([več |https://www.php.net/manual/en/function.imagefilledrectangle]) +filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------- +Ustvari pravokotnik, zapolnjen s `$color` na sliki, ki se začne pri `$x1` in `$y1` ter konča pri `$x2` in `$y2`. Točka 0, 0 je zgornji levi vogal slike. ([več) |https://www.php.net/manual/en/function.imagefilledrectangle] -fillToBorder(int $x, int $y, int $border, int $color): void .[method] ---------------------------------------------------------------------- +filledRectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------------------- +Ustvari pravokotnik, zapolnjen s `$color` na sliki, ki se začne v točki `$left` in `$top`, s širino `$width` in višino `$height`. Točka 0, 0 je zgornji levi vogal slike. + + +fillToBorder(int $x, int $y, int $border, ImageColor $color): void .[method] +---------------------------------------------------------------------------- Izvede zalivko, katere barva roba je določena s `$border`. Začetna točka za zapolnitev je `$x`, `$y` (levo zgoraj je 0, 0), območje pa je zapolnjeno z barvo `$color`. ([več |https://www.php.net/manual/en/function.imagefilltoborder]) @@ -497,9 +518,9 @@ flip(int $mode): void .[method] Obrne sliko z uporabo danega `$mode`. ([več |https://www.php.net/manual/en/function.imageflip]) -ftText(int $size, int $angle, int $x, int $y, int $col, string $fontFile, string $text, array $extrainfo=null): array .[method] -------------------------------------------------------------------------------------------------------------------------------- -Besedilo v sliko zapišite s pisavami FreeType 2. ([več |https://www.php.net/manual/en/function.imagefttext]) +ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method] +---------------------------------------------------------------------------------------------------------------------------------------- +Napišite besedilo na sliko. ([več) |https://www.php.net/manual/en/function.imagefttext] gammaCorrect(float $inputgamma, float $outputgamma): void .[method] @@ -542,13 +563,13 @@ layerEffect(int $effect): void .[method] Nastavite zastavico mešanja alfa, če želite uporabiti učinke plastenja. ([več |https://www.php.net/manual/en/function.imagelayereffect]) -line(int $x1, int $y1, int $x2, int $y2, int $color): void .[method] --------------------------------------------------------------------- +line(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +--------------------------------------------------------------------------- Nariše črto med dvema danima točkama. ([več |https://www.php.net/manual/en/function.imageline]) -openPolygon(array $points, int $numPoints, int $color): void .[method] ----------------------------------------------------------------------- +openPolygon(array $points, ImageColor $color): void .[method] +------------------------------------------------------------- Na sliko nariše odprt poligon. V nasprotju s spletno stranjo `polygon()` med zadnjo in prvo točko ni potegnjena črta. ([več |https://www.php.net/manual/en/function.imageopenpolygon]) @@ -567,16 +588,21 @@ place(Image $image, int|string $left=0, int|string $top=0, int $opacity=100): Im Kopira `$image` v sliko na koordinatah `$left` in `$top`. Koordinate lahko posredujete kot cela števila v pikslih ali kot nize v odstotkih (npr. `'50%'`). -polygon(array $points, int $numPoints, int $color): void .[method] ------------------------------------------------------------------- +polygon(array $points, ImageColor $color): void .[method] +--------------------------------------------------------- Ustvari poligon na sliki. ([več |https://www.php.net/manual/en/function.imagepolygon]) -rectangle(int $x1, int $y1, int $x2, int $y2, int $col): void .[method] ------------------------------------------------------------------------ +rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +-------------------------------------------------------------------------------- Ustvari pravokotnik, ki se začne na določenih koordinatah. ([več |https://www.php.net/manual/en/function.imagerectangle]) +rectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------------- +Ustvari pravokotnik na danih koordinatah. + + resize(int|string $width, int|string $height, int $flags=Image::OrSmaller): Image .[method] ------------------------------------------------------------------------------------------- Skaliranje slike, glejte [več informacij |#Image Resize]. Dimenzije lahko posredujete kot cela števila v pikslih ali kot nize v odstotkih (npr. `'50%'`). @@ -638,8 +664,8 @@ setInterpolation(int $method=IMG_BILINEAR_FIXED): void .[method] Nastavi metodo interpolacije, ki vpliva na metodi `rotate()` in `affine()`. ([več |https://www.php.net/manual/en/function.imagesetinterpolation]) -setPixel(int $x, int $y, int $color): void .[method] ----------------------------------------------------- +setPixel(int $x, int $y, ImageColor $color): void .[method] +----------------------------------------------------------- Nariše piksel na določeni koordinati. ([več |https://www.php.net/manual/en/function.imagesetpixel]) @@ -668,16 +694,6 @@ Nekoliko izostri sliko. Zahteva razširitev *Bundled GD extension*, zato ni gotovo, da bo delovala povsod. -string(int $font, int $x, int $y, string $str, int $col): void .[method] ------------------------------------------------------------------------- -Nariše niz na danih koordinatah. ([več |https://www.php.net/manual/en/function.imagestring]) - - -stringUp(int $font, int $x, int $y, string $s, int $col): void .[method] ------------------------------------------------------------------------- -Vertikalno nariše niz na danih koordinatah. ([več |https://www.php.net/manual/en/function.imagestringup]) - - toString(int $type=ImageType::JPEG, int $quality=null): string .[method] ------------------------------------------------------------------------ Izpiše sliko v niz. @@ -690,6 +706,6 @@ trueColorToPalette(bool $dither, int $ncolors): void .[method] Pretvori sliko truecolor v sliko palete. ([več |https://www.php.net/manual/en/function.imagetruecolortopalette]) -ttfText(int $size, int $angle, int $x, int $y, int $color, string $fontfile, string $text): array .[method] ------------------------------------------------------------------------------------------------------------ -V sliko zapiše podano besedilo z uporabo pisav TrueType. ([več |https://www.php.net/manual/en/function.imagettftext]) +ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method] +----------------------------------------------------------------------------------------------------------------------------------------- +V sliko zapiše podano besedilo. ([več) |https://www.php.net/manual/en/function.imagettftext] diff --git a/utils/tr/images.texy b/utils/tr/images.texy index 2e7c3b2ed0..fafc8c5deb 100644 --- a/utils/tr/images.texy +++ b/utils/tr/images.texy @@ -17,6 +17,7 @@ Aşağıdaki örneklerde, aşağıdaki sınıf takma adının tanımlandığı v ```php use Nette\Utils\Image; +use Nette\Utils\ImageColor; use Nette\Utils\ImageType; ``` @@ -33,7 +34,7 @@ $image = Image::fromBlank(100, 200); İsteğe bağlı olarak bir arka plan rengi belirtebilirsiniz (varsayılan renk siyahtır): ```php -$image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0)); +$image = Image::fromBlank(100, 200, ImageColor::rgb(125, 0, 0)); ``` Ya da görüntüyü bir dosyadan yükleriz: @@ -191,16 +192,36 @@ $image->cropAuto(IMG_CROP_BLACK); `cropAuto()` yöntemi, `imagecropauto()` işlevinin bir nesne kapsüllemesidir, daha fazla bilgi için [belgelerine |https://www.php.net/manual/en/function.imagecropauto] bakın. +Renkler .[#toc-colors] +====================== + + `ImageColor::rgb()` yöntemi, kırmızı, yeşil ve mavi (RGB) değerlerini kullanarak bir renk tanımlamanıza olanak tanır. İsteğe bağlı olarak, CSS'de olduğu gibi 0 (tamamen saydam) ile 1 (tamamen opak) arasında değişen bir saydamlık değeri de belirtebilirsiniz. + +```php +$color = ImageColor::rgb(255, 0, 0); // Red +$transparentBlue = ImageColor::rgb(0, 0, 255, 0.5); // Semi-transparent blue +``` + + `ImageColor::hex()` yöntemi, CSS'ye benzer şekilde onaltılık biçimi kullanarak bir renk tanımlamanıza olanak tanır. `#rgb` , `#rrggbb`, `#rgba` ve `#rrggbbaa` biçimlerini destekler: + +```php +$color = ImageColor::hex("#F00"); // Red +$transparentGreen = ImageColor::hex("#00FF0080"); // Semi-transparent green +``` + +Renkler `ellipse()`, `fill()`, vb. gibi diğer yöntemlerde de kullanılabilir. + + Çizim ve Düzenleme .[#toc-drawing-and-editing] ============================================== -Çizebilir, yazabilir, [imagefilledellipse() |https://www.php.net/manual/en/function.imagefilledellipse.php] gibi resimlerle çalışmak için tüm PHP işlevlerini kullanabilirsiniz, ancak nesne stilini kullanarak: +Çizebilir, yazabilir, resim işleme için tüm PHP işlevlerini kullanabilirsiniz, bkz. [yöntemlere genel bakış |#Overview of methods], ancak nesne yönelimli bir sarmalayıcı içinde: ```php -$image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63)); +$image->filledEllipse($centerX, $centerY, $width, $height, ImageColor::rgb(255, 0, 0)); ``` -[Yöntemlere Genel Bakış |#Overview of Methods] bölümüne bakınız. +Dikdörtgen çizmek için PHP işlevleri koordinat belirtmek nedeniyle pratik olmadığından, `Image` sınıfı bunların yerine [rectangleWH() |#rectangleWH()] ve [filledRectangleWH() |#filledRectangleWH()] işlevlerini sunar. Birden Fazla Görüntüyü Birleştirme .[#toc-merge-multiple-images] @@ -210,7 +231,7 @@ Görüntünün içine kolayca başka bir görüntü yerleştirebilirsiniz: ```php $logo = Image::fromFile('logo.png'); -$blank = Image::fromBlank(320, 240, Image::rgb(52, 132, 210)); +$blank = Image::fromBlank(320, 240, ImageColor::rgb(52, 132, 210)); // koordinatlar yüzde olarak da ayarlanabilir $blank->place($logo, '80%', '80%'); // sağ alt köşeye yakın @@ -229,8 +250,8 @@ Yöntemlere Genel Bakış .[#toc-overview-of-methods] ================================================== -static fromBlank(int $width, int $height, array $color=null): Image .[method] ------------------------------------------------------------------------------ +static fromBlank(int $width, int $height, ImageColor $color=null): Image .[method] +---------------------------------------------------------------------------------- Verilen boyutlarda yeni bir gerçek renkli görüntü oluşturur. Varsayılan renk siyahtır. @@ -244,9 +265,9 @@ static fromString(string $s, int &$detectedFormat=null): Image .[method] Bir dizeden bir görüntü okur ve [türünü |#Formats] `$detectedFormat` olarak döndürür. -static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method] ---------------------------------------------------------------------------------- -`ellipse()`, `fill()` gibi diğer yöntemlerde kullanılabilecek bir renk oluşturur. +static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated] +--------------------------------------------------------------------------------------------- +Bu özellik `ImageColor` sınıfı ile değiştirilmiştir, bkz. [renkler |#Colors]. static typeToExtension(int $type): string .[method] @@ -279,6 +300,11 @@ static isTypeSupported(int $type): bool .[method] Verilen görüntü [türünün |#Formats] desteklenip desteklenmediğini belirler. +static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method] +------------------------------------------------------------------------------------------------------------------------ +Metni belirtilen yazı tipi ve boyutta çevreleyen dikdörtgenin boyutlarını hesaplar. `left` , `top`, `width`, `height` anahtarlarını içeren bir ilişkisel dizi döndürür. Metin sola doğru bir çıkıntıyla başlıyorsa, sol kenar boşluğu negatif olabilir. + + affine(array $affine, array $clip=null): Image .[method] -------------------------------------------------------- İsteğe bağlı bir kırpma alanı kullanarak, afin dönüşümü yapılmış src görüntüsünü içeren bir görüntü döndürür. ([daha fazla |https://www.php.net/manual/en/function.imageaffine]). @@ -306,21 +332,11 @@ antialias(bool $on): void .[method] Şeffaf arka plan rengiyle kenar yumuşatılmış ilkel öğelerin kullanılması bazı beklenmedik sonuçlara yol açabilir. Karışım yöntemi, arka plan rengini diğer renkler gibi kullanır. Alfa bileşeni desteğinin olmaması, alfa tabanlı bir kenar yumuşatma yöntemine izin vermez. ([daha fazla |https://www.php.net/manual/en/function.imageantialias]) -arc(int $x, int $y, int $w, int $h, int $start, int $end, int $color): void .[method] -------------------------------------------------------------------------------------- +arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color): void .[method] +--------------------------------------------------------------------------------------------------------------------------- Verilen koordinatları merkez alan bir daire yayı çizer. ([daha fazla |https://www.php.net/manual/en/function.imagearc]) -char(int $font, int $x, int $y, string $char, int $color): void .[method] -------------------------------------------------------------------------- -Görüntüdeki `$char` öğesinin ilk karakterini sol üst köşesi `$x`,`$y` (sol üst köşesi 0, 0) olacak şekilde `$color` rengiyle çizer. ([daha fazla |https://www.php.net/manual/en/function.imagechar]) - - -charUp(int $font, int $x, int $y, string $char, int $color): void .[method] ---------------------------------------------------------------------------- -Verilen görüntü üzerinde belirtilen koordinatta `$char` karakterini dikey olarak çizer. ([daha fazla |https://www.php.net/manual/en/function.imagecharup]) - - colorAllocate(int $red, int $green, int $blue): int .[method] ------------------------------------------------------------- Verilen RGB bileşenlerinden oluşan rengi temsil eden bir renk tanımlayıcısı döndürür. Görüntüde kullanılacak her bir rengi oluşturmak için çağrılmalıdır. ([daha fazla |https://www.php.net/manual/en/function.imagecolorallocate]) @@ -447,43 +463,48 @@ crop(int|string $left, int|string $top, int|string $width, int|string $height): Bir görüntüyü verilen dikdörtgen alana kırpar. Boyutlar piksel cinsinden tamsayılar veya yüzde cinsinden dizeler olarak aktarılabilir (örn. `'50%'`). -cropAuto(int $mode=-1, float $threshold=.5, int $color=-1): Image .[method] ---------------------------------------------------------------------------- +cropAuto(int $mode=-1, float $threshold=.5, ?ImageColor $color=null): Image .[method] +------------------------------------------------------------------------------------- Bir görüntüyü verilen `$mode` adresine göre otomatik olarak kırpar. ([daha fazla |https://www.php.net/manual/en/function.imagecropauto]) -ellipse(int $cx, int $cy, int $w, int $h, int $color): void .[method] ---------------------------------------------------------------------- +ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method] +----------------------------------------------------------------------------------------------- Belirtilen koordinatlarda ortalanmış bir elips çizer. ([daha fazla |https://www.php.net/manual/en/function.imageellipse]) -fill(int $x, int $y, int $color): void .[method] ------------------------------------------------- +fill(int $x, int $y, ImageColor $color): void .[method] +------------------------------------------------------- Verilen koordinattan başlayarak (sol üst 0, 0'dır) görüntüde verilen `$color` ile bir sel dolgusu gerçekleştirir. ([daha fazla |https://www.php.net/manual/en/function.imagefill]) -filledArc(int $cx, int $cy, int $w, int $h, int $s, int $e, int $color, int $style): void .[method] ---------------------------------------------------------------------------------------------------- +filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style): void .[method] +--------------------------------------------------------------------------------------------------------------------------------------------- Görüntüde belirtilen koordinatı merkez alan kısmi bir yay çizer. ([daha fazla |https://www.php.net/manual/en/function.imagefilledarc]) -filledEllipse(int $cx, int $cy, int $w, int $h, int $color): void .[method] ---------------------------------------------------------------------------- +filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method] +----------------------------------------------------------------------------------------------------- Görüntüde belirtilen koordinatı merkez alan bir elips çizer. ([daha fazla |https://www.php.net/manual/en/function.imagefilledellipse]) -filledPolygon(array $points, int $numPoints, int $color): void .[method] ------------------------------------------------------------------------- +filledPolygon(array $points, ImageColor $color): void .[method] +--------------------------------------------------------------- Resim içinde dolu bir çokgen oluşturur. ([daha fazla |https://www.php.net/manual/en/function.imagefilledpolygon]) -filledRectangle(int $x1, int $y1, int $x2, int $y2, int $color): void .[method] -------------------------------------------------------------------------------- -Görüntüde 1 noktasından başlayıp 2 noktasında biten `$color` ile doldurulmuş bir dikdörtgen oluşturur. 0, 0 görüntünün sol üst köşesidir. ([daha fazla |https://www.php.net/manual/en/function.imagefilledrectangle]) +filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------- +Görüntüde `$x1` & `$y1` adresinden başlayıp `$x2` & `$y2` adresinde biten `$color` ile doldurulmuş bir dikdörtgen oluşturur. 0, 0 noktası görüntünün sol üst köşesidir. ([daha fazla |https://www.php.net/manual/en/function.imagefilledrectangle]) -fillToBorder(int $x, int $y, int $border, int $color): void .[method] ---------------------------------------------------------------------- +filledRectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------------------- +Görüntüde `$left` & `$top` noktasından başlayarak genişliği `$width` ve yüksekliği `$height` olan `$color` ile doldurulmuş bir dikdörtgen oluşturur. 0, 0 noktası görüntünün sol üst köşesidir. + + +fillToBorder(int $x, int $y, int $border, ImageColor $color): void .[method] +---------------------------------------------------------------------------- Kenarlık rengi `$border` tarafından tanımlanan bir taşma dolgusu gerçekleştirir. Dolgu için başlangıç noktası `$x`, `$y` (sol üst 0, 0'dır) ve bölge `$color` rengi ile doldurulur. ([daha fazla |https://www.php.net/manual/en/function.imagefilltoborder]) @@ -497,9 +518,9 @@ flip(int $mode): void .[method] Verilen `$mode` adresini kullanarak görüntüyü çevirir. ([daha fazla |https://www.php.net/manual/en/function.imageflip]) -ftText(int $size, int $angle, int $x, int $y, int $col, string $fontFile, string $text, array $extrainfo=null): array .[method] -------------------------------------------------------------------------------------------------------------------------------- -FreeType 2 kullanan yazı tiplerini kullanarak görüntüye metin yazın. ([daha fazla |https://www.php.net/manual/en/function.imagefttext]) +ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method] +---------------------------------------------------------------------------------------------------------------------------------------- +Resimdeki metni yazın. ([daha fazla |https://www.php.net/manual/en/function.imagefttext]) gammaCorrect(float $inputgamma, float $outputgamma): void .[method] @@ -542,13 +563,13 @@ layerEffect(int $effect): void .[method] Katmanlama efektlerini kullanmak için alfa karıştırma bayrağını ayarlayın. ([daha fazla |https://www.php.net/manual/en/function.imagelayereffect]) -line(int $x1, int $y1, int $x2, int $y2, int $color): void .[method] --------------------------------------------------------------------- +line(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +--------------------------------------------------------------------------- Verilen iki nokta arasında bir çizgi çizer. ([daha fazla |https://www.php.net/manual/en/function.imageline]) -openPolygon(array $points, int $numPoints, int $color): void .[method] ----------------------------------------------------------------------- +openPolygon(array $points, ImageColor $color): void .[method] +------------------------------------------------------------- Görüntü üzerine açık bir çokgen çizer. `polygon()` 'un aksine, son nokta ile ilk nokta arasında bir çizgi çizilmez. ([daha fazla |https://www.php.net/manual/en/function.imageopenpolygon]) @@ -567,16 +588,21 @@ place(Image $image, int|string $left=0, int|string $top=0, int $opacity=100): Im `$image` adresini `$left` ve `$top` koordinatlarındaki görüntüye kopyalar. Koordinatlar piksel cinsinden tamsayılar veya yüzde cinsinden dizeler olarak aktarılabilir (örn. `'50%'`). -polygon(array $points, int $numPoints, int $color): void .[method] ------------------------------------------------------------------- +polygon(array $points, ImageColor $color): void .[method] +--------------------------------------------------------- Görüntüde bir çokgen oluşturur. ([daha fazla |https://www.php.net/manual/en/function.imagepolygon]) -rectangle(int $x1, int $y1, int $x2, int $y2, int $col): void .[method] ------------------------------------------------------------------------ +rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +-------------------------------------------------------------------------------- Belirtilen koordinatlardan başlayan bir dikdörtgen oluşturur. ([daha fazla |https://www.php.net/manual/en/function.imagerectangle]) +rectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------------- +Verilen koordinatlarda bir dikdörtgen oluşturur. + + resize(int|string $width, int|string $height, int $flags=Image::OrSmaller): Image .[method] ------------------------------------------------------------------------------------------- Bir görüntüyü ölçeklendirir, [daha fazla bilgi |#Image Resize] için bkz. Boyutlar piksel cinsinden tamsayılar veya yüzde cinsinden dizeler olarak aktarılabilir (örn. `'50%'`). @@ -638,8 +664,8 @@ setInterpolation(int $method=IMG_BILINEAR_FIXED): void .[method] `rotate()` ve `affine()` yöntemlerini etkileyen enterpolasyon yöntemini ayarlar. ([daha fazla |https://www.php.net/manual/en/function.imagesetinterpolation]) -setPixel(int $x, int $y, int $color): void .[method] ----------------------------------------------------- +setPixel(int $x, int $y, ImageColor $color): void .[method] +----------------------------------------------------------- Belirtilen koordinatta bir piksel çizer. ([devamı |https://www.php.net/manual/en/function.imagesetpixel]) @@ -668,16 +694,6 @@ Görüntüyü biraz keskinleştirir. Paketlenmiş GD uzantısı* gerektirir, bu nedenle her yerde çalışacağından emin değiliz. -string(int $font, int $x, int $y, string $str, int $col): void .[method] ------------------------------------------------------------------------- -Verilen koordinatlarda bir dize çizer. ([daha fazla |https://www.php.net/manual/en/function.imagestring]) - - -stringUp(int $font, int $x, int $y, string $s, int $col): void .[method] ------------------------------------------------------------------------- -Verilen koordinatlarda dikey olarak bir dize çizer. ([daha fazla |https://www.php.net/manual/en/function.imagestringup]) - - toString(int $type=ImageType::JPEG, int $quality=null): string .[method] ------------------------------------------------------------------------ Bir görüntüyü dizeye çıktı olarak verir. @@ -690,6 +706,6 @@ trueColorToPalette(bool $dither, int $ncolors): void .[method] Bir gerçek renkli görüntüyü bir palet görüntüsüne dönüştürür. ([daha fazla |https://www.php.net/manual/en/function.imagetruecolortopalette]) -ttfText(int $size, int $angle, int $x, int $y, int $color, string $fontfile, string $text): array .[method] ------------------------------------------------------------------------------------------------------------ -TrueType yazı tiplerini kullanarak verilen metni görüntüye yazar. ([daha fazla |https://www.php.net/manual/en/function.imagettftext]) +ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method] +----------------------------------------------------------------------------------------------------------------------------------------- +Verilen metni resmin içine yazar. ([daha fazla |https://www.php.net/manual/en/function.imagettftext]) diff --git a/utils/uk/images.texy b/utils/uk/images.texy index eb9439afac..398fc1253e 100644 --- a/utils/uk/images.texy +++ b/utils/uk/images.texy @@ -17,6 +17,7 @@ composer require nette/utils ```php use Nette\Utils\Image; +use Nette\Utils\ImageColor; use Nette\Utils\ImageType; ``` @@ -33,7 +34,7 @@ $image = Image::fromBlank(100, 200); За бажанням можна вказати колір фону (за замовчуванням чорний): ```php -$image = Image::fromBlank(100, 200, Image::rgb(125, 0, 0)); +$image = Image::fromBlank(100, 200, ImageColor::rgb(125, 0, 0)); ``` Або завантажте зображення з файлу: @@ -191,16 +192,36 @@ $image->cropAuto(IMG_CROP_BLACK); Метод `cropAuto()` є об'єктною заміною функції `imagecropauto()`, більш детальну інформацію див. у [документації до неї |https://www.php.net/manual/en/function.imagecropauto]. +Кольори .[#toc-colors] +====================== + +Метод `ImageColor::rgb()` дозволяє визначити колір за допомогою значень червоного, зеленого та синього (RGB). За бажанням, ви також можете вказати значення прозорості в діапазоні від 0 (повністю прозорий) до 1 (повністю непрозорий), так само, як і в CSS. + +```php +$color = ImageColor::rgb(255, 0, 0); // Red +$transparentBlue = ImageColor::rgb(0, 0, 255, 0.5); // Semi-transparent blue +``` + +Метод `ImageColor::hex()` дозволяє визначити колір за допомогою шістнадцяткового формату, подібно до CSS. Він підтримує формати `#rgb`, `#rrggbb`, `#rgba` і `#rrggbbaa`: + +```php +$color = ImageColor::hex("#F00"); // Red +$transparentGreen = ImageColor::hex("#00FF0080"); // Semi-transparent green +``` + +Кольори можна використовувати і в інших методах, таких як `ellipse()`, `fill()` тощо. + + Малювання та редагування .[#toc-drawing-and-editing] ==================================================== -Ви можете малювати, можете писати, але не рвіть сторінки. Усі функції PHP для роботи із зображеннями, такі як [imagefilledellipse |https://www.php.net/manual/en/function.imagefilledellipse.php], доступні вам, але в об'єктно-орієнтованому образі: +Ви можете малювати, можете писати, можете використовувати всі функції PHP для маніпулювання зображеннями, див. [Огляд методів |#Overview of methods], але в об'єктно-орієнтованій обгортці: ```php -$image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63)); +$image->filledEllipse($centerX, $centerY, $width, $height, ImageColor::rgb(255, 0, 0)); ``` -Див. розділ [Огляд методів |#Overview-of-Methods]. +Оскільки функції PHP для малювання прямокутників непрактичні через необхідність вказувати координати, клас `Image` пропонує їх заміну у вигляді функцій [rectangleWH( |#rectangleWH()] ) і [filledRectangleWH( |#filledRectangleWH()]). Об'єднання декількох зображень .[#toc-merge-multiple-images] @@ -210,7 +231,7 @@ $image->filledEllipse($cx, $cy, $width, $height, Image::rgb(255, 0, 0, 63)); ```php $logo = Image::fromFile('logo.png'); -$blank = Image::fromBlank(320, 240, Image::rgb(52, 132, 210)); +$blank = Image::fromBlank(320, 240, ImageColor::rgb(52, 132, 210)); // координати можуть бути знову задані у відсотках $blank->place($logo, '80%', '80%'); // вставте в правий нижній кут @@ -229,8 +250,8 @@ $blank->place($image, '80%', '80%', 25); // прозорість станови ========================================= -static fromBlank(int $width, int $height, array $color=null): Image .[method] ------------------------------------------------------------------------------ +static fromBlank(int $width, int $height, ImageColor $color=null): Image .[method] +---------------------------------------------------------------------------------- Створює нове істинно кольорове зображення заданих розмірів. За замовчуванням використовується чорний колір. @@ -244,9 +265,9 @@ static fromString(string $s, int &$detectedFormat=null): Image .[method] Читає зображення з рядка і повертає його [тип |#Formats] в `$detectedFormat`. -static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method] ---------------------------------------------------------------------------------- -Створює колір, який може бути використаний в інших методах, таких як `ellipse()`, `fill()` тощо. +static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated] +--------------------------------------------------------------------------------------------- +Ця функція була замінена на клас `ImageColor`, див. [кольори |#Colors]. static typeToExtension(int $type): string .[method] @@ -279,6 +300,11 @@ static isTypeSupported(int $type): bool .[method] Визначає, чи підтримується даний [тип |#Formats] зображення. +static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method] +------------------------------------------------------------------------------------------------------------------------ +Обчислює розміри прямокутника, який охоплює текст заданого шрифту та розміру. Повертає асоціативний масив, що містить ключі `left`, `top`, `width`, `height`. Ліве поле може бути від'ємним, якщо текст починається з лівого відступу. + + affine(array $affine, array $clip=null): Image .[method] -------------------------------------------------------- Повертає зображення, що містить афінно-трансформоване зображення src з використанням необов'язкової області обрізання. ([докладніше |https://www.php.net/manual/en/function.imageaffine]). @@ -306,21 +332,11 @@ antialias(bool $on): void .[method] Використання згладженого примітиву з прозорим кольором фону може призвести до несподіваних результатів. Метод змішування використовує колір фону як будь-який інший колір. ([докладніше |https://www.php.net/manual/en/function.imageantialias]) -arc(int $x, int $y, int $w, int $h, int $start, int $end, int $color): void .[method] -------------------------------------------------------------------------------------- +arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color): void .[method] +--------------------------------------------------------------------------------------------------------------------------- Малює дугу кола з центром у заданих координатах. ([докладніше |https://www.php.net/manual/en/function.imagearc]) -char(int $font, int $x, int $y, string $char, int $color): void .[method] -------------------------------------------------------------------------- -Намалює перший символ `$char` у зображенні з лівим верхнім кутом `$x`, `$y` (лівий верхній кут дорівнює 0, 0) кольором `$color`. ([докладніше |https://www.php.net/manual/en/function.imagechar]) - - -charUp(int $font, int $x, int $y, string $char, int $color): void .[method] ---------------------------------------------------------------------------- -Малює символ `$char` вертикально за вказаною координатою в заданому зображенні. ([докладніше |https://www.php.net/manual/en/function.imagecharup]) - - colorAllocate(int $red, int $green, int $blue): int .[method] ------------------------------------------------------------- Повертає ідентифікатор кольору, що представляє колір, який складається із заданих компонентів RGB. Повинен бути викликаний для створення кожного кольору, який буде використовуватися в зображенні. ([докладніше |https://www.php.net/manual/en/function.imagecolorallocate]) @@ -447,43 +463,48 @@ crop(int|string $left, int|string $top, int|string $width, int|string $height): Обрізає зображення до заданої прямокутної області. Розміри можуть бути вказані як цілі числа в пікселях або рядки у відсотках (наприклад, `'50%'`). -cropAuto(int $mode=-1, float $threshold=.5, int $color=-1): Image .[method] ---------------------------------------------------------------------------- +cropAuto(int $mode=-1, float $threshold=.5, ?ImageColor $color=null): Image .[method] +------------------------------------------------------------------------------------- Автоматичне кадрування зображення відповідно до заданого `$mode`. ([докладніше |https://www.php.net/manual/en/function.imagecropauto]) -ellipse(int $cx, int $cy, int $w, int $h, int $color): void .[method] ---------------------------------------------------------------------- +ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method] +----------------------------------------------------------------------------------------------- Малює еліпс із центром у заданих координатах. ([докладніше |https://www.php.net/manual/en/function.imageellipse]) -fill(int $x, int $y, int $color): void .[method] ------------------------------------------------- +fill(int $x, int $y, ImageColor $color): void .[method] +------------------------------------------------------- Заповнює область, що починається в заданій координаті (зліва вгорі 0, 0), заданим `$color`. ([докладніше |https://www.php.net/manual/en/function.imagefill]) -filledArc(int $cx, int $cy, int $w, int $h, int $s, int $e, int $color, int $style): void .[method] ---------------------------------------------------------------------------------------------------- +filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style): void .[method] +--------------------------------------------------------------------------------------------------------------------------------------------- Малює неповну дугу з центром у заданих координатах. ([докладніше |https://www.php.net/manual/en/function.imagefilledarc]) -filledEllipse(int $cx, int $cy, int $w, int $h, int $color): void .[method] ---------------------------------------------------------------------------- +filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color): void .[method] +----------------------------------------------------------------------------------------------------- Малює еліпс із центром у заданих координатах. ([докладніше |https://www.php.net/manual/en/function.imagefilledellipse]) -filledPolygon(array $points, int $numPoints, int $color): void .[method] ------------------------------------------------------------------------- +filledPolygon(array $points, ImageColor $color): void .[method] +--------------------------------------------------------------- Створює заповнений багатокутник на зображенні. ([докладніше |https://www.php.net/manual/en/function.imagefilledpolygon]) -filledRectangle(int $x1, int $y1, int $x2, int $y2, int $color): void .[method] -------------------------------------------------------------------------------- -Створює прямокутник, заповнений `$color` на зображенні, починаючи з точки 1 і закінчуючи точкою 2. Точка 0, 0 - лівий верхній кут зображення. ([докладніше |https://www.php.net/manual/en/function.imagefilledrectangle]) +filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------- +Створює прямокутник, заповнений `$color` на зображенні, що починається з `$x1` та `$y1` і закінчується `$x2` та `$y2`. Точка 0, 0 є верхнім лівим кутом зображення. ([докладніше |https://www.php.net/manual/en/function.imagefilledrectangle]) -fillToBorder(int $x, int $y, int $border, int $color): void .[method] ---------------------------------------------------------------------- +filledRectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------------------- +Створює на зображенні прямокутник, заповнений `$color`, починаючи з точок `$left` та `$top` з шириною `$width` та висотою `$height`. Точка 0, 0 є верхнім лівим кутом зображення. + + +fillToBorder(int $x, int $y, int $border, ImageColor $color): void .[method] +---------------------------------------------------------------------------- Створює заливку, колір межі якої визначається `$border`. Початкова точка заливки - `$x`, `$y` (лівий верхній кут - 0, 0), а область заливається кольором `$color`. ([докладніше |https://www.php.net/manual/en/function.imagefilltoborder]) @@ -497,9 +518,9 @@ flip(int $mode): void .[method] Інвертує зображення за заданою адресою `$mode`. ([докладніше |https://www.php.net/manual/en/function.imageflip]) -ftText(int $size, int $angle, int $x, int $y, int $col, string $fontFile, string $text, array $extrainfo=null): array .[method] -------------------------------------------------------------------------------------------------------------------------------- -Пишіть текст на зображенні, використовуючи шрифти FreeType 2. ([докладніше |https://www.php.net/manual/en/function.imagefttext]) +ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method] +---------------------------------------------------------------------------------------------------------------------------------------- +Напишіть текст на картинці. ([більше |https://www.php.net/manual/en/function.imagefttext]) gammaCorrect(float $inputgamma, float $outputgamma): void .[method] @@ -542,13 +563,13 @@ layerEffect(int $effect): void .[method] Встановіть прапор альфа-змішання для використання ефектів нашарування. ([докладніше |https://www.php.net/manual/en/function.imagelayereffect]) -line(int $x1, int $y1, int $x2, int $y2, int $color): void .[method] --------------------------------------------------------------------- +line(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +--------------------------------------------------------------------------- Проводить лінію між двома заданими точками. ([докладніше |https://www.php.net/manual/en/function.imageline]) -openPolygon(array $points, int $numPoints, int $color): void .[method] ----------------------------------------------------------------------- +openPolygon(array $points, ImageColor $color): void .[method] +------------------------------------------------------------- Малює відкритий багатокутник на зображенні. На відміну від `polygon()`, між останньою і першою точкою не проводиться лінія. ([докладніше |https://www.php.net/manual/en/function.imageopenpolygon]) @@ -567,16 +588,21 @@ place(Image $image, int|string $left=0, int|string $top=0, int $opacity=100): Im Копіює `$image` у зображення за координатами `$left` і `$top`. Координати можуть бути вказані як цілі числа в пікселях або рядки у відсотках (наприклад, `'50%'`). -polygon(array $points, int $numPoints, int $color): void .[method] ------------------------------------------------------------------- +polygon(array $points, ImageColor $color): void .[method] +--------------------------------------------------------- Створює багатокутник на зображенні. ([докладніше |https://www.php.net/manual/en/function.imagepolygon]) -rectangle(int $x1, int $y1, int $x2, int $y2, int $col): void .[method] ------------------------------------------------------------------------ +rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color): void .[method] +-------------------------------------------------------------------------------- Створює прямокутник за заданими координатами. ([докладніше |https://www.php.net/manual/en/function.imagerectangle]) +rectangleWH(int $left, int $top, int $width, int $height, ImageColor $color): void .[method] +-------------------------------------------------------------------------------------------- +Створює прямокутник за заданими координатами. + + resize(int|string $width, int|string $height, int $flags=Image::OrSmaller): Image .[method] ------------------------------------------------------------------------------------------- Зміна розмірів зображення, [додаткова інформація |#Image-Resize]. Розміри можуть бути вказані як цілі числа в пікселях або рядки у відсотках (наприклад, `'50%'`). @@ -638,8 +664,8 @@ setInterpolation(int $method=IMG_BILINEAR_FIXED): void .[method] Задає метод інтерполяції, який впливає на методи `rotate()` і `affine()`. ([докладніше |https://www.php.net/manual/en/function.imagesetinterpolation]) -setPixel(int $x, int $y, int $color): void .[method] ----------------------------------------------------- +setPixel(int $x, int $y, ImageColor $color): void .[method] +----------------------------------------------------------- Малює піксель у вказаній координаті. ([докладніше |https://www.php.net/manual/en/function.imagesetpixel]) @@ -668,16 +694,6 @@ sharpen(): Image .[method] Вимагає наявності *Bundled GD extension*, тому може працювати не скрізь. -string(int $font, int $x, int $y, string $str, int $col): void .[method] ------------------------------------------------------------------------- -Виводить рядок за заданими координатами. ([докладніше |https://www.php.net/manual/en/function.imagestring]) - - -stringUp(int $font, int $x, int $y, string $s, int $col): void .[method] ------------------------------------------------------------------------- -Виводить рядок по вертикалі в заданих координатах. ([докладніше |https://www.php.net/manual/en/function.imagestringup]) - - toString(int $type=ImageType::JPEG, int $quality=null): string .[method] ------------------------------------------------------------------------ Зберігає зображення в рядку. @@ -690,6 +706,6 @@ trueColorToPalette(bool $dither, int $ncolors): void .[method] Перетворює truecolor зображення в палітру. ([докладніше |https://www.php.net/manual/en/function.imagetruecolortopalette]) -ttfText(int $size, int $angle, int $x, int $y, int $color, string $fontfile, string $text): array .[method] ------------------------------------------------------------------------------------------------------------ -Друкує заданий текст у зображення з використанням шрифтів TrueType. ([докладніше |https://www.php.net/manual/en/function.imagettftext]) +ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options=[]): array .[method] +----------------------------------------------------------------------------------------------------------------------------------------- +Записує заданий текст у зображення. ([докладніше |https://www.php.net/manual/en/function.imagettftext]) From 36171f621723d25c02b7be9517598460e8d742de Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 1 Nov 2023 13:49:28 +0100 Subject: [PATCH 033/137] php-generator: improved perex etc --- php-generator/bg/@home.texy | 21 +++++++++++++-------- php-generator/cs/@home.texy | 20 ++++++++++++-------- php-generator/de/@home.texy | 21 +++++++++++++-------- php-generator/el/@home.texy | 21 +++++++++++++-------- php-generator/en/@home.texy | 21 +++++++++++++-------- php-generator/es/@home.texy | 21 +++++++++++++-------- php-generator/fr/@home.texy | 21 +++++++++++++-------- php-generator/hu/@home.texy | 21 +++++++++++++-------- php-generator/it/@home.texy | 21 +++++++++++++-------- php-generator/ja/@home.texy | 21 +++++++++++++-------- php-generator/pl/@home.texy | 21 +++++++++++++-------- php-generator/pt/@home.texy | 21 +++++++++++++-------- php-generator/ro/@home.texy | 21 +++++++++++++-------- php-generator/ru/@home.texy | 21 +++++++++++++-------- php-generator/sl/@home.texy | 21 +++++++++++++-------- php-generator/tr/@home.texy | 21 +++++++++++++-------- php-generator/uk/@home.texy | 21 +++++++++++++-------- 17 files changed, 220 insertions(+), 136 deletions(-) diff --git a/php-generator/bg/@home.texy b/php-generator/bg/@home.texy index 6eda3b9886..84b1dd3580 100644 --- a/php-generator/bg/@home.texy +++ b/php-generator/bg/@home.texy @@ -2,11 +2,12 @@ ********************
    -- Трябва да генерирате PHP код за класове, функции, PHP файлове и др. -- Поддържа всички най-нови функции на PHP като енуми, атрибути и др. +Търсите ли инструмент за генериране на PHP код за класове, функции или цели файлове? + +- Поддържа всички най-нови функции на PHP (като enums и др.) - Позволява ви лесно да променяте съществуващи класове -- Изход, съвместим с PSR-12 / PER coding style -- Високо развита, стабилна и широко използвана библиотека +- Изход, съвместим със стила на кодиране PSR-12 / PER +- Зряла, стабилна и широко използвана библиотека
    @@ -509,6 +510,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer public bool $bracesOnNextLine = true; // поставяне на един параметър на един ред, дори ако той има атрибут или е повишен public bool $singleParameterOnOneLine = false; + // omits namespaces that do not contain any class or function + public bool $omitEmptyNamespaces = true; // разделител между дясната скоба и типа за връщане на функции и методи public string $returnTypeColon = ': '; } @@ -530,7 +533,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer use Nette\PhpGenerator\Type; $member->setType('array'); // или Type::Array; -$member->setType('array|string'); // или Type::union('array', 'string') +$member->setType('?array'); // or Type::nullable(Type::Array); +$member->setType('array|string'); // or Type::union(Type::Array, Type::String) $member->setType('Foo&Bar'); // или Type::intersection(Foo::class, Bar::class) $member->setType(null); // премахва тип ``` @@ -679,9 +683,8 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range' Преобразуване на имена на класове .[#toc-class-names-resolving] --------------------------------------------------------------- -**Когато класът е част от пространството от имена, той се визуализира по малко по-различен начин**: всички типове (т.е. подсказките за тип, типовете за връщане, името на родителския клас, -имплементирани интерфейси, използвани черти и атрибути) се решават автоматично* (освен ако не го изключите, вижте по-долу). -Това означава, че трябва да **използвате пълни имена на класове** в дефинициите и те ще бъдат заменени с псевдоними (в съответствие с декларациите за употреба) или с напълно квалифицирани имена в получения код: +**Когато един клас е част от пространство от имена, той се визуализира по малко по-различен начин:** всички типове (напр. подсказки за тип, типове връщане, име на родителския клас, имплементирани интерфейси, използвани черти и атрибути) се решават автоматично (освен ако не го изключите, вижте по-долу). +Това означава, че трябва да използвате **пълно квалифицирани имена на класове** в дефинициите и те ще бъдат заменени с псевдоними (въз основа на клаузи за използване) или напълно квалифицирани имена в получения код: ```php $namespace = new Nette\PhpGenerator\PhpNamespace('Foo'); @@ -777,6 +780,8 @@ function foo() } ``` +**Забележете:** Във файловете не може да се добавя допълнителен код извън функциите и класовете. + Генериране според съществуващите .[#toc-generating-according-to-existing-ones] ------------------------------------------------------------------------------ diff --git a/php-generator/cs/@home.texy b/php-generator/cs/@home.texy index a4562005f3..abbc84d111 100644 --- a/php-generator/cs/@home.texy +++ b/php-generator/cs/@home.texy @@ -1,11 +1,12 @@ Generátor PHP kódu ****************** -
    -- Potřebujete generovat kód tříd, funkcí, PHP souborů atd? +
    +Hledáte nástroj pro generování PHP kódu tříd, funkcí či kompletních souborů? + - Umí všechny nejnovější vychytávky v PHP (jako enumy atd.) -- Dovolí vám snadno modifikovat existující třídy -- Výstup vyhovující PSR-12 / PER coding style +- Umožní vám snadno modifikovat existující třídy +- Výstupní kód je v souladu s PSR-12 / PER coding style - Zralá, stabilní a široce používaná knihovna
    @@ -509,6 +510,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer public bool $bracesOnNextLine = true; // umístěte jeden parametr na jeden řádek, i když má atribut nebo je podporován public bool $singleParameterOnOneLine = false; + // omits namespaces that do not contain any class or function + public bool $omitEmptyNamespaces = true; // oddělovač mezi pravou závorkou a návratovým typem funkcí a metod public string $returnTypeColon = ': '; } @@ -530,7 +533,8 @@ Každý typ nebo union/intersection typ lze předat jako řetězec, můžete tak use Nette\PhpGenerator\Type; $member->setType('array'); // nebo Type::Array; -$member->setType('array|string'); // nebo Type::union('array', 'string') +$member->setType('?array'); // or Type::nullable(Type::Array); +$member->setType('array|string'); // or Type::union(Type::Array, Type::String) $member->setType('Foo&Bar'); // nebo Type::intersection(Foo::class, Bar::class) $member->setType(null); // odstraní typ ``` @@ -679,8 +683,7 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range' Překlady názvů tříd ------------------- -**Když je třída součástí jmenného prostoru, je vykreslena mírně odlišně:** všechny typy (například typehinty, návratové typy, název rodičovské třídy, -implementovaná rozhraní, použité vlastnosti a atributy) jsou automaticky *překládány* (pokud to nevypnete, viz níže). +**Když je třída součástí jmenného prostoru, je vykreslena mírně odlišně:** všechny typy (například typehinty, návratové typy, název rodičovské třídy, implementovaná rozhraní, použité vlastnosti a atributy) jsou automaticky *překládány* (pokud to nevypnete, viz níže). To znamená, že musíte v definicích **používat úplné názvy tříd** a ty budou nahrazeny za aliasy (podle klauzulí use) nebo za plně kvalifikovaná jména ve výsledném kódu: ```php @@ -777,6 +780,8 @@ function foo() } ``` +**Upozornění:** Do souborů není možné přidávat žádný další kód mimo funkce a třídy. + Generování podle existujících ----------------------------- @@ -857,5 +862,4 @@ Tabulka kompatibility PhpGenerator 4.0 a 4.1 jsou kompatibilní s PHP 8.0 až 8.3. - {{leftbar: nette:@menu-topics}} diff --git a/php-generator/de/@home.texy b/php-generator/de/@home.texy index 25ef0fccca..8ee6152a76 100644 --- a/php-generator/de/@home.texy +++ b/php-generator/de/@home.texy @@ -2,11 +2,12 @@ PHP-Code-Generator ******************
    -- Müssen Sie PHP-Code für Klassen, Funktionen, PHP-Dateien usw. generieren? -- Unterstützt alle aktuellen PHP-Funktionen wie Enums, Attribute, etc. +Suchen Sie ein Tool, um PHP-Code für Klassen, Funktionen oder komplette Dateien zu generieren? + +- Unterstützt alle aktuellen PHP-Funktionen (wie Enums, etc.) - Ermöglicht die einfache Änderung bestehender Klassen -- PSR-12-konforme Ausgabe -- Hochgradig ausgereifte, stabile und weit verbreitete Bibliothek +- Ausgabe in Übereinstimmung mit PSR-12 / PER-Kodierung +- Ausgereifte, stabile und weit verbreitete Bibliothek
    @@ -509,6 +510,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer public bool $bracesOnNextLine = true; // Platzierung eines Parameters in einer Zeile, auch wenn er ein Attribut hat oder promotet wird public bool $singleParameterOnOneLine = false; + // omits namespaces that do not contain any class or function + public bool $omitEmptyNamespaces = true; // Trennzeichen zwischen der rechten Klammer und dem Rückgabetyp von Funktionen und Methoden public string $returnTypeColon = ': '; } @@ -530,7 +533,8 @@ Jeder Typ oder Gewerkschafts-/Schnittstellentyp kann als String übergeben werde use Nette\PhpGenerator\Type; $member->setType('array'); // oder Type::Array; -$member->setType('array|string'); // oder Type::union('array', 'string') +$member->setType('?array'); // or Type::nullable(Type::Array); +$member->setType('array|string'); // or Type::union(Type::Array, Type::String) $member->setType('Foo&Bar'); // oder Type::intersection(Foo::class, Bar::class) $member->setType(null); // Entfernt Typ ``` @@ -679,9 +683,8 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range' Auflösen von Klassennamen .[#toc-class-names-resolving] ------------------------------------------------------- -**Wenn die Klasse Teil des Namespaces ist, wird sie etwas anders dargestellt**: alle Typen (d.h. Typ-Hinweise, Rückgabetypen, Name der Elternklasse, -implementierte Schnittstellen, verwendete Traits und Attribute) werden automatisch *aufgelöst* (es sei denn, Sie schalten dies aus, siehe unten). -Das bedeutet, dass Sie **vollständige Klassennamen** in Definitionen verwenden müssen und diese im resultierenden Code durch Aliasnamen (entsprechend den Verwendungsbestimmungen) oder voll qualifizierte Namen ersetzt werden: +**Wenn eine Klasse Teil eines Namensraums ist, wird sie etwas anders dargestellt:** Alle Typen (z.B. Typ-Hinweise, Rückgabetypen, Name der Elternklasse, implementierte Schnittstellen, verwendete Traits und Attribute) werden automatisch *aufgelöst* (es sei denn, Sie schalten dies aus, siehe unten). +Das bedeutet, dass Sie **voll qualifizierte Klassennamen** in Definitionen verwenden müssen, und diese werden im resultierenden Code durch Aliase (basierend auf Verwendungsklauseln) oder voll qualifizierte Namen ersetzt: ```php $namespace = new Nette\PhpGenerator\PhpNamespace('Foo'); @@ -777,6 +780,8 @@ function foo() } ``` +**Bitte beachten Sie:** Außer den Funktionen und Klassen kann den Dateien kein weiterer Code hinzugefügt werden. + Generierung nach vorhandenen Elementen .[#toc-generating-according-to-existing-ones] ------------------------------------------------------------------------------------ diff --git a/php-generator/el/@home.texy b/php-generator/el/@home.texy index 14df08af86..adc47e3fbb 100644 --- a/php-generator/el/@home.texy +++ b/php-generator/el/@home.texy @@ -2,11 +2,12 @@ ********************
    -- Χρειάζεται να δημιουργήσετε κώδικα PHP για κλάσεις, συναρτήσεις, αρχεία PHP κ.λπ. -- Υποστηρίζει όλα τα τελευταία χαρακτηριστικά της PHP, όπως enums, attributes κ.λπ. +Ψάχνετε ένα εργαλείο για τη δημιουργία κώδικα PHP για κλάσεις, συναρτήσεις ή πλήρη αρχεία; + +- Υποστηρίζει όλα τα τελευταία χαρακτηριστικά της PHP (όπως enums κ.λπ.) - Σας επιτρέπει να τροποποιείτε εύκολα τις υπάρχουσες κλάσεις -- Έξοδος συμβατή με το PSR-12 / PER coding style -- Εξαιρετικά ώριμη, σταθερή και ευρέως χρησιμοποιούμενη βιβλιοθήκη +- Έξοδος συμβατή με το στυλ κωδικοποίησης PSR-12 / PER +- Ώριμη, σταθερή και ευρέως χρησιμοποιούμενη βιβλιοθήκη
    @@ -509,6 +510,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer public bool $bracesOnNextLine = true; // τοποθέτηση μιας παραμέτρου σε μια γραμμή, ακόμη και αν έχει ένα χαρακτηριστικό ή αν προωθείται public bool $singleParameterOnOneLine = false; + // omits namespaces that do not contain any class or function + public bool $omitEmptyNamespaces = true; // διαχωριστικό μεταξύ της δεξιάς παρένθεσης και του τύπου επιστροφής των συναρτήσεων και των μεθόδων public string $returnTypeColon = ': '; } @@ -530,7 +533,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer use Nette\PhpGenerator\Type; $member->setType('array'); // ή Type::Array, -$member->setType('array|string'); // ή Type::union('array', 'string') +$member->setType('?array'); // or Type::nullable(Type::Array); +$member->setType('array|string'); // or Type::union(Type::Array, Type::String) $member->setType('Foo&Bar'); // ή Type::intersection(Foo::class, Bar::class) $member->setType(null); // αφαιρεί τον τύπο ``` @@ -679,9 +683,8 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range' Επίλυση ονομάτων κλάσεων .[#toc-class-names-resolving] ------------------------------------------------------ -**Όταν η κλάση είναι μέρος του χώρου ονομάτων, αποδίδεται ελαφρώς διαφορετικά**: όλοι οι τύποι (δηλαδή οι υποδείξεις τύπου, οι τύποι επιστροφής, το όνομα της γονικής κλάσης, -υλοποιημένες διεπαφές, χρησιμοποιούμενα γνωρίσματα και χαρακτηριστικά) *επιλύονται* αυτόματα (εκτός αν το απενεργοποιήσετε, βλ. παρακάτω). -Αυτό σημαίνει ότι πρέπει να **χρησιμοποιείτε πλήρη ονόματα κλάσεων** στους ορισμούς και αυτά θα αντικατασταθούν με ψευδώνυμα (σύμφωνα με τις δηλώσεις χρήσης) ή πλήρως προσδιορισμένα ονόματα στον κώδικα που θα προκύψει: +**Όταν μια κλάση είναι μέρος ενός χώρου ονομάτων, αποδίδεται ελαφρώς διαφορετικά:** όλοι οι τύποι (π.χ. υποδείξεις τύπου, τύποι επιστροφής, όνομα γονικής κλάσης, υλοποιημένες διασυνδέσεις, χρησιμοποιούμενα γνωρίσματα και χαρακτηριστικά) *επιλύονται* αυτόματα (εκτός αν το απενεργοποιήσετε, δείτε παρακάτω). +Αυτό σημαίνει ότι πρέπει να χρησιμοποιείτε **πλήρως προσδιορισμένα ονόματα κλάσεων** στους ορισμούς, και θα αντικατασταθούν με ψευδώνυμα (με βάση τις ρήτρες χρήσης) ή πλήρως προσδιορισμένα ονόματα στον κώδικα που θα προκύψει: ```php $namespace = new Nette\PhpGenerator\PhpNamespace('Foo'); @@ -777,6 +780,8 @@ function foo() } ``` +**Παρακαλώ σημειώστε:** Δεν μπορεί να προστεθεί πρόσθετος κώδικας στα αρχεία εκτός των συναρτήσεων και των κλάσεων. + Δημιουργία σύμφωνα με τις υπάρχουσες .[#toc-generating-according-to-existing-ones] ---------------------------------------------------------------------------------- diff --git a/php-generator/en/@home.texy b/php-generator/en/@home.texy index 97599942ed..44181cbc5b 100644 --- a/php-generator/en/@home.texy +++ b/php-generator/en/@home.texy @@ -2,11 +2,12 @@ PHP Code Generator ******************
    -- Need to generate PHP code for classes, functions, PHP files, etc.? -- Supports all the latest PHP features like enums, attributes, etc. +Are you looking for a tool to generate PHP code for classes, functions, or complete files? + +- Supports all the latest PHP features (like enums, etc.) - Allows you to easily modify existing classes -- PSR-12 / PER coding style compliant output -- Highly mature, stable, and widely used library +- Output compliant with PSR-12 / PER coding style +- Mature, stable, and widely used library
    @@ -509,6 +510,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer public bool $bracesOnNextLine = true; // place one parameter in one line, even if it has an attribute or is promoted public bool $singleParameterOnOneLine = false; + // omits namespaces that do not contain any class or function + public bool $omitEmptyNamespaces = true; // separator between the right parenthesis and return type of functions and methods public string $returnTypeColon = ': '; } @@ -530,7 +533,8 @@ Each type or union/intersection type can be passed as a string, you can also use use Nette\PhpGenerator\Type; $member->setType('array'); // or Type::Array; -$member->setType('array|string'); // or Type::union('array', 'string') +$member->setType('?array'); // or Type::nullable(Type::Array); +$member->setType('array|string'); // or Type::union(Type::Array, Type::String) $member->setType('Foo&Bar'); // or Type::intersection(Foo::class, Bar::class) $member->setType(null); // removes type ``` @@ -679,9 +683,8 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range' Class Names Resolving --------------------- -**When the class is part of the namespace, it is rendered slightly differently**: all types (ie. type hints, return types, parent class name, -implemented interfaces, used traits and attributes) are automatically *resolved* (unless you turn it off, see below). -It means that you have to **use full class names** in definitions and they will be replaced with aliases (according to the use-statements) or fully qualified names in the resulting code: +**When a class is part of a namespace, it's rendered slightly differently:** all types (e.g., type hints, return types, parent class name, implemented interfaces, used traits, and attributes) are automatically *resolved* (unless you turn it off, see below). +This means you must use **fully qualified class names** in definitions, and they will be replaced with aliases (based on use clauses) or fully qualified names in the resulting code: ```php $namespace = new Nette\PhpGenerator\PhpNamespace('Foo'); @@ -777,6 +780,8 @@ function foo() } ``` +**Please note:** No additional code can be added to the files outside of functions and classes. + Generating According to Existing Ones ------------------------------------- diff --git a/php-generator/es/@home.texy b/php-generator/es/@home.texy index e26cb1a50a..fe4d193d12 100644 --- a/php-generator/es/@home.texy +++ b/php-generator/es/@home.texy @@ -2,11 +2,12 @@ Generador de código PHP ***********************
    -- ¿Necesita generar código PHP para clases, funciones, archivos PHP, etc.? -- Soporta todas las últimas características de PHP como enums, atributos, etc. +¿Está buscando una herramienta para generar código PHP para clases, funciones o archivos completos? + +- Soporta todas las últimas características de PHP (como enums, etc.) - Le permite modificar fácilmente las clases existentes -- Salida compatible con PSR-12 / PER coding style -- Librería altamente madura, estable y ampliamente utilizada +- Salida conforme con el estilo de codificación PSR-12 / PER +- Biblioteca madura, estable y ampliamente utilizada
    @@ -509,6 +510,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer public bool $bracesOnNextLine = true; // colocar un parámetro en una línea, incluso si tiene un atributo o es promocionado public bool $singleParameterOnOneLine = false; + // omits namespaces that do not contain any class or function + public bool $omitEmptyNamespaces = true; // separador entre el paréntesis derecho y el tipo de retorno de funciones y métodos public string $returnTypeColon = ': '; } @@ -530,7 +533,8 @@ Cada tipo o tipo de unión/intersección puede pasarse como una cadena, también use Nette\PhpGenerator\Type; $member->setType('array'); // o Type::Array; -$member->setType('array|string'); // o Type::union('array', 'string') +$member->setType('?array'); // or Type::nullable(Type::Array); +$member->setType('array|string'); // or Type::union(Type::Array, Type::String) $member->setType('Foo&Bar'); // o Type::intersection(Foo::class, Bar::class) $member->setType(null); // elimina el tipo ``` @@ -679,9 +683,8 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range' Resolución de nombres de clase .[#toc-class-names-resolving] ------------------------------------------------------------ -**Cuando la clase es parte del espacio de nombres, se renderiza de forma ligeramente diferente**: todos los tipos (ie. type hints, return types, parent class name, -interfaces implementadas, rasgos y atributos usados) se *resuelven* automáticamente (a menos que lo desactives, ver más abajo). -Esto significa que tienes que **usar nombres de clase completos** en las definiciones y serán reemplazados por alias (de acuerdo con las declaraciones de uso) o nombres completamente cualificados en el código resultante: +**Cuando una clase es parte de un espacio de nombres, se renderiza de forma ligeramente diferente:** todos los tipos (por ejemplo, sugerencias de tipo, tipos de retorno, nombre de la clase padre, interfaces implementadas, rasgos usados y atributos) se *resuelven* automáticamente (a menos que lo desactives, ver más abajo). +Esto significa que debes usar **nombres de clase completamente cualificados** en las definiciones, y serán reemplazados por alias (basados en cláusulas de uso) o nombres completamente cualificados en el código resultante: ```php $namespace = new Nette\PhpGenerator\PhpNamespace('Foo'); @@ -777,6 +780,8 @@ function foo() } ``` +**Por favor, tenga en cuenta:** No se puede añadir código adicional a los archivos fuera de las funciones y clases. + Generar en función de los existentes .[#toc-generating-according-to-existing-ones] ---------------------------------------------------------------------------------- diff --git a/php-generator/fr/@home.texy b/php-generator/fr/@home.texy index c5daf74780..2df1b8f742 100644 --- a/php-generator/fr/@home.texy +++ b/php-generator/fr/@home.texy @@ -2,11 +2,12 @@ Générateur de code PHP **********************
    -- Vous avez besoin de générer du code PHP pour des classes, des fonctions, des fichiers PHP, etc. -- Supporte toutes les dernières fonctionnalités de PHP comme les enums, les attributs, etc. +Vous cherchez un outil pour générer du code PHP pour des classes, des fonctions ou des fichiers complets ? + +- Supporte toutes les dernières fonctionnalités de PHP (comme les enums, etc.) - Vous permet de modifier facilement les classes existantes -- Sortie conforme à PSR-12 / PER coding style -- Bibliothèque très mature, stable et largement utilisée. +- Sortie conforme au style de codage PSR-12 / PER +- Bibliothèque mature, stable et largement utilisée
    @@ -509,6 +510,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer public bool $bracesOnNextLine = true; // placer un seul paramètre sur une seule ligne, même s'il possède un attribut ou est promu public bool $singleParameterOnOneLine = false; + // omits namespaces that do not contain any class or function + public bool $omitEmptyNamespaces = true; // séparateur entre la parenthèse droite et le type de retour des fonctions et méthodes public string $returnTypeColon = ': '; } @@ -530,7 +533,8 @@ Chaque type ou type d'union/intersection peut être passé comme une chaîne de use Nette\PhpGenerator\Type; $member->setType('array'); // ou Type::Array; -$member->setType('array|string'); // ou Type::union('array', 'string') +$member->setType('?array'); // or Type::nullable(Type::Array); +$member->setType('array|string'); // or Type::union(Type::Array, Type::String) $member->setType('Foo&Bar'); // ou Type::intersection(Foo::class, Bar::class) $member->setType(null); // supprime le type ``` @@ -679,9 +683,8 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range' Résolution des noms de classe .[#toc-class-names-resolving] ----------------------------------------------------------- -**Lorsque la classe fait partie de l'espace de nom, elle est rendue de manière légèrement différente** : tous les types (c'est-à-dire les indications de type, les types de retour, le nom de la classe parente, -interfaces implémentées, traits et attributs utilisés) sont automatiquement *résolus* (sauf si vous le désactivez, voir ci-dessous). -Cela signifie que vous devez **utiliser les noms de classe complets** dans les définitions et qu'ils seront remplacés par des alias (selon les déclarations d'utilisation) ou des noms pleinement qualifiés dans le code résultant : +**Lorsqu'une classe fait partie d'un espace de noms, son rendu est légèrement différent:** tous les types (par exemple, les indications de type, les types de retour, le nom de la classe mère, les interfaces implémentées, les traits utilisés et les attributs) sont automatiquement *résolus* (sauf si vous le désactivez, voir ci-dessous). +Cela signifie que vous devez utiliser des **noms de classe pleinement qualifiés** dans les définitions, et qu'ils seront remplacés par des alias (basés sur des clauses d'utilisation) ou des noms pleinement qualifiés dans le code résultant : ```php $namespace = new Nette\PhpGenerator\PhpNamespace('Foo'); @@ -777,6 +780,8 @@ function foo() } ``` +**Remarque : aucun code supplémentaire ne peut être ajouté aux fichiers en dehors des fonctions et des classes. + Générer en fonction de ceux qui existent déjà .[#toc-generating-according-to-existing-ones] ------------------------------------------------------------------------------------------- diff --git a/php-generator/hu/@home.texy b/php-generator/hu/@home.texy index 8afbccb2e6..64d67f47c9 100644 --- a/php-generator/hu/@home.texy +++ b/php-generator/hu/@home.texy @@ -2,11 +2,12 @@ PHP kód generátor *****************
    -- PHP kódot szeretne generálni osztályokhoz, függvényekhez, PHP fájlokhoz stb.? -- Támogatja az összes legújabb PHP funkciót, mint például az enumokat, attribútumokat stb. +Olyan eszközt keres, amellyel PHP kódot generálhat osztályokhoz, függvényekhez vagy teljes fájlokhoz? + +- Támogatja az összes legújabb PHP-funkciót (például enums stb.) - Lehetővé teszi a meglévő osztályok egyszerű módosítását -- PSR-12 / PER coding style szabványnak megfelelő kimenet -- Rendkívül kiforrott, stabil és széles körben használt könyvtár +- PSR-12 / PER kódolási stílusnak megfelelő kimenet +- Kiforrott, stabil és széles körben használt könyvtár
    @@ -509,6 +510,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer public bool $bracesOnNextLine = true; // egy paramétert egy sorba helyezünk, még akkor is, ha attribútummal rendelkezik vagy előléptetve van. public bool $singleParameterOnOneLine = false; + // omits namespaces that do not contain any class or function + public bool $omitEmptyNamespaces = true; // elválasztó a függvények és metódusok jobb oldali zárójel és a visszatérési típus között. public string $returnTypeColon = ': '; } @@ -530,7 +533,8 @@ Minden típus vagy union/intersection típus átadható stringként, a natív t use Nette\PhpGenerator\Type; $member->setType('array'); // vagy Type::Array; -$member->setType('array|string'); // vagy Type::union('array', 'string') +$member->setType('?array'); // or Type::nullable(Type::Array); +$member->setType('array|string'); // or Type::union(Type::Array, Type::String) $member->setType('Foo&Bar'); // vagy Type::intersection(Foo::class, Bar::class) $member->setType(null); // eltávolítja a típust ``` @@ -679,9 +683,8 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range' Osztálynevek feloldása .[#toc-class-names-resolving] ---------------------------------------------------- -**Ha az osztály a névtér része, akkor kissé másképp jelenik meg**: minden típus (azaz a típushivatkozások, a visszatérési típusok, a szülő osztály neve, -implementált interfészek, használt tulajdonságok és attribútumok) automatikusan *feloldódnak* (hacsak ki nem kapcsolod, lásd alább). -Ez azt jelenti, hogy a definíciókban **teljes osztályneveket** kell használnod, és ezek a keletkező kódban aliasokkal (a use-statementsnek megfelelően) vagy teljesen minősített nevekkel lesznek helyettesítve: +**Ha egy osztály egy névtér része, akkor kissé másképp jelenik meg:** minden típus (pl. a típushivatkozások, visszatérési típusok, szülőosztály neve, implementált interfészek, használt tulajdonságok és attribútumok) automatikusan *feloldódik* (hacsak ki nem kapcsolod, lásd alább). +Ez azt jelenti, hogy a definíciókban **teljesen minősített osztályneveket** kell használnia, és ezek helyébe aliasok (a használati záradékok alapján) vagy teljesen minősített nevek lépnek az eredményül kapott kódban: ```php $namespace = new Nette\PhpGenerator\PhpNamespace('Foo'); @@ -777,6 +780,8 @@ function foo() } ``` +**Figyelem:** A függvényeken és osztályokon kívül nem lehet további kódot hozzáadni a fájlokhoz. + A meglévők szerint generálva .[#toc-generating-according-to-existing-ones] -------------------------------------------------------------------------- diff --git a/php-generator/it/@home.texy b/php-generator/it/@home.texy index a4e86164e0..8c6834cf33 100644 --- a/php-generator/it/@home.texy +++ b/php-generator/it/@home.texy @@ -2,11 +2,12 @@ Generatore di codice PHP ************************
    -- Avete bisogno di generare codice PHP per classi, funzioni, file PHP e così via? -- Supporta tutte le più recenti caratteristiche di PHP, come enum, attributi, ecc. +State cercando uno strumento per generare codice PHP per classi, funzioni o file completi? + +- Supporta tutte le più recenti caratteristiche di PHP (come gli enum, ecc.) - Permette di modificare facilmente le classi esistenti -- Output conforme a PSR-12 / PER coding style -- Libreria altamente matura, stabile e ampiamente utilizzata +- Uscita conforme allo stile di codifica PSR-12 / PER +- Libreria matura, stabile e ampiamente utilizzata
    @@ -509,6 +510,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer public bool $bracesOnNextLine = true; // inserire un parametro in una sola riga, anche se ha un attributo o è promosso public bool $singleParameterOnOneLine = false; + // omits namespaces that do not contain any class or function + public bool $omitEmptyNamespaces = true; // separatore tra la parentesi destra e il tipo di ritorno di funzioni e metodi public string $returnTypeColon = ': '; } @@ -530,7 +533,8 @@ Ogni tipo o tipo di unione/intersezione può essere passato come stringa; si pos use Nette\PhpGenerator\Type; $member->setType('array'); // o Type::Array; -$member->setType('array|string'); // o Type::union('array', 'stringa') +$member->setType('?array'); // or Type::nullable(Type::Array); +$member->setType('array|string'); // or Type::union(Type::Array, Type::String) $member->setType('Foo&Bar'); // o Type::intersection(Foo::class, Bar::class) $member->setType(null); // rimuove il tipo ``` @@ -679,9 +683,8 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range' Risoluzione dei nomi di classe .[#toc-class-names-resolving] ------------------------------------------------------------ -**Quando la classe fa parte dello spazio dei nomi, viene resa in modo leggermente diverso**: tutti i tipi (cioè i suggerimenti sui tipi, i tipi di ritorno, il nome della classe genitore, -interfacce implementate, tratti e attributi utilizzati) sono automaticamente *risolti* (a meno che non lo si disattivi, vedere sotto). -Ciò significa che bisogna **usare i nomi completi delle classi** nelle definizioni, che saranno sostituiti da alias (secondo le dichiarazioni d'uso) o da nomi pienamente qualificati nel codice risultante: +**Quando una classe fa parte di uno spazio dei nomi, viene resa in modo leggermente diverso: tutti i tipi (ad esempio, i suggerimenti sui tipi, i tipi di ritorno, il nome della classe madre, le interfacce implementate, i tratti utilizzati e gli attributi) vengono automaticamente *risolti* (a meno che non si disattivi, vedere sotto). +Ciò significa che è necessario usare nomi di classe **completamente qualificati** nelle definizioni, che verranno sostituiti con alias (basati su clausole di utilizzo) o nomi pienamente qualificati nel codice risultante: ```php $namespace = new Nette\PhpGenerator\PhpNamespace('Foo'); @@ -777,6 +780,8 @@ function foo() } ``` +**Nota: ** Non è possibile aggiungere altro codice ai file al di fuori delle funzioni e delle classi. + Generare in base a quelli esistenti .[#toc-generating-according-to-existing-ones] --------------------------------------------------------------------------------- diff --git a/php-generator/ja/@home.texy b/php-generator/ja/@home.texy index 126581589a..44c35f1c69 100644 --- a/php-generator/ja/@home.texy +++ b/php-generator/ja/@home.texy @@ -2,11 +2,12 @@ PHP コードジェネレータ *************
    -- クラス、関数、PHPファイルなどのPHPコードを生成する必要がありますか? -- enum、属性など、最新のPHP機能をすべてサポートしています。 +クラスや関数、ファイル全体のPHPコードを生成するツールをお探しですか? + +- 最新の PHP 機能 (enum など) をすべてサポートしています。 - 既存のクラスを簡単に修正することが可能 -- PSR-12に準拠した出力 -- 非常に成熟した、安定した、広く使われているライブラリです。 +- PSR-12 / PERコーディングスタイルに準拠した出力 +- 成熟し、安定し、広く使用されているライブラリ
    @@ -509,6 +510,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer public bool $bracesOnNextLine = true; // パラメータが属性を持っていたり、昇格していても、1つのパラメータを1行に配置する。 public bool $singleParameterOnOneLine = false; + // omits namespaces that do not contain any class or function + public bool $omitEmptyNamespaces = true; // メソッドの右括弧と戻り値の関数との間の区切り文字 public string $returnTypeColon = ': '; } @@ -530,7 +533,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer use Nette\PhpGenerator\Type; $member->setType('array'); // or Type::Array; -$member->setType('array|string'); // or Type::union('array', 'string') +$member->setType('?array'); // or Type::nullable(Type::Array); +$member->setType('array|string'); // or Type::union(Type::Array, Type::String) $member->setType('Foo&Bar'); // or Type::intersection(Foo::class, Bar::class) $member->setType(null); // removes type ``` @@ -679,9 +683,8 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range' クラス名の解決 .[#toc-class-names-resolving] ------------------------------------- -**クラスが名前空間の一部である場合、わずかに異なる方法でレンダリングされます**:すべてのタイプ(すなわち、タイプヒント、戻り値タイプ、親クラス名、 -実装されたインターフェース、使用された特性や属性)は自動的に*解決*されます(オフにしない限り、以下を参照)。 -つまり、定義では完全なクラス名**を使用しなければならず、結果のコードではエイリアス(use-statementに従う)または完全修飾名に置き換えられます: +**すべての型(例:型ヒント、戻り値型、親クラス名、実装されたインターフェイス、使用された特性、属性)は自動的に *解決* されます(オフにしない限り。) +つまり、**完全に修飾されたクラス名** を定義に使用する必要があり、結果のコードではエイリアス(use句に基づく)または完全に修飾された名前に置き換えられます: ```php $namespace = new Nette\PhpGenerator\PhpNamespace('Foo'); @@ -777,6 +780,8 @@ function foo() } ``` +**注意:*** 関数やクラス以外のコードをファイルに追加することはできません。 + 既存のものに合わせて生成する .[#toc-generating-according-to-existing-ones] ------------------------------------------------------------ diff --git a/php-generator/pl/@home.texy b/php-generator/pl/@home.texy index d8c4c85ac0..20dd2737c1 100644 --- a/php-generator/pl/@home.texy +++ b/php-generator/pl/@home.texy @@ -2,11 +2,12 @@ Generator kodu PHP ******************
    -- Potrzebujesz wygenerować kod PHP dla klas, funkcji, plików PHP, itp. -- Obsługuje wszystkie najnowsze funkcje PHP, takie jak enumy, atrybuty, itp. +Szukasz narzędzia do generowania kodu PHP dla klas, funkcji lub całych plików? + +- Obsługuje wszystkie najnowsze funkcje PHP (takie jak wyliczenia itp.) - Pozwala na łatwą modyfikację istniejących klas -- Wyjście zgodne z PSR-12 / PER coding style -- Wysoce dojrzała, stabilna i szeroko stosowana biblioteka +- Wyjście zgodne ze stylem kodowania PSR-12 / PER +- Dojrzała, stabilna i szeroko stosowana biblioteka
    @@ -509,6 +510,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer public bool $bracesOnNextLine = true; // umieszczenie jednego parametru w jednej linii, nawet jeśli ma atrybut lub jest promowany public bool $singleParameterOnOneLine = false; + // omits namespaces that do not contain any class or function + public bool $omitEmptyNamespaces = true; // separator między prawym nawiasem a typem zwracanej funkcji i metody public string $returnTypeColon = ': '; } @@ -530,7 +533,8 @@ Każdy typ lub typ unii / przecięcia może być przekazany jako ciąg, możesz use Nette\PhpGenerator\Type; $member->setType('array'); // lub Type::Array; -$member->setType('array|string'); // lub Type::union('array', 'string') +$member->setType('?array'); // or Type::nullable(Type::Array); +$member->setType('array|string'); // or Type::union(Type::Array, Type::String) $member->setType('Foo&Bar'); // lub Type::intersection(Foo::class, Bar::class) $member->setType(null); // usuwa typ ``` @@ -679,9 +683,8 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range' Class Names Resolving (rozwiązywanie nazw klas) .[#toc-class-names-resolving] ----------------------------------------------------------------------------- -**Kiedy klasa jest częścią przestrzeni nazw, jest renderowana nieco inaczej**: wszystkie typy (tj. podpowiedzi typów, typy zwracane, nazwa klasy nadrzędnej, -zaimplementowane interfejsy, użyte cechy i atrybuty) są automatycznie *rozwiązywane* (chyba że wyłączysz tę funkcję, patrz poniżej). -Oznacza to, że musisz **używać pełnych nazw klas** w definicjach, a zostaną one zastąpione aliasami (zgodnie z deklaracjami użycia) lub w pełni kwalifikowanymi nazwami w wynikowym kodzie: +**Gdy klasa jest częścią przestrzeni nazw, jest renderowana nieco inaczej:** wszystkie typy (np. podpowiedzi typów, typy zwracane, nazwa klasy nadrzędnej, zaimplementowane interfejsy, używane cechy i atrybuty) są automatycznie *rozwiązywane* (chyba że to wyłączysz, patrz poniżej). +Oznacza to, że musisz używać **w pełni kwalifikowanych nazw klas** w definicjach, a zostaną one zastąpione aliasami (opartymi na klauzulach użycia) lub w pełni kwalifikowanymi nazwami w wynikowym kodzie: ```php $namespace = new Nette\PhpGenerator\PhpNamespace('Foo'); @@ -777,6 +780,8 @@ function foo() } ``` +**Uwaga:** Do plików nie można dodawać żadnego dodatkowego kodu poza funkcjami i klasami. + Generowanie według istniejących .[#toc-generating-according-to-existing-ones] ----------------------------------------------------------------------------- diff --git a/php-generator/pt/@home.texy b/php-generator/pt/@home.texy index 9e49068c2c..9cf37e054a 100644 --- a/php-generator/pt/@home.texy +++ b/php-generator/pt/@home.texy @@ -2,11 +2,12 @@ Gerador de código PHP *********************
    -- Necessidade de gerar código PHP para classes, funções, arquivos PHP, etc.? -- Suporta todas as últimas características do PHP, como enumeração, atributos, etc. +Você está procurando uma ferramenta para gerar código PHP para classes, funções ou arquivos completos? + +- Oferece suporte a todos os recursos mais recentes do PHP (como enums, etc.) - Permite modificar facilmente as classes existentes -- Saída compatível com PSR-12 / PER coding style -- Biblioteca altamente madura, estável e amplamente utilizada +- Saída compatível com o estilo de codificação PSR-12 / PER +- Biblioteca madura, estável e amplamente utilizada
    @@ -509,6 +510,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer public bool $bracesOnNextLine = true; // colocar um parâmetro em uma linha, mesmo que ele tenha um atributo ou seja promovido public bool $singleParameterOnOneLine = false; + // omits namespaces that do not contain any class or function + public bool $omitEmptyNamespaces = true; // separador entre o parêntese direito e o tipo de retorno de funções e métodos public string $returnTypeColon = ': '; } @@ -530,7 +533,8 @@ Cada tipo ou tipo de união/intersecção pode ser passado como uma corda, você use Nette\PhpGenerator\Type; $member->setType('array'); // or Type::Array; -$member->setType('array|string'); // or Type::union('array', 'string') +$member->setType('?array'); // or Type::nullable(Type::Array); +$member->setType('array|string'); // or Type::union(Type::Array, Type::String) $member->setType('Foo&Bar'); // or Type::intersection(Foo::class, Bar::class) $member->setType(null); // removes type ``` @@ -679,9 +683,8 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range' Resolução de Nomes de Classe .[#toc-class-names-resolving] ---------------------------------------------------------- -** Quando a classe faz parte do namespace, ela é renderizada de forma ligeiramente diferente**: todos os tipos (ou seja, dicas de tipo, tipos de retorno, nome da classe pai, -interfaces implementadas, características e atributos utilizados) são automaticamente *resolvidos* (a menos que você o desligue, veja abaixo). -Isso significa que você tem que **utilizar nomes completos de classe** em definições e eles serão substituídos por apelidos (de acordo com as declarações de uso) ou nomes totalmente qualificados no código resultante: +**Quando uma classe faz parte de um namespace, ela é renderizada de forma um pouco diferente:** todos os tipos (por exemplo, dicas de tipo, tipos de retorno, nome da classe pai, interfaces implementadas, características usadas e atributos) são automaticamente *resolvidos* (a menos que você desative essa opção, veja abaixo). +Isso significa que você deve usar **nomes de classe totalmente qualificados** nas definições, e eles serão substituídos por aliases (com base em cláusulas de uso) ou nomes totalmente qualificados no código resultante: ```php $namespace = new Nette\PhpGenerator\PhpNamespace('Foo'); @@ -777,6 +780,8 @@ function foo() } ``` +**Observação:** Nenhum código adicional pode ser adicionado aos arquivos fora das funções e classes. + Gerando de acordo com os já existentes .[#toc-generating-according-to-existing-ones] ------------------------------------------------------------------------------------ diff --git a/php-generator/ro/@home.texy b/php-generator/ro/@home.texy index d64f15e758..26da1299d6 100644 --- a/php-generator/ro/@home.texy +++ b/php-generator/ro/@home.texy @@ -2,11 +2,12 @@ Generator de coduri PHP ***********************
    -- Aveți nevoie să generați cod PHP pentru clase, funcții, fișiere PHP, etc.? -- Suportă toate cele mai recente caracteristici PHP, cum ar fi enums, atribute, etc. +Sunteți în căutarea unui instrument pentru a genera cod PHP pentru clase, funcții sau fișiere complete? + +- Suportă toate cele mai recente caracteristici PHP (cum ar fi enums etc.) - Vă permite să modificați cu ușurință clasele existente -- Ieșire conformă cu PSR-12 / PER coding style -- Bibliotecă extrem de matură, stabilă și utilizată pe scară largă +- Ieșire conformă cu stilul de codare PSR-12 / PER +- Bibliotecă matură, stabilă și utilizată pe scară largă
    @@ -509,6 +510,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer public bool $bracesOnNextLine = true; // plasează un parametru pe o singură linie, chiar dacă are un atribut sau este promovat public bool $singleParameterOnOneLine = false; + // omits namespaces that do not contain any class or function + public bool $omitEmptyNamespaces = true; // separator între paranteza dreaptă și tipul return al funcțiilor și metodelor public string $returnTypeColon = ': '; } @@ -530,7 +533,8 @@ Fiecare tip sau tip de uniune/intersecție poate fi transmis ca un șir de carac use Nette\PhpGenerator\Type; $member->setType('array'); // sau Type::Array; -$member->setType('array|string'); // sau Type::union('array', 'string') +$member->setType('?array'); // or Type::nullable(Type::Array); +$member->setType('array|string'); // or Type::union(Type::Array, Type::String) $member->setType('Foo&Bar'); // sau Type::intersection(Foo::class, Bar::class) $member->setType(null); // elimină tipul ``` @@ -679,9 +683,8 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range' Rezolvarea numelor de clase .[#toc-class-names-resolving] --------------------------------------------------------- -**Când clasa face parte din spațiul de nume, este redată puțin diferit**: toate tipurile (adică indicii de tip, tipuri de returnare, numele clasei părinte, -interfețele implementate, trăsăturile și atributele utilizate) sunt automat *rezolvate* (cu excepția cazului în care dezactivați această funcție, a se vedea mai jos). -Aceasta înseamnă că trebuie să **utilizați nume de clasă complete** în definiții și că acestea vor fi înlocuite cu alias-uri (în conformitate cu declarațiile de utilizare) sau cu nume complet calificate în codul rezultat: +**Când o clasă face parte dintr-un spațiu de nume, aceasta este redată în mod ușor diferit:** toate tipurile (de exemplu, indicii de tip, tipuri de returnare, numele clasei părinte, interfețe implementate, trăsături utilizate și atribute) sunt automat *rezolvate* (dacă nu le dezactivați, a se vedea mai jos). +Acest lucru înseamnă că trebuie să utilizați **nume de clasă complet calificate** în definiții, iar acestea vor fi înlocuite cu pseudonime (pe baza clauzelor de utilizare) sau cu nume complet calificate în codul rezultat: ```php $namespace = new Nette\PhpGenerator\PhpNamespace('Foo'); @@ -777,6 +780,8 @@ function foo() } ``` +**Atenție:** Nu se poate adăuga niciun cod suplimentar la fișiere în afara funcțiilor și claselor. + Generarea în funcție de cele existente .[#toc-generating-according-to-existing-ones] ------------------------------------------------------------------------------------ diff --git a/php-generator/ru/@home.texy b/php-generator/ru/@home.texy index bd7d7f6417..66bc911e8d 100644 --- a/php-generator/ru/@home.texy +++ b/php-generator/ru/@home.texy @@ -2,11 +2,12 @@ ******************
    -- Вам нужно сгенерировать PHP-код для классов, функций, PHP-файлов и т.д.? -- Поддерживает все новейшие возможности PHP, такие как перечисления, атрибуты и т.д. +Вы ищете инструмент для генерации PHP-кода для классов, функций или целых файлов? + +- Поддерживает все новейшие возможности PHP (такие как перечисления и т.д.) - Позволяет легко модифицировать существующие классы -- Выходные данные соответствуют стандарту PSR-12 / PER coding style -- Высокоразвитая, стабильная и широко используемая библиотека +- Выходные данные соответствуют стилю кодирования PSR-12 / PER +- Зрелая, стабильная и широко используемая библиотека
    @@ -509,6 +510,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer public bool $bracesOnNextLine = true; // размещение одного параметра в одной строке, даже если у него есть атрибут или он продвигается public bool $singleParameterOnOneLine = false; + // omits namespaces that do not contain any class or function + public bool $omitEmptyNamespaces = true; // разделитель между правой круглой скобкой и возвращаемым типом функций и методов public string $returnTypeColon = ': '; } @@ -530,7 +533,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer use Nette\PhpGenerator\Type; $member->setType('array'); // или Type::Array; -$member->setType('array|string'); // или Type::union('array', 'string') +$member->setType('?array'); // or Type::nullable(Type::Array); +$member->setType('array|string'); // or Type::union(Type::Array, Type::String) $member->setType('Foo&Bar'); // или Type::intersection(Foo::class, Bar::class) $member->setType(null); // удаляет тип ``` @@ -679,9 +683,8 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range' Разрешение имён классов .[#toc-class-names-resolving] ----------------------------------------------------- -**Когда класс является частью пространства имен, он отображается несколько иначе**: все типы (т.е. подсказки типов, возвращаемые типы, имя родительского класса, -реализованные интерфейсы, используемые черты и атрибуты) автоматически *разрешаются* (если вы не отключите эту функцию, см. ниже). -Это означает, что вы должны **использовать полные имена классов** в определениях, и они будут заменены псевдонимами (в соответствии с условиями использования) или полностью квалифицированными именами в результирующем коде: +**Когда класс является частью пространства имен, он отображается несколько иначе:** все типы (например, подсказки типов, возвращаемые типы, имя родительского класса, реализованные интерфейсы, используемые трейты и атрибуты) автоматически *разрешаются* (если это не отключено, см. ниже). +Это означает, что в определениях необходимо использовать **полностью квалифицированные имена классов**, и в результирующем коде они будут заменены псевдонимами (основанными на положениях use) или полностью квалифицированными именами: ```php $namespace = new Nette\PhpGenerator\PhpNamespace('Foo'); @@ -777,6 +780,8 @@ function foo() } ``` +**Примечание:** В файлы не может быть добавлен дополнительный код за пределами функций и классов. + Генерация с использованием Reflection .[#toc-generating-according-to-existing-ones] ----------------------------------------------------------------------------------- diff --git a/php-generator/sl/@home.texy b/php-generator/sl/@home.texy index 0b2e86b50c..f20bf6ed39 100644 --- a/php-generator/sl/@home.texy +++ b/php-generator/sl/@home.texy @@ -2,11 +2,12 @@ Generator kode PHP ******************
    -- Potrebujete kodo PHP za razrede, funkcije, datoteke PHP itd.? -- Podpira vse najnovejše funkcije PHP, kot so enumi, atributi itd. +Iščete orodje za ustvarjanje kode PHP za razrede, funkcije ali celotne datoteke? + +- Podpira vse najnovejše funkcije PHP (kot so enumi itd.) - Omogoča enostavno spreminjanje obstoječih razredov -- Izpis v skladu s standardom PSR-12 / PER coding style -- Zelo zrela, stabilna in pogosto uporabljena knjižnica +- Izhod je skladen s slogom kodiranja PSR-12 / PER +- Zrela, stabilna in široko uporabljena knjižnica
    @@ -509,6 +510,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer public bool $bracesOnNextLine = true; // postavi en parameter v eno vrstico, tudi če ima atribut ali je povišan public bool $singleParameterOnOneLine = false; + // omits namespaces that do not contain any class or function + public bool $omitEmptyNamespaces = true; // ločilo med desnim oklepajem in tipom vrnitve funkcij in metod public string $returnTypeColon = ': '; } @@ -530,7 +533,8 @@ Vsak tip ali tip zveze/intersekcije je mogoče posredovati kot niz, uporabite la use Nette\PhpGenerator\Type; $member->setType('array'); // ali Type::Array; -$member->setType('array|string'); // ali Type::union('array', 'string') +$member->setType('?array'); // or Type::nullable(Type::Array); +$member->setType('array|string'); // or Type::union(Type::Array, Type::String) $member->setType('Foo&Bar'); // ali Type::intersection(Foo::class, Bar::class) $member->setType(null); // odstrani tip ``` @@ -679,9 +683,8 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range' Razreševanje imen razredov .[#toc-class-names-resolving] -------------------------------------------------------- -**Ko je razred del imenskega prostora, se prikaže nekoliko drugače**: vse vrste (tj. namigi na vrsto, vrnitvene vrste, ime nadrejenega razreda, -implementirani vmesniki, uporabljene lastnosti in atributi) se samodejno *razrešijo* (razen če to izklopite, glejte spodaj). -To pomeni, da morate v definicijah **uporabiti polna imena razredov**, ki bodo v dobljeni kodi nadomeščena s približki (glede na izjave o uporabi) ali polno kvalificiranimi imeni: +**Ko je razred del imenskega prostora, se prikaže nekoliko drugače:** vsi tipi (npr. namigi na tip, tipi vrnitve, ime nadrejenega razreda, implementirani vmesniki, uporabljene lastnosti in atributi) se samodejno *razrešijo* (razen če to izklopite, glejte spodaj). +To pomeni, da morate v definicijah uporabljati **polno kvalificirana imena razredov**, ki bodo v dobljeni kodi nadomeščena s približki (na podlagi klavzul use) ali polno kvalificiranimi imeni: ```php $namespace = new Nette\PhpGenerator\PhpNamespace('Foo'); @@ -777,6 +780,8 @@ function foo() } ``` +**Upoštevajte:** V datoteke ni mogoče dodajati dodatne kode zunaj funkcij in razredov. + Ustvarjanje glede na obstoječe .[#toc-generating-according-to-existing-ones] ---------------------------------------------------------------------------- diff --git a/php-generator/tr/@home.texy b/php-generator/tr/@home.texy index e0683b5911..ca68e290fe 100644 --- a/php-generator/tr/@home.texy +++ b/php-generator/tr/@home.texy @@ -2,11 +2,12 @@ PHP Kod Oluşturucu ******************
    -- Sınıflar, fonksiyonlar, PHP dosyaları vb. için PHP kodu oluşturmanız mı gerekiyor? -- Enumlar, nitelikler vb. gibi en son PHP özelliklerini destekler. +Sınıflar, fonksiyonlar veya tüm dosyalar için PHP kodu üretecek bir araç mı arıyorsunuz? + +- En son PHP özelliklerini destekler (enumlar vb. gibi) - Mevcut sınıfları kolayca değiştirmenizi sağlar -- PSR-12 / PER coding style uyumlu çıkış -- Son derece olgun, istikrarlı ve yaygın olarak kullanılan kütüphane +- PSR-12 / PER kodlama stili ile uyumlu çıkış +- Olgun, kararlı ve yaygın olarak kullanılan kütüphane
    @@ -509,6 +510,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer public bool $bracesOnNextLine = true; // bir özniteliğe sahip olsa veya terfi ettirilse bile bir parametreyi tek bir satıra yerleştirir public bool $singleParameterOnOneLine = false; + // omits namespaces that do not contain any class or function + public bool $omitEmptyNamespaces = true; // sağ parantez ile fonksiyon ve metotların dönüş tipi arasında ayırıcı public string $returnTypeColon = ': '; } @@ -530,7 +533,8 @@ Her tür veya birlik/kesişim türü bir dize olarak geçirilebilir, ayrıca yer use Nette\PhpGenerator\Type; $member->setType('array'); // veya Type::Array; -$member->setType('array|string'); // veya Type::union('array', 'string') +$member->setType('?array'); // or Type::nullable(Type::Array); +$member->setType('array|string'); // or Type::union(Type::Array, Type::String) $member->setType('Foo&Bar'); // veya Type::intersection(Foo::class, Bar::class) $member->setType(null); // türü kaldırır ``` @@ -679,9 +683,8 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range' Sınıf Adları Çözülüyor .[#toc-class-names-resolving] ---------------------------------------------------- -**Sınıf isim alanının bir parçası olduğunda, biraz farklı şekilde işlenir**: tüm tipler (yani tip ipuçları, dönüş tipleri, ana sınıf adı, -uygulanan arayüzler, kullanılan özellikler ve nitelikler) otomatik olarak *çözülür* (kapatmadığınız sürece, aşağıya bakın). -Bu, tanımlarda **tam sınıf adlarını** kullanmanız gerektiği ve sonuçta ortaya çıkan kodda bunların takma adlarla (kullanım ifadelerine göre) veya tam nitelikli adlarla değiştirileceği anlamına gelir: +**Bir sınıf bir isim alanının parçası olduğunda, biraz farklı şekilde işlenir:** tüm tipler (örneğin, tip ipuçları, dönüş tipleri, ana sınıf adı, uygulanan arayüzler, kullanılan özellikler ve nitelikler) otomatik olarak *çözülür* (kapatmadığınız sürece, aşağıya bakın). +Bu, tanımlarda **tam nitelikli sınıf adları** kullanmanız gerektiği anlamına gelir ve bunlar sonuçta ortaya çıkan kodda takma adlarla (use cümlelerine dayalı olarak) veya tam nitelikli adlarla değiştirilecektir: ```php $namespace = new Nette\PhpGenerator\PhpNamespace('Foo'); @@ -777,6 +780,8 @@ function foo() } ``` +**Lütfen dikkat:** Dosyalara fonksiyonlar ve sınıflar dışında hiçbir ek kod eklenemez. + Mevcut Olanlara Göre Üretme .[#toc-generating-according-to-existing-ones] ------------------------------------------------------------------------- diff --git a/php-generator/uk/@home.texy b/php-generator/uk/@home.texy index 757f00ce49..2aff78d110 100644 --- a/php-generator/uk/@home.texy +++ b/php-generator/uk/@home.texy @@ -2,11 +2,12 @@ ******************
    -- Потрібно згенерувати PHP-код для класів, функцій, PHP-файлів тощо? -- Підтримує всі найновіші можливості PHP, такі як перерахування, атрибути тощо. +Ви шукаєте інструмент для генерації PHP-коду для класів, функцій або цілих файлів? + +- Підтримує всі найновіші можливості PHP (наприклад, перерахування тощо). - Дозволяє легко модифікувати існуючі класи -- Вихідні дані, сумісні з PSR-12 / PER coding style -- Досконала, стабільна та широко використовувана бібліотека +- Вихід, сумісний зі стилем кодування PSR-12 / PER +- Зріла, стабільна та широко використовувана бібліотека
    @@ -509,6 +510,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer public bool $bracesOnNextLine = true; // розміщувати один параметр в одному рядку, навіть якщо він має атрибут або є розкрученим public bool $singleParameterOnOneLine = false; + // omits namespaces that do not contain any class or function + public bool $omitEmptyNamespaces = true; // роздільник між правою круглою дужкою та типом повернення функцій та методів public string $returnTypeColon = ': '; } @@ -530,7 +533,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer use Nette\PhpGenerator\Type; $member->setType('array'); // або Type::Array; -$member->setType('array|string'); // або Type::union('array', 'string') +$member->setType('?array'); // or Type::nullable(Type::Array); +$member->setType('array|string'); // or Type::union(Type::Array, Type::String) $member->setType('Foo&Bar'); // або Type::intersection(Foo::class, Bar::class) $member->setType(null); // видаляє тип ``` @@ -679,9 +683,8 @@ echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range' Приведення імен класів .[#toc-class-names-resolving] ---------------------------------------------------- -**Коли клас є частиною простору імен, він відображається дещо інакше**: всі типи (тобто підказки типів, типи, що повертаються, ім'я батьківського класу, -реалізовані інтерфейси, використані риси та атрибути) автоматично *розв'язуються* (якщо ви не вимкнете цю функцію, див. нижче). -Це означає, що ви повинні **використовувати повні імена класів** у визначеннях, а в результуючому коді вони будуть замінені на псевдоніми (відповідно до операторів використання) або повністю кваліфіковані імена: +**Коли клас є частиною простору імен, він відображається дещо інакше:** всі типи (наприклад, підказки типів, типи повернення, ім'я батьківського класу, реалізовані інтерфейси, використані риси та атрибути) автоматично *розв'язуються* (якщо ви не вимкнете цю опцію, див. нижче). +Це означає, що ви повинні використовувати **повні імена класів** у визначеннях, і вони будуть замінені псевдонімами (на основі клаузул використання) або повними іменами у результуючому коді: ```php $namespace = new Nette\PhpGenerator\PhpNamespace('Foo'); @@ -777,6 +780,8 @@ function foo() } ``` +**Зверніть увагу:** До файлів не можна додавати додатковий код за межами функцій та класів. + Генерувати відповідно до існуючого .[#toc-generating-according-to-existing-ones] -------------------------------------------------------------------------------- From 0be2e7ea63b075141accfa55b6c2d4b30077cf23 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 1 Nov 2023 13:23:27 +0100 Subject: [PATCH 034/137] robot-loader: improved translation --- robot-loader/bg/@home.texy | 87 ++++++++++++++++++++------------------ robot-loader/cs/@home.texy | 11 +++-- robot-loader/de/@home.texy | 77 +++++++++++++++++---------------- robot-loader/el/@home.texy | 71 ++++++++++++++++--------------- robot-loader/en/@home.texy | 63 ++++++++++++++------------- robot-loader/es/@home.texy | 65 +++++++++++++++------------- robot-loader/fr/@home.texy | 69 ++++++++++++++++-------------- robot-loader/hu/@home.texy | 71 ++++++++++++++++--------------- robot-loader/it/@home.texy | 65 +++++++++++++++------------- robot-loader/pl/@home.texy | 83 +++++++++++++++++++----------------- robot-loader/pt/@home.texy | 81 ++++++++++++++++++----------------- robot-loader/ro/@home.texy | 63 ++++++++++++++------------- robot-loader/ru/@home.texy | 79 ++++++++++++++++++---------------- robot-loader/sl/@home.texy | 71 ++++++++++++++++--------------- robot-loader/tr/@home.texy | 65 +++++++++++++++------------- robot-loader/uk/@home.texy | 73 +++++++++++++++++--------------- 16 files changed, 587 insertions(+), 507 deletions(-) diff --git a/robot-loader/bg/@home.texy b/robot-loader/bg/@home.texy index 333415531b..bfd702176e 100644 --- a/robot-loader/bg/@home.texy +++ b/robot-loader/bg/@home.texy @@ -1,79 +1,82 @@ -RobotLoader: клас Autoloader -**************************** +RobotLoader: Автоматично зареждане на класове +*********************************************
    -RobotLoader е инструмент, който осигурява автоматично зареждане на класове за цялото приложение, включително библиотеки на трети страни. +RobotLoader е инструмент, който ви дава възможност за автоматизирано зареждане на класове за цялото ви приложение, включително библиотеки на трети страни. -- да се отървете от всички `require` -- зареждат се само необходимите скриптове -- не изисква строги конвенции за именуване на директориите или файловете. +- Елиминирайте всички изявления `require` +- Ще бъдат заредени само необходимите скриптове +- Не изисква строги конвенции за именуване на директории или файлове +- Изключително бързо +- Няма ръчни актуализации на кеша, всичко се изпълнява автоматично +- Зряла, стабилна и широко използвана библиотека
    -Така че можем да забравим за известните блокове от код: +Така можем да забравим за тези познати блокове код: ```php require_once 'Utils/Page.php'; require_once 'Utils/Style.php'; require_once 'Utils/Paginator.php'; -// ... +//... ``` -Инсталиране на .[#toc-installation] ------------------------------------ +Инсталация .[#toc-installation] +------------------------------- -Можете да изтеглите RobotLoader като [един самостоятелен файл `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], който можете да включите в скрипта си с помощта на `require`, и веднага да разполагате с удобно автоматично зареждане за цялото си приложение: +Можете да изтеглите RobotLoader като [един самостоятелен файл `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], който да включите с помощта на `require` в скрипта си, и веднага да се насладите на удобно автоматично зареждане за цялото приложение. ```php require '/path/to/RobotLoader.php'; $loader = new Nette\Loaders\RobotLoader; -// ... +//... ``` -Ако изграждате приложение, което използва [Composer |best-practices:composer], можете да го инсталирате чрез него: +Ако изграждате приложение с помощта на [Composer |best-practices:composer], можете да го инсталирате чрез: ```shell composer require nette/robot-loader ``` -Използване на .[#toc-usage] ---------------------------- +Употреба .[#toc-usage] +---------------------- -По същия начин, по който Google претърсва и индексира уебсайтове, [RobotLoader |api:Nette\Loaders\RobotLoader] преглежда всички PHP скриптове и записва кои класове и интерфейси са открити в тях. След това тези записи се кешират и се използват при всяко следващо търсене. Трябва само да посочите кои директории да се индексират и къде да се съхранява кешът: +Подобно на начина, по който роботът на Google обхожда и индексира уеб страници, [RobotLoader |api:Nette\Loaders\RobotLoader] преминава през всички PHP скриптове и отбелязва кои класове, интерфейси, черти и енуми е намерил. След това той съхранява резултатите в кеш за използване при следващи заявки. Необходимо е само да посочите кои директории трябва да прегледа и къде да се съхранява кешът: ```php $loader = new Nette\Loaders\RobotLoader; -// директории, които да бъдат индексирани от RobotLoader (включително поддиректории) +// Директории, които RobotLoader да индексира (включително поддиректории) $loader->addDirectory(__DIR__ . '/app'); $loader->addDirectory(__DIR__ . '/libs'); -// използвайте директория 'temp' за кеша +// Задаване на кеширане в директорията 'temp' $loader->setTempDirectory(__DIR__ . '/temp'); -$loader->register(); // Стартиране на RobotLoader +$loader->register(); // Активиране на RobotLoader ``` -И това е всичко. Отсега нататък не е необходимо да използвате `require`. Чудесно, нали? +И това е всичко, от този момент нататък не е необходимо да използваме `require`. Страхотно! -Когато RobotLoader срещне дублирано име на клас по време на индексирането, той хвърля изключение и ви уведомява за това. RobotLoader също така автоматично актуализира кеша си, когато трябва да зареди клас, който не познава. Препоръчваме да забраните това на производствени сървъри, вижте раздел [Кеширане |#Кэширование]. +Ако RobotLoader срещне дублиращо се име на клас по време на индексирането, той ще хвърли изключение и ще ви уведоми. RobotLoader също така автоматично актуализира кеша, когато трябва да зареди непознат клас. Препоръчваме да изключите тази функция на производствени сървъри, вижте " [Кеширане" |#Caching]. -Ако искате RobotLoader да пропусне някои директории, използвайте `$loader->excludeDirectory('temp')` (може да се извика многократно или да се предадат няколко директории). +Ако искате RobotLoader да прескача определени директории, използвайте `$loader->excludeDirectory('temp')` (може да се извика многократно или да се предадат няколко директории). -По подразбиране RobotLoader съобщава за грешки в PHP файловете, като хвърля изключение `ParseError`. Това може да бъде деактивирано с помощта на `$loader->reportParseErrors(false)`. +По подразбиране RobotLoader съобщава за грешки в PHP файлове, като хвърля изключение `ParseError`. Това може да се потисне с помощта на `$loader->reportParseErrors(false)`. -Приложение Nette .[#toc-nette-application] +Нетно приложение .[#toc-nette-application] ------------------------------------------ -В рамките на приложението Nette, където `$configurator` се използва в `Bootstrap.php`, можете да конфигурирате RobotLoader по този начин: +Вътре в Nette Application, където `$configurator` се използва в `Bootstrap.php`, можете да настроите RobotLoader по този начин: ```php $configurator = new Nette\Bootstrap\Configurator; -// ... +//... $configurator->setTempDirectory(__DIR__ . '/../temp'); $configurator->createRobotLoader() ->addDirectory(__DIR__) @@ -82,30 +85,32 @@ $configurator->createRobotLoader() ``` -PHP файлов анализатор .[#toc-php-files-analyzer] ------------------------------------------------- +Анализатор на PHP файлове .[#toc-php-files-analyzer] +---------------------------------------------------- -RobotLoader може да се използва и само за намиране на класове, интерфейси и черти в PHP файлове **без да се използва функцията за автоматично зареждане: +RobotLoader може да се използва и само за намиране на класове, интерфейси, черти и енуми в PHP файлове, без да се използва функцията за автоматично зареждане: ```php $loader = new Nette\Loaders\RobotLoader; $loader->addDirectory(__DIR__ . '/app'); -// Търсене на директории за класове / интерфейси / черти +// Търсене на директории за класове/интерфейси/характеристики/енуми $loader->rebuild(); -//връща масив от двойки клас => име на файл +// Връща масив от двойки клас => име на файл $res = $loader->getIndexedClasses(); ``` -Дори и при тази употреба можете да използвате кеша. В резултат на това немодифицираните файлове няма да бъдат анализирани отново при повторно сканиране: +Дори при такава употреба можете да използвате кеширане. Това гарантира, че непроменените файлове няма да бъдат сканирани отново: ```php $loader = new Nette\Loaders\RobotLoader; $loader->addDirectory(__DIR__ . '/app'); + +// Задаване на кеширане в директорията 'temp' $loader->setTempDirectory(__DIR__ . '/temp'); -// Сканиране на директории с кеш +// Претърсване на директориите с помощта на кеша $loader->refresh(); // Връща масив от двойки клас => име на файл @@ -116,23 +121,23 @@ $res = $loader->getIndexedClasses(); Кеширане .[#toc-caching] ------------------------ -RobotLoader е много бърз, защото използва кеша интелигентно. +RobotLoader е много бърз, защото умело използва кеширане. -Когато разработвате с него, почти не забелязвате, че работи във фонов режим. Той постоянно актуализира кеша, защото знае, че класовете и файловете могат да бъдат създавани, изтривани, преименувани и т.н. И не сканира повторно немодифицирани файлове. +По време на разработката почти не забелязвате, че той работи във фонов режим. Той непрекъснато обновява кеша си, като се има предвид, че класовете и файловете могат да бъдат създавани, изтривани, преименувани и т.н. И не сканира отново непроменените файлове. -От друга страна, когато се използва в производствен сървър, препоръчваме да забраните актуализирането на кеша с `$loader->setAutoRefresh(false)` (това се прави автоматично в приложението Nette), тъй като файловете не се модифицират. В същото време трябва да **изчистите кеша**, когато качвате нова версия на хоста. +В производствен сървър, от друга страна, препоръчваме да изключите обновяването на кеша с помощта на `$loader->setAutoRefresh(false)` (в приложение на Nette това става автоматично), тъй като файловете не се променят. В същото време е необходимо **изчистване на кеша** при качване на нова версия на хостинг. -Разбира се, първоначалното сканиране на файловете, когато кешът все още не съществува, може да отнеме няколко секунди при по-големи приложения. RobotLoader разполага с вградена защита срещу "препускане на кеша":https://en.wikipedia.org/wiki/Cache_stampede. -Това е ситуация, в която производствен сървър получава голям брой едновременни заявки и тъй като кешът на RobotLoader все още не съществува, всички те започват да сканират за файлове. Това увеличава натоварването на процесора и файловата система. -За щастие RobotLoader работи по такъв начин, че ако има няколко едновременни заявки, само първата нишка индексира файловете, създава кеш, а останалите изчакват, след което използват кеша. +Първоначалното сканиране на файловете, когато кешът все още не съществува, естествено може да отнеме известно време за по-големи приложения. RobotLoader разполага с вградена превенция срещу "прецакване на кеша:https://en.wikipedia.org/wiki/Cache_stampede". +Това е ситуация, при която голям брой едновременни заявки на производствен сървър ще задействат RobotLoader и тъй като кешът все още не съществува, всички те ще започнат да сканират файлове, което ще претовари сървъра. +За щастие RobotLoader работи по такъв начин, че само първата нишка индексира файловете, създава кеша, а останалите изчакват и след това използват кеша. PSR-4 .[#toc-psr-4] ------------------- -Днес Composer може да се използва за [автоматично зареждане в |best-practices:composer#Autoloading] съответствие с PSR-4. Казано по-просто, това е система, в която пространствата от имена и имената на класовете съответстват на структурата на директориите и имената на файловете, т.е. `App\Router\RouterFactory` е във файла `/path/to/App/Router/RouterFactory.php`. +В днешно време можете да използвате [Composer за автоматично зареждане |best-practices:composer#autoloading], като се придържате към PSR-4. Казано по-просто, това е система, при която пространствата от имена и имената на класовете съответстват на структурата на директориите и имената на файловете, например `App\Router\RouterFactory` ще бъде във файла `/path/to/App/Router/RouterFactory.php`. -RobotLoader не е обвързан с никаква фиксирана структура, така че е полезен в ситуации, в които не искате структурата на директориите да бъде представена от пространствата от имена на PHP или когато разработвате приложение, което в миналото не е използвало тези конвенции. Можете също така да използвате и двете зареждащи устройства заедно. +RobotLoader не е обвързан с никаква фиксирана структура, така че е полезен в ситуации, в които не искате структурата на директорията да е проектирана точно като пространствата от имена на PHP, или когато разработвате приложение, което исторически не използва такива конвенции. Възможно е също така да се използват и двата зареждащи механизма заедно. {{leftbar: nette:@menu-topics}} diff --git a/robot-loader/cs/@home.texy b/robot-loader/cs/@home.texy index 2e5e544ee5..81c026ec19 100644 --- a/robot-loader/cs/@home.texy +++ b/robot-loader/cs/@home.texy @@ -8,6 +8,9 @@ RobotLoader je nástroj, který vám zajistí komfort automatického načítán - zbavíme se všech `require` - budou se načítat jen potřebné skripty - nevyžaduje striktní konvence pojmenování adresářů či souborů +- extrémně rychlé +- žádné ruční aktualizace mezipaměti, vše probíhá automaticky +- zralá, stabilní a široce používaná knihovna
    @@ -43,7 +46,7 @@ composer require nette/robot-loader Použití ------- -Podobně, jako Google robot prochází a indexuje webové stránky, tak i [RobotLoader |api:Nette\Loaders\RobotLoader] prochází všechny PHP skripty a zaznamenává si, které třídy, rozhraní a traity v nich našel. Výsledky bádání si poté uloží do cache a použije při dalším požadavku. Stačí tedy určit, které adresáře má procházet a kam ukládat cache: +Podobně, jako Google robot prochází a indexuje webové stránky, tak i [RobotLoader |api:Nette\Loaders\RobotLoader] prochází všechny PHP skripty a zaznamenává si, které třídy, rozhraní, traity a enumy v nich našel. Výsledky bádání si poté uloží do cache a použije při dalším požadavku. Stačí tedy určit, které adresáře má procházet a kam ukládat cache: ```php $loader = new Nette\Loaders\RobotLoader; @@ -85,13 +88,13 @@ $configurator->createRobotLoader() Analyzátor PHP souborů ---------------------- -RobotLoader lze také použít čistě k vyhledávání tříd, rozhraní a trait v souborech PHP **bez** využívání funkce autoloadingu: +RobotLoader lze také použít čistě k vyhledávání tříd, rozhraní, trait a enumů v souborech PHP **bez** využívání funkce autoloadingu: ```php $loader = new Nette\Loaders\RobotLoader; $loader->addDirectory(__DIR__ . '/app'); -// prohledá adresáře na třídy / rozhraní / traity +// prohledá adresáře na třídy / rozhraní / traity / enumy $loader->rebuild(); // vrací pole dvojic třída => název souboru @@ -103,6 +106,8 @@ I při takovém použití můžete využít cache. Díky tomu při opětovném s ```php $loader = new Nette\Loaders\RobotLoader; $loader->addDirectory(__DIR__ . '/app'); + +// nastavíme cachování do adresáře 'temp' $loader->setTempDirectory(__DIR__ . '/temp'); // prohledá adresáře s využitím cache diff --git a/robot-loader/de/@home.texy b/robot-loader/de/@home.texy index 2218f88bce..90ac315a9c 100644 --- a/robot-loader/de/@home.texy +++ b/robot-loader/de/@home.texy @@ -5,35 +5,38 @@ RobotLoader: Klasse Autoloading RobotLoader ist ein Tool, das Ihnen den Komfort des automatischen Ladens von Klassen für Ihre gesamte Anwendung einschließlich der Bibliotheken von Drittanbietern bietet. -- alle loswerden `require` -- nur notwendige Skripte werden geladen -- erfordert keine strengen Verzeichnis- oder Dateinamenskonventionen +- Eliminieren Sie alle `require` Anweisungen +- Nur notwendige Skripte werden geladen +- Erfordert keine strengen Namenskonventionen für Verzeichnisse oder Dateien +- Äußerst schnell +- Keine manuellen Cache-Updates, alles läuft automatisch ab +- Ausgereifte, stabile und weit verbreitete Bibliothek
    -Wir können also diese berühmten Codeblöcke vergessen: +Wir können also diese vertrauten Codeblöcke vergessen: ```php require_once 'Utils/Page.php'; require_once 'Utils/Style.php'; require_once 'Utils/Paginator.php'; -// ... +//... ``` -Installation .[#toc-installation] ---------------------------------- +Einrichtung .[#toc-installation] +-------------------------------- -Sie können RobotLoader als [einzelne Standalone-Datei `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php] herunterladen, die Sie mit `require` in Ihr Skript einbinden können, und haben sofort eine komfortable automatische Ladung für Ihre gesamte Anwendung: +Sie können RobotLoader als [einzelne Standalone-Datei `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php] herunterladen, die Sie mit `require` in Ihr Skript einbinden, und sofort das komfortable automatische Laden für die gesamte Anwendung nutzen. ```php require '/path/to/RobotLoader.php'; $loader = new Nette\Loaders\RobotLoader; -// ... +//... ``` -Wenn Sie eine Anwendung erstellen, die [Composer |best-practices:composer] verwendet, können Sie ihn über Composer installieren: +Wenn Sie eine Anwendung mit [Composer |best-practices:composer] erstellen, können Sie ihn über installieren: ```shell composer require nette/robot-loader @@ -43,37 +46,37 @@ composer require nette/robot-loader Verwendung .[#toc-usage] ------------------------ -Ähnlich wie der Google-Roboter Webseiten crawlt und indiziert, crawlt [RobotLoader |api:Nette\Loaders\RobotLoader] alle PHP-Skripte und zeichnet auf, welche Klassen und Schnittstellen in ihnen gefunden wurden. Diese Aufzeichnungen werden dann im Cache gespeichert und bei allen nachfolgenden Anfragen verwendet. Sie müssen nur angeben, welche Verzeichnisse indiziert werden sollen und wo der Cache gespeichert werden soll: +Ähnlich wie der Google-Roboter Webseiten crawlt und indiziert, geht der [RobotLoader |api:Nette\Loaders\RobotLoader] durch alle PHP-Skripte und notiert, welche Klassen, Schnittstellen, Traits und Enums er gefunden hat. Anschließend speichert er die Ergebnisse im Cache, um sie bei nachfolgenden Anfragen zu verwenden. Sie müssen nur angeben, welche Verzeichnisse er durchsuchen soll und wo der Cache gespeichert werden soll: ```php $loader = new Nette\Loaders\RobotLoader; -// Verzeichnisse, die von RobotLoader indiziert werden sollen (einschließlich Unterverzeichnisse) +// Verzeichnisse, die RobotLoader indizieren soll (einschließlich Unterverzeichnisse) $loader->addDirectory(__DIR__ . '/app'); $loader->addDirectory(__DIR__ . '/libs'); -// 'temp' Verzeichnis für Cache verwenden +// Zwischenspeicherung auf das Verzeichnis "temp" einstellen $loader->setTempDirectory(__DIR__ . '/temp'); -$loader->register(); // Starten Sie den RobotLoader +$loader->register(); // RobotLoader aktivieren ``` -Und das ist alles. Von nun an brauchen Sie `require` nicht mehr zu verwenden. Toll, nicht wahr? +Und das war's, von nun an brauchen wir `require` nicht mehr zu verwenden. Großartig! -Wenn RobotLoader bei der Indizierung auf doppelte Klassennamen stößt, löst er eine Ausnahme aus und informiert Sie darüber. RobotLoader aktualisiert auch automatisch den Cache, wenn er eine Klasse laden muss, die er nicht kennt. Wir empfehlen, dies auf Produktionsservern zu deaktivieren, siehe [Caching |#Caching]. +Wenn RobotLoader während der Indizierung auf einen doppelten Klassennamen stößt, wird eine Ausnahme ausgelöst und Sie werden benachrichtigt. RobotLoader aktualisiert auch automatisch den Cache, wenn er eine unbekannte Klasse laden muss. Wir empfehlen, dies auf Produktionsservern zu deaktivieren, siehe [Caching |#Caching]. -Wenn Sie möchten, dass RobotLoader einige Verzeichnisse überspringt, verwenden Sie `$loader->excludeDirectory('temp')` (es kann mehrfach aufgerufen werden oder Sie können mehrere Verzeichnisse übergeben). +Wenn Sie möchten, dass RobotLoader bestimmte Verzeichnisse überspringt, verwenden Sie `$loader->excludeDirectory('temp')` (kann mehrfach aufgerufen werden oder mehrere Verzeichnisse übergeben). -Standardmäßig meldet RobotLoader Fehler in PHP-Dateien, indem er die Ausnahme `ParseError` auslöst. Sie kann über `$loader->reportParseErrors(false)` deaktiviert werden. +Standardmäßig meldet RobotLoader Fehler in PHP-Dateien, indem er eine `ParseError` Exception auslöst. Dies kann mit `$loader->reportParseErrors(false)` unterdrückt werden. Nette Anwendung .[#toc-nette-application] ----------------------------------------- -Innerhalb der Nette-Anwendung, wo `$configurator` in `Bootstrap.php` verwendet wird, können Sie RobotLoader auf diese Weise einrichten: +Innerhalb von Nette Application, wo `$configurator` in `Bootstrap.php` verwendet wird, können Sie RobotLoader auf diese Weise einrichten: ```php $configurator = new Nette\Bootstrap\Configurator; -// ... +//... $configurator->setTempDirectory(__DIR__ . '/../temp'); $configurator->createRobotLoader() ->addDirectory(__DIR__) @@ -85,54 +88,56 @@ $configurator->createRobotLoader() PHP-Dateianalysator .[#toc-php-files-analyzer] ---------------------------------------------- -RobotLoader kann auch verwendet werden, um Klassen, Interfaces und Traits in PHP-Dateien zu finden **ohne** die Autoloading-Funktion zu verwenden: +RobotLoader kann auch nur zum Auffinden von Klassen, Interfaces, Traits und Enums in PHP-Dateien **ohne** Verwendung der Autoloading-Funktion verwendet werden: ```php $loader = new Nette\Loaders\RobotLoader; $loader->addDirectory(__DIR__ . '/app'); -// Durchsucht Verzeichnisse nach Klassen / Schnittstellen / Traits +// Durchsucht Verzeichnisse nach Klassen/Schnittstellen/Traits/Enums $loader->rebuild(); -// Gibt Array von Klasse => Dateinamenpaaren zurück +// Gibt ein Array von Klasse => Dateinamenpaaren zurück $res = $loader->getIndexedClasses(); ``` -Auch bei einer solchen Verwendung können Sie den Cache nutzen. Dadurch werden unveränderte Dateien beim erneuten Scannen nicht wiederholt analysiert: +Auch bei einer solchen Verwendung können Sie das Caching nutzen. Dadurch wird sichergestellt, dass unveränderte Dateien nicht erneut gescannt werden: ```php $loader = new Nette\Loaders\RobotLoader; $loader->addDirectory(__DIR__ . '/app'); + +// Zwischenspeicherung auf das Verzeichnis 'temp' einstellen $loader->setTempDirectory(__DIR__ . '/temp'); -// Scannt Verzeichnisse mit Hilfe eines Caches +// Scannt Verzeichnisse unter Verwendung des Caches $loader->refresh(); -// Rückgabe eines Arrays von Klasse => Dateinamenpaaren +// Gibt ein Array von Klasse => Dateinamenpaaren zurück $res = $loader->getIndexedClasses(); ``` -Caching .[#toc-caching] ------------------------ +Zwischenspeichern .[#toc-caching] +--------------------------------- -RobotLoader ist sehr schnell, weil er den Cache geschickt nutzt. +RobotLoader ist sehr schnell, weil er geschickt die Zwischenspeicherung nutzt. -Wenn Sie mit ihm entwickeln, bemerken Sie praktisch nicht, dass er im Hintergrund läuft. Der Cache wird ständig aktualisiert, da er weiß, dass Klassen und Dateien erstellt, gelöscht, umbenannt usw. werden können. Und es scannt nicht wiederholt unveränderte Dateien. +Während der Entwicklung bemerken Sie kaum, dass er im Hintergrund läuft. Der Cache wird ständig aktualisiert, da Klassen und Dateien erstellt, gelöscht, umbenannt usw. werden können. Und er scannt unveränderte Dateien nicht erneut. -Beim Einsatz auf einem Produktionsserver empfiehlt es sich hingegen, die Cache-Aktualisierung mit `$loader->setAutoRefresh(false)` zu deaktivieren (dies geschieht automatisch in der Nette-Anwendung), da sich die Dateien nicht ändern. Gleichzeitig ist es notwendig, den Cache zu **leeren**, wenn eine neue Version auf das Hosting hochgeladen wird. +Auf einem Produktionsserver hingegen empfehlen wir, die Cache-Aktualisierung mit `$loader->setAutoRefresh(false)` zu deaktivieren (in einer Nette-Anwendung geschieht dies automatisch), da sich die Dateien nicht ändern. Gleichzeitig ist es notwendig, den Cache zu **leeren**, wenn eine neue Version zum Hosting hochgeladen wird. -Natürlich kann das anfängliche Scannen von Dateien, wenn der Cache noch nicht vorhanden ist, bei größeren Anwendungen einige Sekunden dauern. RobotLoader verfügt über einen eingebauten Schutz gegen "Cache-Stampede":https://en.wikipedia.org/wiki/Cache_stampede. -Dabei handelt es sich um eine Situation, in der der Produktionsserver eine große Anzahl gleichzeitiger Anfragen erhält, und da der Cache von RobotLoader noch nicht vorhanden ist, würden alle mit dem Scannen der Dateien beginnen. Dies führt zu einer hohen CPU- und Dateisystemauslastung. -Glücklicherweise funktioniert RobotLoader so, dass bei mehreren gleichzeitigen Anfragen nur der erste Thread die Dateien indiziert und einen Cache erstellt, die anderen warten und verwenden dann den Cache. +Das anfängliche Scannen der Dateien, wenn der Cache noch nicht vorhanden ist, kann bei größeren Anwendungen natürlich einen Moment dauern. RobotLoader hat einen eingebauten Schutz gegen "Cache-Stampede":https://en.wikipedia.org/wiki/Cache_stampede. +Dies ist eine Situation, in der eine große Anzahl gleichzeitiger Anfragen auf einem Produktionsserver RobotLoader auslösen würde, und da der Cache noch nicht existiert, würden sie alle mit dem Scannen von Dateien beginnen, was den Server überlasten würde. +Glücklicherweise arbeitet RobotLoader so, dass nur der erste Thread die Dateien indiziert und den Cache erstellt, während die anderen warten und dann den Cache verwenden. PSR-4 .[#toc-psr-4] ------------------- -Heute kann Composer für das [Autoloading |best-practices:composer#autoloading] gemäß PSR-4 verwendet werden. Einfach gesagt handelt es sich um ein System, bei dem die Namensräume und Klassennamen der Verzeichnisstruktur und den Dateinamen entsprechen, d.h. `App\Router\RouterFactory` befindet sich in der Datei `/path/to/App/Router/RouterFactory.php`. +Heutzutage können Sie [Composer für das automatische Laden |best-practices:composer#autoloading] unter Einhaltung von PSR-4 verwenden. Einfach ausgedrückt, handelt es sich um ein System, bei dem die Namensräume und Klassennamen der Verzeichnisstruktur und den Dateinamen entsprechen, z. B. `App\Router\RouterFactory` in der Datei `/path/to/App/Router/RouterFactory.php`. -RobotLoader ist nicht an eine feste Struktur gebunden und ist daher in Situationen nützlich, in denen die Verzeichnisstruktur in PHP nicht als Namespaces ausgelegt ist, oder wenn Sie eine Anwendung entwickeln, die solche Konventionen historisch nicht verwendet hat. Es ist auch möglich, beide Loader zusammen zu verwenden. +RobotLoader ist nicht an eine feste Struktur gebunden, so dass es in Situationen nützlich ist, in denen Sie die Verzeichnisstruktur nicht genau wie die PHP-Namensräume gestalten wollen, oder wenn Sie eine Anwendung entwickeln, die historisch gesehen keine solchen Konventionen verwendet. Es ist auch möglich, beide Lader zusammen zu verwenden. {{leftbar: nette:@menu-topics}} diff --git a/robot-loader/el/@home.texy b/robot-loader/el/@home.texy index d705af5afc..e7fa049214 100644 --- a/robot-loader/el/@home.texy +++ b/robot-loader/el/@home.texy @@ -5,35 +5,38 @@ RobotLoader: Αυτόματη φόρτωση κλάσης Το RobotLoader είναι ένα εργαλείο που σας δίνει την άνεση της αυτοματοποιημένης φόρτωσης κλάσεων για ολόκληρη την εφαρμογή σας, συμπεριλαμβανομένων των βιβλιοθηκών τρίτων κατασκευαστών. -- απαλλαγείτε από όλα `require` -- φορτώνονται μόνο τα απαραίτητα σενάρια -- δεν απαιτεί αυστηρές συμβάσεις ονοματοδοσίας καταλόγων ή αρχείων +- Εξαλείψτε όλες τις δηλώσεις `require` +- Θα φορτώνονται μόνο τα απαραίτητα σενάρια +- Δεν απαιτεί αυστηρές συμβάσεις ονοματοδοσίας για καταλόγους ή αρχεία +- Εξαιρετικά γρήγορο +- Καμία χειροκίνητη ενημέρωση της προσωρινής μνήμης, όλα εκτελούνται αυτόματα +- Ώριμη, σταθερή και ευρέως χρησιμοποιούμενη βιβλιοθήκη
    -Μπορούμε λοιπόν να ξεχάσουμε αυτά τα περίφημα μπλοκ κώδικα: +Έτσι, μπορούμε να ξεχάσουμε αυτά τα γνωστά μπλοκ κώδικα: ```php require_once 'Utils/Page.php'; require_once 'Utils/Style.php'; require_once 'Utils/Paginator.php'; -// ... +//... ``` Εγκατάσταση .[#toc-installation] -------------------------------- -Μπορείτε να κατεβάσετε το RobotLoader ως ένα μεμονωμένο [αρχείο `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], το οποίο μπορείτε να συμπεριλάβετε στο σενάριό σας χρησιμοποιώντας το `require`, και να έχετε αμέσως βολική αυτόματη φόρτωση για ολόκληρη την εφαρμογή σας: +Μπορείτε να κατεβάσετε το RobotLoader ως ένα μεμονωμένο [αρχείο `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], το οποίο θα συμπεριλάβετε χρησιμοποιώντας το `require` στο σενάριό σας και θα απολαύσετε αμέσως άνετη αυτόματη φόρτωση για ολόκληρη την εφαρμογή. ```php require '/path/to/RobotLoader.php'; $loader = new Nette\Loaders\RobotLoader; -// ... +//... ``` -Εάν κατασκευάζετε μια εφαρμογή που χρησιμοποιεί το [Composer |best-practices:composer], μπορείτε να το εγκαταστήσετε μέσω αυτού: +Αν κατασκευάζετε μια εφαρμογή χρησιμοποιώντας το [Composer |best-practices:composer], μπορείτε να το εγκαταστήσετε μέσω: ```shell composer require nette/robot-loader @@ -43,27 +46,27 @@ composer require nette/robot-loader Χρήση .[#toc-usage] ------------------- -Όπως το ρομπότ της Google ανιχνεύει και ευρετηριάζει ιστότοπους, το [RobotLoader |api:Nette\Loaders\RobotLoader] ανιχνεύει όλα τα σενάρια PHP και καταγράφει ποιες κλάσεις και διεπαφές βρέθηκαν σε αυτά. Αυτές οι εγγραφές αποθηκεύονται στη συνέχεια στην κρυφή μνήμη και χρησιμοποιούνται κατά τη διάρκεια όλων των επόμενων αιτήσεων. Απλά πρέπει να καθορίσετε ποιοι κατάλογοι θα ευρετηριαστούν και πού θα αποθηκευτεί η κρυφή μνήμη: +Παρόμοια με τον τρόπο με τον οποίο το ρομπότ της Google ανιχνεύει και ευρετηριάζει ιστοσελίδες, ο [RobotLoader |api:Nette\Loaders\RobotLoader] περνάει από όλα τα σενάρια PHP και σημειώνει ποιες κλάσεις, διεπαφές, γνωρίσματα και enums βρήκε. Στη συνέχεια αποθηκεύει τα αποτελέσματα στην κρυφή μνήμη για χρήση σε επόμενες αιτήσεις. Απλά πρέπει να καθορίσετε ποιους καταλόγους θα πρέπει να περάσει και πού θα αποθηκεύσει την κρυφή μνήμη: ```php $loader = new Nette\Loaders\RobotLoader; -// κατάλογοι που θα ευρετηριαστεί από το RobotLoader (συμπεριλαμβανομένων των υποκαταλόγων) +// Κατάλογοι για τον RobotLoader για ευρετηρίαση (συμπεριλαμβανομένων των υποκαταλόγων) $loader->addDirectory(__DIR__ . '/app'); $loader->addDirectory(__DIR__ . '/libs'); -// χρήση του καταλόγου 'temp' για την κρυφή μνήμη +// Ορίστε την προσωρινή αποθήκευση στον κατάλογο 'temp' $loader->setTempDirectory(__DIR__ . '/temp'); -$loader->register(); // Εκτέλεση του RobotLoader +$loader->register(); // Ενεργοποίηση του RobotLoader ``` -Και αυτό είναι όλο. Από εδώ και στο εξής, δεν χρειάζεται να χρησιμοποιείτε το `require`. Υπέροχα, έτσι δεν είναι; +Και αυτό είναι όλο, από εδώ και πέρα, δεν χρειάζεται να χρησιμοποιήσουμε το `require`. Φοβερό! -Όταν το RobotLoader συναντά διπλότυπο όνομα κλάσης κατά τη διάρκεια της ευρετηρίασης, πετάει μια εξαίρεση και σας ενημερώνει σχετικά. Ο RobotLoader ενημερώνει επίσης αυτόματα την κρυφή μνήμη όταν πρέπει να φορτώσει μια κλάση που δεν γνωρίζει. Συνιστούμε να το απενεργοποιήσετε αυτό στους διακομιστές παραγωγής, δείτε την ενότητα [Caching |#Caching]. +Εάν το RobotLoader συναντήσει ένα διπλότυπο όνομα κλάσης κατά τη διάρκεια της ευρετηρίασης, θα πετάξει μια εξαίρεση και θα σας ειδοποιήσει. Ο RobotLoader ενημερώνει επίσης αυτόματα την κρυφή μνήμη όταν χρειάζεται να φορτώσει μια άγνωστη κλάση. Συνιστούμε να το απενεργοποιήσετε αυτό στους διακομιστές παραγωγής, δείτε την ενότητα [Caching |#Caching]. -Αν θέλετε ο RobotLoader να παραλείψει κάποιους καταλόγους, χρησιμοποιήστε το `$loader->excludeDirectory('temp')` (μπορεί να κληθεί πολλές φορές ή μπορείτε να περάσετε πολλούς καταλόγους). +Αν θέλετε το RobotLoader να παραλείπει ορισμένους καταλόγους, χρησιμοποιήστε το `$loader->excludeDirectory('temp')` (μπορεί να κληθεί πολλές φορές ή να περάσει πολλούς καταλόγους). -Από προεπιλογή, ο RobotLoader αναφέρει σφάλματα σε αρχεία PHP με την εμφάνιση εξαιρέσεων `ParseError`. Μπορεί να απενεργοποιηθεί μέσω του `$loader->reportParseErrors(false)`. +Από προεπιλογή, το RobotLoader αναφέρει σφάλματα σε αρχεία PHP πετώντας μια εξαίρεση `ParseError`. Αυτό μπορεί να καταστραφεί με τη χρήση του `$loader->reportParseErrors(false)`. Εφαρμογή Nette .[#toc-nette-application] @@ -73,7 +76,7 @@ $loader->register(); // Εκτέλεση του RobotLoader ```php $configurator = new Nette\Bootstrap\Configurator; -// ... +//... $configurator->setTempDirectory(__DIR__ . '/../temp'); $configurator->createRobotLoader() ->addDirectory(__DIR__) @@ -82,33 +85,35 @@ $configurator->createRobotLoader() ``` -PHP Files Analyzer .[#toc-php-files-analyzer] ---------------------------------------------- +Αναλυτής αρχείων PHP .[#toc-php-files-analyzer] +----------------------------------------------- -Το RobotLoader μπορεί επίσης να χρησιμοποιηθεί καθαρά για την εύρεση κλάσεων, διεπαφών και χαρακτηριστικών σε αρχεία PHP **χωρίς** να χρησιμοποιεί τη δυνατότητα αυτόματης φόρτωσης: +Το RobotLoader μπορεί επίσης να χρησιμοποιηθεί καθαρά για την εύρεση κλάσεων, διεπαφών, χαρακτηριστικών και enums σε αρχεία PHP **χωρίς** τη χρήση της λειτουργίας αυτόματης φόρτωσης: ```php $loader = new Nette\Loaders\RobotLoader; $loader->addDirectory(__DIR__ . '/app'); -// Σαρώνει καταλόγους για κλάσεις / διεπαφές / γνωρίσματα +// Σαρώνει καταλόγους για κλάσεις/διεπαφές/traits/enums $loader->rebuild(); -// Επιστρέφει πίνακα με ζεύγη κλάσεων => ονόματα αρχείων +// Επιστρέφει έναν πίνακα από ζεύγη κλάσεων => ονόματα αρχείων $res = $loader->getIndexedClasses(); ``` -Ακόμα και με μια τέτοια χρήση, μπορείτε να χρησιμοποιήσετε την κρυφή μνήμη. Ως αποτέλεσμα, τα μη τροποποιημένα αρχεία δεν θα αναλύονται επανειλημμένα κατά την εκ νέου σάρωση: +Ακόμα και με μια τέτοια χρήση, μπορείτε να χρησιμοποιήσετε την προσωρινή αποθήκευση. Αυτό διασφαλίζει ότι τα αμετάβλητα αρχεία δεν θα σαρωθούν εκ νέου: ```php $loader = new Nette\Loaders\RobotLoader; $loader->addDirectory(__DIR__ . '/app'); + +// Ορίστε την προσωρινή αποθήκευση στον κατάλογο 'temp' $loader->setTempDirectory(__DIR__ . '/temp'); -// Σαρώνει καταλόγους χρησιμοποιώντας μια κρυφή μνήμη +// Σαρώνει καταλόγους χρησιμοποιώντας την κρυφή μνήμη $loader->refresh(); -// Επιστρέφει πίνακα ζευγών κλάσης => όνομα αρχείου +// Επιστρέφει έναν πίνακα από ζεύγη κλάσης => όνομα αρχείου $res = $loader->getIndexedClasses(); ``` @@ -116,23 +121,23 @@ $res = $loader->getIndexedClasses(); Caching .[#toc-caching] ----------------------- -Το RobotLoader είναι πολύ γρήγορο επειδή χρησιμοποιεί έξυπνα την κρυφή μνήμη. +Το RobotLoader είναι πολύ γρήγορο επειδή χρησιμοποιεί έξυπνα την προσωρινή αποθήκευση. -Όταν αναπτύσσετε με αυτό, δεν έχετε σχεδόν καμία ιδέα ότι εκτελείται στο παρασκήνιο. Ενημερώνει συνεχώς την κρυφή μνήμη επειδή γνωρίζει ότι κλάσεις και αρχεία μπορούν να δημιουργηθούν, να διαγραφούν, να μετονομαστούν κ.λπ. Και δεν σαρώνει επανειλημμένα μη τροποποιημένα αρχεία. +Κατά τη διάρκεια της ανάπτυξης, δύσκολα θα παρατηρήσετε ότι εκτελείται στο παρασκήνιο. Ενημερώνει συνεχώς την κρυφή μνήμη του, λαμβάνοντας υπόψη ότι κλάσεις και αρχεία μπορούν να δημιουργηθούν, να διαγραφούν, να μετονομαστούν κ.λπ. Και δεν πραγματοποιεί εκ νέου σάρωση αμετάβλητων αρχείων. -Όταν χρησιμοποιείται σε έναν διακομιστή παραγωγής, από την άλλη πλευρά, συνιστούμε να απενεργοποιήσετε την ενημέρωση της κρυφής μνήμης χρησιμοποιώντας το `$loader->setAutoRefresh(false)` (αυτό γίνεται αυτόματα στην εφαρμογή Nette), επειδή τα αρχεία δεν αλλάζουν. Ταυτόχρονα, είναι απαραίτητο να **καθαρίσετε την προσωρινή μνήμη cache** όταν ανεβάζετε μια νέα έκδοση στη φιλοξενία. +Σε έναν διακομιστή παραγωγής, από την άλλη πλευρά, συνιστούμε να απενεργοποιήσετε τις ενημερώσεις της προσωρινής μνήμης με τη χρήση του `$loader->setAutoRefresh(false)` (σε μια εφαρμογή Nette, αυτό συμβαίνει αυτόματα), επειδή τα αρχεία δεν αλλάζουν. Ταυτόχρονα, είναι απαραίτητο να **καθαρίσετε την προσωρινή μνήμη cache** όταν ανεβάζετε μια νέα έκδοση στη φιλοξενία. -Φυσικά, η αρχική σάρωση των αρχείων, όταν η προσωρινή μνήμη δεν υπάρχει ήδη, μπορεί να διαρκέσει μερικά δευτερόλεπτα για μεγαλύτερες εφαρμογές. Το RobotLoader διαθέτει ενσωματωμένη πρόληψη κατά του "αφηνιασμού της κρυφής μνήμης":https://en.wikipedia.org/wiki/Cache_stampede. -Πρόκειται για μια κατάσταση κατά την οποία ο διακομιστής παραγωγής λαμβάνει μεγάλο αριθμό ταυτόχρονων αιτήσεων και επειδή η προσωρινή μνήμη cache του RobotLoader δεν υπάρχει ακόμη, θα ξεκινούσαν όλες να σαρώνουν τα αρχεία. Πράγμα που αυξάνει τη χρήση της CPU και του συστήματος αρχείων. -Ευτυχώς, το RobotLoader λειτουργεί με τέτοιο τρόπο ώστε για πολλαπλές ταυτόχρονες αιτήσεις, μόνο το πρώτο νήμα ευρετηριάζει τα αρχεία, δημιουργεί μια κρυφή μνήμη, οι υπόλοιποι περιμένουν και στη συνέχεια χρησιμοποιούν την κρυφή μνήμη. +Η αρχική σάρωση των αρχείων, όταν η κρυφή μνήμη δεν υπάρχει ακόμα, μπορεί φυσικά να πάρει λίγο χρόνο για μεγαλύτερες εφαρμογές. Το RobotLoader έχει ενσωματωμένη πρόληψη κατά της "αδημονία της cache":https://en.wikipedia.org/wiki/Cache_stampede. +Πρόκειται για μια κατάσταση όπου ένας μεγάλος αριθμός ταυτόχρονων αιτήσεων σε έναν διακομιστή παραγωγής θα ενεργοποιούσε το RobotLoader και, εφόσον η προσωρινή μνήμη δεν υπάρχει ακόμη, θα άρχιζαν όλες να σαρώνουν αρχεία, γεγονός που θα υπερφόρτωνε τον διακομιστή. +Ευτυχώς, το RobotLoader λειτουργεί με τέτοιο τρόπο ώστε μόνο το πρώτο νήμα να ευρετηριάζει τα αρχεία, να δημιουργεί την κρυφή μνήμη και τα υπόλοιπα να περιμένουν και στη συνέχεια να χρησιμοποιούν την κρυφή μνήμη. PSR-4 .[#toc-psr-4] ------------------- -Σήμερα, το Composer μπορεί να χρησιμοποιηθεί για [αυτόματη φόρτωση |best-practices:composer#autoloading] σύμφωνα με το PSR-4. Με απλά λόγια, πρόκειται για ένα σύστημα όπου τα namespaces και τα ονόματα των κλάσεων αντιστοιχούν στη δομή των καταλόγων και των ονομάτων των αρχείων, δηλαδή το `App\Router\RouterFactory` βρίσκεται στο αρχείο `/path/to/App/Router/RouterFactory.php`. +Σήμερα, μπορείτε να χρησιμοποιήσετε το [Composer για αυτόματη φόρτωση |best-practices:composer#autoloading] τηρώντας το PSR-4. Με απλά λόγια, πρόκειται για ένα σύστημα όπου τα namespaces και τα ονόματα των κλάσεων αντιστοιχούν στη δομή των καταλόγων και τα ονόματα των αρχείων, π.χ. το `App\Router\RouterFactory` θα βρίσκεται στο αρχείο `/path/to/App/Router/RouterFactory.php`. -Το RobotLoader δεν συνδέεται με καμία σταθερή δομή, επομένως, είναι χρήσιμο σε περιπτώσεις όπου δεν σας βολεύει να έχετε τη δομή καταλόγου σχεδιασμένη ως namespaces στην PHP, ή όταν αναπτύσσετε μια εφαρμογή που ιστορικά δεν έχει χρησιμοποιήσει τέτοιες συμβάσεις. Είναι επίσης δυνατό να χρησιμοποιήσετε και τους δύο φορτωτές μαζί. +Το RobotLoader δεν δεσμεύεται από καμία σταθερή δομή, οπότε είναι χρήσιμο σε περιπτώσεις όπου δεν θέλετε να έχετε τη δομή καταλόγου σχεδιασμένη ακριβώς όπως τα namespaces της PHP, ή όταν αναπτύσσετε μια εφαρμογή που ιστορικά δεν χρησιμοποιεί τέτοιες συμβάσεις. Είναι επίσης δυνατό να χρησιμοποιήσετε και τους δύο φορτωτές μαζί. {{leftbar: nette:@menu-topics}} diff --git a/robot-loader/en/@home.texy b/robot-loader/en/@home.texy index d8cb1f60fc..b3dac69a2f 100644 --- a/robot-loader/en/@home.texy +++ b/robot-loader/en/@home.texy @@ -5,13 +5,16 @@ RobotLoader: Class Autoloading RobotLoader is a tool that gives you comfort of automated class loading for your entire application including third-party libraries. -- get rid of all `require` -- only necessary scripts are loaded -- does not require strict directory or file naming conventions +- Eliminate all `require` statements +- Only necessary scripts will be loaded +- Doesn't require strict naming conventions for directories or files +- Extremely fast +- No manual cache updates, everything runs automatically +- Mature, stable and widely used library
    -So we can forget about those famous code blocks: +Thus, we can forget about these familiar code blocks: ```php require_once 'Utils/Page.php'; @@ -24,7 +27,7 @@ require_once 'Utils/Paginator.php'; Installation ------------ -You can download RobotLoader as a [single standalone file `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], which you can include in your script using `require`, and immediately have convenient autoloading for your entire application: +You can download RobotLoader as a [single standalone file `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], which you include using `require` in your script, and instantly enjoy comfortable autoloading for the entire application. ```php require '/path/to/RobotLoader.php'; @@ -33,7 +36,7 @@ $loader = new Nette\Loaders\RobotLoader; // ... ``` -If you are building an application that uses [Composer|best-practices:composer], you can install it through it: +If you're building an application using [Composer|best-practices:composer], you can install it via: ```shell composer require nette/robot-loader @@ -43,33 +46,33 @@ composer require nette/robot-loader Usage ----- -Like the Google robot crawls and indexes websites, [RobotLoader |api:Nette\Loaders\RobotLoader] crawls all PHP scripts and records what classes and interfaces were found in them. These records are then saved in cache and used during all subsequent requests. You just need to specify what directories to index and where to save the cache: +Similar to how the Google robot crawls and indexes web pages, the [RobotLoader |api:Nette\Loaders\RobotLoader] goes through all PHP scripts and notes which classes, interfaces, traits and enums it found. It then stores the results in cache for use in subsequent requests. You just need to specify which directories it should go through and where to store the cache: ```php $loader = new Nette\Loaders\RobotLoader; -// directories to be indexed by RobotLoader (including subdirectories) +// Directories for RobotLoader to index (including subdirectories) $loader->addDirectory(__DIR__ . '/app'); $loader->addDirectory(__DIR__ . '/libs'); -// use 'temp' directory for cache +// Set caching to the 'temp' directory $loader->setTempDirectory(__DIR__ . '/temp'); -$loader->register(); // Run the RobotLoader +$loader->register(); // Activate RobotLoader ``` -And that's all. From now on, you don't need to use `require`. Great, isn't it? +And that's it, from this point on, we don't need to use `require`. Awesome! -When RobotLoader encounters duplicate class name during indexing, it throws an exception and informs you about it. RobotLoader also automatically updates the cache when it has to load a class it doesn't know. We recommend disabling this on production servers, see [#Caching]. +If RobotLoader encounters a duplicate class name during indexing, it will throw an exception and notify you. RobotLoader also automatically updates the cache when it needs to load an unknown class. We recommend turning this off on production servers, see [#Caching]. -If you want RobotLoader to skip some directories, use `$loader->excludeDirectory('temp')` (it can be called multiple times or you can pass multiple directories). +If you want RobotLoader to skip certain directories, use `$loader->excludeDirectory('temp')` (can be called multiple times or pass multiple directories). -By default, RobotLoader reports errors in PHP files by throwing exception `ParseError`. It can be disabled via `$loader->reportParseErrors(false)`. +By default, RobotLoader reports errors in PHP files by throwing a `ParseError` exception. This can be suppressed using `$loader->reportParseErrors(false)`. Nette Application ----------------- -Inside Nette application, where `$configurator` is used in `Bootstrap.php`, you can setup RobotLoader this way: +Inside Nette Application, where `$configurator` is used in `Bootstrap.php`, you can setup RobotLoader this way: ```php $configurator = new Nette\Bootstrap\Configurator; @@ -85,30 +88,32 @@ $configurator->createRobotLoader() PHP Files Analyzer ------------------ -RobotLoader can also be used purely to find classes, interfaces, and trait in PHP files **without** using the autoloading feature: +RobotLoader can also be used purely for finding classes, interfaces, traits and enums in PHP files **without** using the autoloading function: ```php $loader = new Nette\Loaders\RobotLoader; $loader->addDirectory(__DIR__ . '/app'); -// Scans directories for classes / interfaces / traits +// Scans directories for classes/interfaces/traits/enums $loader->rebuild(); -// Returns array of class => filename pairs +// Returns an array of class => filename pairs $res = $loader->getIndexedClasses(); ``` -Even with such use, you can use the cache. As a result, unmodified files will not be repeatedly analyzed when rescanning: +Even with such usage, you can utilize caching. This ensures that unchanged files won't be rescanned: ```php $loader = new Nette\Loaders\RobotLoader; $loader->addDirectory(__DIR__ . '/app'); + +// Set caching to the 'temp' directory $loader->setTempDirectory(__DIR__ . '/temp'); -// Scans directories using a cache +// Scans directories using cache $loader->refresh(); -// Returns array of class => filename pairs +// Returns an array of class => filename pairs $res = $loader->getIndexedClasses(); ``` @@ -116,23 +121,23 @@ $res = $loader->getIndexedClasses(); Caching ------- -RobotLoader is very fast because it cleverly uses the cache. +RobotLoader is very fast because it cleverly uses caching. -When developing with it, you have practically no idea that it runs on the background. It continuously updates the cache because it knows that classes and files can be created, deleted, renamed, etc. And it doesn't repeatedly scan unmodified files. +During development, you hardly notice it running in the background. It continuously updates its cache, considering that classes and files can be created, deleted, renamed, etc. And it doesn't rescan unchanged files. -When used on a production server, on the other hand, we recommend disabling the cache update using `$loader->setAutoRefresh(false)` (this is done automatically in the Nette Application), because the files are not changing. At the same time, it is necessary to **clear the cache** when uploading a new version on the hosting. +On a production server, on the other hand, we recommend turning off cache updates using `$loader->setAutoRefresh(false)` (in a Nette Application, this happens automatically), because files don't change. At the same time, it's necessary to **clear the cache** when uploading a new version to hosting. -Of course, the initial scanning of files, when the cache does not already exist, may take a few seconds for larger applications. RobotLoader has built-in prevention against "cache stampede":https://en.wikipedia.org/wiki/Cache_stampede. -This is a situation where production server receives a large number of concurrent requests and because RobotLoader's cache does not yet exist, they would all start scanning the files. Which spikes CPU and filesystem usage. -Fortunately, RobotLoader works in such a way that for multiple concurrent requests, only the first thread indexes the files, creates a cache, the others wait, and then use the cache. +The initial file scanning, when the cache doesn't exist yet, can naturally take a moment for larger applications. RobotLoader has built-in prevention against "cache stampede":https://en.wikipedia.org/wiki/Cache_stampede. +This is a situation where a large number of concurrent requests on a production server would trigger RobotLoader, and since the cache doesn't exist yet, they would all start scanning files, which would overload the server. +Fortunately, RobotLoader works in such a way that only the first thread indexes the files, creates the cache, and the rest wait and then use the cache. PSR-4 ----- -Today, Composer can be used for [autoloading|best-practices:composer#autoloading] in compliance with PSR-4. Simply saying, it is a system where the namespaces and class names correspond to the directory structure and file names, ie `App\Router\RouterFactory` is located in the file `/path/to/App/Router/RouterFactory.php`. +Nowadays, you can use [Composer for autoloading|best-practices:composer#autoloading] while adhering to PSR-4. Simply put, it's a system where namespaces and class names correspond to the directory structure and file names, e.g., `App\Router\RouterFactory` will be in the file `/path/to/App/Router/RouterFactory.php`. -RobotLoader is not tied to any fixed structure, therefore, it is useful in situations where it does not suit you to have the directory structure designed as namespaces in PHP, or when you are developing an application that has historically not used such conventions. It is also possible to use both loaders together. +RobotLoader isn't tied to any fixed structure, so it's useful in situations where you don't want to have the directory structure designed exactly like the PHP namespaces, or when developing an application that historically doesn't use such conventions. It's also possible to use both loaders together. {{leftbar: nette:@menu-topics}} diff --git a/robot-loader/es/@home.texy b/robot-loader/es/@home.texy index 24506e56b0..cc61ef4d2f 100644 --- a/robot-loader/es/@home.texy +++ b/robot-loader/es/@home.texy @@ -5,35 +5,38 @@ RobotLoader: Carga automática de clases RobotLoader es una herramienta que le ofrece la comodidad de la carga automática de clases para toda su aplicación, incluidas las bibliotecas de terceros. -- deshacerse de todos `require` -- sólo se cargan los scripts necesarios -- no requiere estrictas convenciones de nomenclatura de directorios o archivos +- Elimina todas las sentencias `require` +- Sólo se cargarán los scripts necesarios +- No requiere convenciones de nomenclatura estrictas para directorios o archivos +- Extremadamente rápido +- Sin actualizaciones manuales de la caché, todo se ejecuta automáticamente +- Biblioteca madura, estable y ampliamente utilizada
    -Así que podemos olvidarnos de los famosos bloques de código: +Así, podemos olvidarnos de estos bloques de código tan familiares: ```php require_once 'Utils/Page.php'; require_once 'Utils/Style.php'; require_once 'Utils/Paginator.php'; -// ... +//... ``` Instalación .[#toc-installation] -------------------------------- -Puede descargar RobotLoader como un [único archivo independiente `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], que puede incluir en su script utilizando `require`, y disponer inmediatamente de una cómoda carga automática para toda su aplicación: +Puede descargar RobotLoader como un [único archivo independiente `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], que incluirá utilizando `require` en su script, y disfrutar al instante de una cómoda carga automática para toda la aplicación. ```php require '/path/to/RobotLoader.php'; $loader = new Nette\Loaders\RobotLoader; -// ... +//... ``` -Si estás construyendo una aplicación que utiliza [Composer |best-practices:composer], puedes instalarlo a través de él: +Si estás construyendo una aplicación usando [Composer |best-practices:composer], puedes instalarlo a través de: ```shell composer require nette/robot-loader @@ -43,37 +46,37 @@ composer require nette/robot-loader Utilización .[#toc-usage] ------------------------- -Al igual que el robot de Google rastrea e indexa sitios web, [RobotLoader |api:Nette\Loaders\RobotLoader] rastrea todos los scripts PHP y registra qué clases e interfaces se encontraron en ellos. Estos registros se guardan en la caché y se utilizan durante todas las solicitudes posteriores. Sólo necesita especificar qué directorios indexar y dónde guardar la caché: +De forma similar a como el robot de Google rastrea e indexa páginas web, el [RobotLoader |api:Nette\Loaders\RobotLoader] recorre todos los scripts PHP y anota las clases, interfaces, traits y enums que encuentra. A continuación, almacena los resultados en la caché para su uso en solicitudes posteriores. Sólo tienes que especificar qué directorios debe recorrer y dónde almacenar la caché: ```php $loader = new Nette\Loaders\RobotLoader; -// directorios a indexar por RobotLoader (incluyendo subdirectorios) +// Directorios que RobotLoader debe indexar (incluidos los subdirectorios) $loader->addDirectory(__DIR__ . '/app'); $loader->addDirectory(__DIR__ . '/libs'); -// usar directorio 'temp' para caché +// Establecer la caché en el directorio 'temp $loader->setTempDirectory(__DIR__ . '/temp'); -$loader->register(); // Ejecutar el RobotLoader +$loader->register(); // Activar RobotLoader ``` -Y eso es todo. A partir de ahora, no necesitará utilizar `require`. Estupendo, ¿verdad? +Y ya está, a partir de este momento no necesitamos usar `require`. ¡Impresionante! -Cuando RobotLoader encuentra un nombre de clase duplicado durante la indexación, lanza una excepción y te informa de ello. RobotLoader también actualiza automáticamente la caché cuando tiene que cargar una clase que no conoce. Recomendamos desactivar esto en los servidores de producción, ver [Caché |#Caching]. +Si RobotLoader encuentra un nombre de clase duplicado durante la indexación, lanzará una excepción y te lo notificará. RobotLoader también actualiza automáticamente la caché cuando necesita cargar una clase desconocida. Recomendamos desactivar esta opción en servidores de producción, ver [Caché |#Caching]. -Si quieres que RobotLoader se salte algunos directorios, utiliza `$loader->excludeDirectory('temp')` (se puede llamar varias veces o puedes pasar varios directorios). +Si desea que RobotLoader omita ciertos directorios, utilice `$loader->excludeDirectory('temp')` (puede llamarse varias veces o pasar varios directorios). -Por defecto, RobotLoader informa de errores en archivos PHP lanzando la excepción `ParseError`. Se puede desactivar a través de `$loader->reportParseErrors(false)`. +Por defecto, RobotLoader informa de errores en archivos PHP lanzando una excepción `ParseError`. Esto puede suprimirse usando `$loader->reportParseErrors(false)`. Aplicación Nette .[#toc-nette-application] ------------------------------------------ -Dentro de la aplicación Nette, donde `$configurator` se utiliza en `Bootstrap.php`, puede configurar RobotLoader de esta manera: +Dentro de la Aplicación Nette, donde `$configurator` se utiliza en `Bootstrap.php`, puede configurar RobotLoader de esta manera: ```php $configurator = new Nette\Bootstrap\Configurator; -// ... +//... $configurator->setTempDirectory(__DIR__ . '/../temp'); $configurator->createRobotLoader() ->addDirectory(__DIR__) @@ -85,27 +88,29 @@ $configurator->createRobotLoader() Analizador de archivos PHP .[#toc-php-files-analyzer] ----------------------------------------------------- -RobotLoader también puede ser usado puramente para encontrar clases, interfaces y traits en archivos PHP **sin** usar la característica de autocarga: +RobotLoader también puede ser usado puramente para encontrar clases, interfaces, traits y enums en archivos PHP **sin** usar la función de autocarga: ```php $loader = new Nette\Loaders\RobotLoader; $loader->addDirectory(__DIR__ . '/app'); -// Busca clases / interfaces / traits en los directorios +// Escanea directorios en busca de clases/interfaces/traits/enums $loader->rebuild(); // Devuelve un array de pares clase => nombre de fichero $res = $loader->getIndexedClasses(); ``` -Incluso con tal uso, puede utilizar la caché. Como resultado, los archivos no modificados no serán analizados repetidamente al volver a escanear: +Incluso con este uso, puede utilizar el almacenamiento en caché. Esto asegura que los archivos no modificados no serán escaneados de nuevo: ```php $loader = new Nette\Loaders\RobotLoader; $loader->addDirectory(__DIR__ . '/app'); + +// Establece la caché en el directorio 'temp $loader->setTempDirectory(__DIR__ . '/temp'); -// Escanea directorios usando una caché +// Escanea los directorios usando la caché $loader->refresh(); // Devuelve un array de pares clase => nombre de fichero @@ -116,23 +121,23 @@ $res = $loader->getIndexedClasses(); Almacenamiento en caché .[#toc-caching] --------------------------------------- -RobotLoader es muy rápido porque utiliza inteligentemente la caché. +RobotLoader es muy rápido porque utiliza inteligentemente el almacenamiento en caché. -Cuando desarrollas con él, prácticamente no tienes ni idea de que se ejecuta en segundo plano. Actualiza continuamente la caché porque sabe que las clases y archivos pueden ser creados, borrados, renombrados, etc. Y no escanea repetidamente archivos no modificados. +Durante el desarrollo, apenas se nota que está funcionando en segundo plano. Actualiza continuamente su caché, teniendo en cuenta que las clases y archivos pueden ser creados, borrados, renombrados, etc. Y no vuelve a escanear los archivos no modificados. -En cambio, cuando se utiliza en un servidor de producción, se recomienda desactivar la actualización de la caché mediante `$loader->setAutoRefresh(false)` (esto se hace automáticamente en la aplicación Nette), porque los ficheros no cambian. Al mismo tiempo, es necesario **limpiar la caché** al subir una nueva versión al hosting. +En un servidor de producción, en cambio, recomendamos desactivar las actualizaciones de la caché mediante `$loader->setAutoRefresh(false)` (en una aplicación Nette, esto sucede automáticamente), porque los archivos no cambian. Al mismo tiempo, es necesario **limpiar la caché** cuando se sube una nueva versión al hosting. -Por supuesto, el escaneo inicial de los archivos, cuando la caché no existe ya, puede tardar unos segundos para las aplicaciones más grandes. RobotLoader tiene incorporada una prevención contra la "estampida de:https://en.wikipedia.org/wiki/Cache_stampede caché". -Se trata de una situación en la que el servidor de producción recibe un gran número de peticiones simultáneas y, debido a que la caché de RobotLoader aún no existe, todas ellas comenzarían a escanear los archivos. Lo que dispara el uso de la CPU y del sistema de archivos. -Afortunadamente, RobotLoader funciona de tal manera que para múltiples peticiones concurrentes, sólo el primer hilo indexa los archivos, crea una caché, los demás esperan, y luego utilizan la caché. +El escaneo inicial de archivos, cuando la caché aún no existe, puede tardar un momento en las aplicaciones más grandes. RobotLoader tiene incorporada una prevención contra la "estampida de:https://en.wikipedia.org/wiki/Cache_stampede caché". +Esta es una situación en la que un gran número de peticiones concurrentes en un servidor de producción activaría RobotLoader, y puesto que la caché no existe todavía, todos empezarían a escanear archivos, lo que sobrecargaría el servidor. +Afortunadamente, RobotLoader funciona de tal manera que sólo el primer hilo indexa los archivos, crea la caché, y el resto espera y luego utiliza la caché. PSR-4 .[#toc-psr-4] ------------------- -En la actualidad, Composer puede utilizarse para la [autolectura |best-practices:composer#autoloading] de conformidad con PSR-4. En pocas palabras, se trata de un sistema en el que los espacios de nombres y los nombres de las clases se corresponden con la estructura de directorios y los nombres de los archivos, es decir, `App\Router\RouterFactory` se encuentra en el archivo `/path/to/App/Router/RouterFactory.php`. +Hoy en día, se puede utilizar [Composer para la autocarga |best-practices:composer#autoloading] respetando PSR-4. En pocas palabras, se trata de un sistema en el que los espacios de nombres y los nombres de las clases se corresponden con la estructura de directorios y los nombres de los archivos; por ejemplo, `App\Router\RouterFactory` estará en el archivo `/path/to/App/Router/RouterFactory.php`. -RobotLoader no está atado a ninguna estructura fija, por lo tanto, es útil en situaciones donde no le conviene tener la estructura de directorios diseñada como namespaces en PHP, o cuando está desarrollando una aplicación que históricamente no ha usado tales convenciones. También es posible usar ambos cargadores juntos. +RobotLoader no está atado a ninguna estructura fija, por lo que es útil en situaciones en las que no se desea tener la estructura de directorios diseñada exactamente como los espacios de nombres de PHP, o cuando se desarrolla una aplicación que históricamente no utiliza tales convenciones. También es posible usar ambos cargadores juntos. {{leftbar: nette:@menu-topics}} diff --git a/robot-loader/fr/@home.texy b/robot-loader/fr/@home.texy index cceff67b9a..801d5dfa4d 100644 --- a/robot-loader/fr/@home.texy +++ b/robot-loader/fr/@home.texy @@ -1,39 +1,42 @@ -RobotLoader : Auto-chargement des classes -***************************************** +RobotLoader : Autoloading de classe +***********************************
    -RobotLoader est un outil qui vous offre le confort du chargement automatique des classes pour l'ensemble de votre application, y compris les bibliothèques tierces. +RobotLoader est un outil qui vous permet de charger automatiquement des classes pour l'ensemble de votre application, y compris les bibliothèques tierces. -- se débarrasser de tout `require` -- seuls les scripts nécessaires sont chargés -- ne nécessite pas de conventions strictes en matière de nom de répertoire ou de fichier +- Éliminez toutes les déclarations `require` +- Seuls les scripts nécessaires seront chargés +- Ne nécessite pas de conventions de nommage strictes pour les répertoires ou les fichiers +- Extrêmement rapide +- Pas de mise à jour manuelle du cache, tout s'exécute automatiquement +- Bibliothèque mature, stable et largement utilisée
    -On peut donc oublier ces fameux blocs de code : +Nous pouvons donc oublier ces blocs de code familiers : ```php require_once 'Utils/Page.php'; require_once 'Utils/Style.php'; require_once 'Utils/Paginator.php'; -// ... +//... ``` Installation .[#toc-installation] --------------------------------- -Vous pouvez télécharger RobotLoader sous la forme d'un [fichier autonome `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], que vous pouvez inclure dans votre script à l'aide de `require`, et disposer immédiatement d'un chargement automatique pratique pour l'ensemble de votre application : +Vous pouvez télécharger RobotLoader sous la forme d'un [seul fichier autonome `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], que vous incluez à l'aide de `require` dans votre script, et profiter instantanément d'un chargement automatique confortable pour l'ensemble de l'application. ```php require '/path/to/RobotLoader.php'; $loader = new Nette\Loaders\RobotLoader; -// ... +//... ``` -Si vous construisez une application qui utilise [Composer |best-practices:composer], vous pouvez l'installer par l'intermédiaire de ce dernier : +Si vous construisez une application à l'aide de [Composer |best-practices:composer], vous pouvez l'installer via : ```shell composer require nette/robot-loader @@ -43,27 +46,27 @@ composer require nette/robot-loader Utilisation .[#toc-usage] ------------------------- -Tout comme le robot Google explore et indexe les sites Web, [RobotLoader |api:Nette\Loaders\RobotLoader] explore tous les scripts PHP et enregistre les classes et les interfaces qu'ils contiennent. Ces enregistrements sont ensuite sauvegardés dans le cache et utilisés lors de toutes les requêtes ultérieures. Il vous suffit de spécifier les répertoires à indexer et l'endroit où sauvegarder le cache : +De la même manière que le robot Google parcourt et indexe les pages web, [RobotLoader |api:Nette\Loaders\RobotLoader] parcourt tous les scripts PHP et note les classes, interfaces, traits et enums qu'il a trouvés. Il stocke ensuite les résultats dans le cache pour les utiliser lors de requêtes ultérieures. Il vous suffit de spécifier les répertoires qu'il doit parcourir et l'endroit où il doit stocker le cache : ```php $loader = new Nette\Loaders\RobotLoader; -// répertoires à indexer par RobotLoader (y compris les sous-répertoires) +// Répertoires à indexer par RobotLoader (y compris les sous-répertoires) $loader->addDirectory(__DIR__ . '/app'); $loader->addDirectory(__DIR__ . '/libs'); -// utiliser le répertoire 'temp' pour le cache +// Définir la mise en cache dans le répertoire "temp". $loader->setTempDirectory(__DIR__ . '/temp'); -$loader->register(); // Exécution du RobotLoader +$loader->register(); // Activer RobotLoader ``` -Et c'est tout. A partir de maintenant, vous n'avez plus besoin d'utiliser `require`. Super, n'est-ce pas ? +Et c'est tout, à partir de maintenant, nous n'avons plus besoin d'utiliser `require`. Génial ! -Lorsque RobotLoader rencontre un nom de classe en double pendant l'indexation, il lève une exception et vous en informe. RobotLoader met aussi automatiquement à jour le cache lorsqu'il doit charger une classe qu'il ne connaît pas. Nous recommandons de désactiver cette fonction sur les serveurs de production, voir [Mise en cache |#Caching]. +Si RobotLoader rencontre un nom de classe dupliqué pendant l'indexation, il lèvera une exception et vous en informera. RobotLoader met également à jour automatiquement le cache lorsqu'il doit charger une classe inconnue. Nous recommandons de désactiver cette fonction sur les serveurs de production, voir [Caching |#Caching]. -Si vous voulez que RobotLoader saute certains répertoires, utilisez `$loader->excludeDirectory('temp')` (il peut être appelé plusieurs fois ou vous pouvez passer plusieurs répertoires). +Si vous souhaitez que RobotLoader ignore certains répertoires, utilisez `$loader->excludeDirectory('temp')` (peut être appelé plusieurs fois ou passer plusieurs répertoires). -Par défaut, RobotLoader signale les erreurs dans les fichiers PHP en lançant l'exception `ParseError`. Elle peut être désactivée via `$loader->reportParseErrors(false)`. +Par défaut, RobotLoader signale les erreurs dans les fichiers PHP en lançant une exception `ParseError`. Cette exception peut être supprimée en utilisant `$loader->reportParseErrors(false)`. Application Nette .[#toc-nette-application] @@ -73,7 +76,7 @@ Dans l'application Nette, où `$configurator` est utilisé dans `Bootstrap.php`, ```php $configurator = new Nette\Bootstrap\Configurator; -// ... +//... $configurator->setTempDirectory(__DIR__ . '/../temp'); $configurator->createRobotLoader() ->addDirectory(__DIR__) @@ -85,27 +88,29 @@ $configurator->createRobotLoader() Analyseur de fichiers PHP .[#toc-php-files-analyzer] ---------------------------------------------------- -RobotLoader peut aussi être utilisé uniquement pour trouver des classes, des interfaces et des traits dans les fichiers PHP **sans utiliser la fonction de chargement automatique : +RobotLoader peut également être utilisé uniquement pour trouver des classes, des interfaces, des traits et des enums dans les fichiers PHP **sans** utiliser la fonction d'autoloading : ```php $loader = new Nette\Loaders\RobotLoader; $loader->addDirectory(__DIR__ . '/app'); -// Recherche des classes, interfaces et traits dans les répertoires. +// Recherche les classes/interfaces/traits/enums dans les répertoires $loader->rebuild(); // Retourne un tableau de paires classe => nom de fichier $res = $loader->getIndexedClasses(); ``` -Même avec une telle utilisation, vous pouvez utiliser le cache. Ainsi, les fichiers non modifiés ne seront pas analysés à plusieurs reprises lors d'une nouvelle recherche : +Même avec une telle utilisation, vous pouvez utiliser la mise en cache. Cela permet de s'assurer que les fichiers inchangés ne seront pas analysés à nouveau : ```php $loader = new Nette\Loaders\RobotLoader; $loader->addDirectory(__DIR__ . '/app'); + +// Définit la mise en cache dans le répertoire "temp". $loader->setTempDirectory(__DIR__ . '/temp'); -// Analyse des répertoires en utilisant un cache +// Analyse les répertoires en utilisant le cache $loader->refresh(); // Retourne un tableau de paires classe => nom de fichier @@ -116,23 +121,23 @@ $res = $loader->getIndexedClasses(); Mise en cache .[#toc-caching] ----------------------------- -RobotLoader est très rapide car il utilise intelligemment le cache. +RobotLoader est très rapide parce qu'il utilise intelligemment la mise en cache. -Lorsque vous développez avec lui, vous n'avez pratiquement aucune idée qu'il fonctionne en arrière-plan. Il met continuellement à jour le cache car il sait que les classes et les fichiers peuvent être créés, supprimés, renommés, etc. Et il n'analyse pas de manière répétée les fichiers non modifiés. +Pendant le développement, vous remarquez à peine qu'il fonctionne en arrière-plan. Il met continuellement à jour son cache, en tenant compte du fait que les classes et les fichiers peuvent être créés, supprimés, renommés, etc. Et il ne rescanne pas les fichiers inchangés. -En revanche, lorsqu'il est utilisé sur un serveur de production, nous recommandons de désactiver la mise à jour du cache à l'aide de `$loader->setAutoRefresh(false)` (cela se fait automatiquement dans l'application Nette), car les fichiers ne changent pas. En même temps, il est nécessaire de **nettoyer le cache** lors du téléchargement d'une nouvelle version sur l'hébergement. +Sur un serveur de production, en revanche, nous recommandons de désactiver les mises à jour du cache à l'aide de `$loader->setAutoRefresh(false)` (dans une application Nette, cela se fait automatiquement), car les fichiers ne changent pas. En même temps, il est nécessaire de **vider le cache** lors de l'envoi d'une nouvelle version à l'hébergement. -Bien sûr, le balayage initial des fichiers, lorsque le cache n'existe pas encore, peut prendre quelques secondes pour les applications plus importantes. RobotLoader a une prévention intégrée contre la "ruée vers le cache":https://en.wikipedia.org/wiki/Cache_stampede. -Il s'agit d'une situation dans laquelle le serveur de production reçoit un grand nombre de demandes simultanées et, comme le cache de RobotLoader n'existe pas encore, elles commencent toutes à analyser les fichiers. Ce qui fait monter en flèche l'utilisation du CPU et du système de fichiers. -Heureusement, RobotLoader fonctionne de telle manière que pour plusieurs demandes simultanées, seul le premier thread indexe les fichiers, crée un cache, les autres attendent, puis utilisent le cache. +L'analyse initiale des fichiers, lorsque le cache n'existe pas encore, peut naturellement prendre un certain temps pour les grandes applications. RobotLoader dispose d'une prévention intégrée contre la "ruée vers le cache":https://en.wikipedia.org/wiki/Cache_stampede. +Il s'agit d'une situation dans laquelle un grand nombre de demandes simultanées sur un serveur de production déclencherait RobotLoader, et comme le cache n'existe pas encore, elles commenceraient toutes à analyser les fichiers, ce qui surchargerait le serveur. +Heureusement, RobotLoader fonctionne de telle manière que seul le premier thread indexe les fichiers, crée le cache, et que les autres attendent et utilisent ensuite le cache. PSR-4 .[#toc-psr-4] ------------------- -Aujourd'hui, Composer peut être utilisé pour l'[autoloading |best-practices:composer#autoloading] en conformité avec PSR-4. En d'autres termes, il s'agit d'un système où les espaces de noms et les noms de classes correspondent à la structure des répertoires et aux noms de fichiers, c'est-à-dire que `App\Router\RouterFactory` est situé dans le fichier `/path/to/App/Router/RouterFactory.php`. +Aujourd'hui, vous pouvez utiliser [Composer pour l'autoloading |best-practices:composer#autoloading] tout en adhérant à PSR-4. En termes simples, il s'agit d'un système dans lequel les espaces de noms et les noms de classes correspondent à la structure des répertoires et aux noms de fichiers, par exemple, `App\Router\RouterFactory` sera dans le fichier `/path/to/App/Router/RouterFactory.php`. -RobotLoader n'est lié à aucune structure fixe, il est donc utile dans les situations où il ne vous convient pas d'avoir une structure de répertoire conçue comme des espaces de noms en PHP, ou lorsque vous développez une application qui n'a historiquement pas utilisé de telles conventions. Il est également possible d'utiliser les deux chargeurs ensemble. +RobotLoader n'est pas lié à une structure fixe, il est donc utile dans les situations où vous ne voulez pas que la structure du répertoire soit conçue exactement comme les espaces de noms PHP, ou lorsque vous développez une application qui n'utilise pas historiquement de telles conventions. Il est également possible d'utiliser les deux chargeurs ensemble. {{leftbar: nette:@menu-topics}} diff --git a/robot-loader/hu/@home.texy b/robot-loader/hu/@home.texy index 45165f62b5..fc7f4ff69d 100644 --- a/robot-loader/hu/@home.texy +++ b/robot-loader/hu/@home.texy @@ -5,65 +5,68 @@ RobotLoader: Osztály automatikus betöltése A RobotLoader egy olyan eszköz, amely kényelmet biztosít az automatikus osztálybetöltés számára a teljes alkalmazásod számára, beleértve a harmadik féltől származó könyvtárakat is. -- megszabadul az összes `require` -- csak a szükséges szkriptek töltődnek be -- nem igényel szigorú könyvtár- vagy fájlnevezési konvenciókat +- Megszünteti az összes `require` utasítást +- Csak a szükséges szkriptek töltődnek be +- Nem igényel szigorú elnevezési konvenciókat a könyvtárak vagy fájlok számára +- Rendkívül gyors +- Nincs manuális gyorsítótár frissítés, minden automatikusan fut +- Kiforrott, stabil és széles körben használt könyvtár
    -Tehát elfelejthetjük a híres kódblokkokat: +Így elfelejthetjük ezeket az ismerős kódblokkokat: ```php require_once 'Utils/Page.php'; require_once 'Utils/Style.php'; require_once 'Utils/Paginator.php'; -// ... +//... ``` Telepítés .[#toc-installation] ------------------------------ -A RobotLoader egyetlen önálló fájlként letölthető [`RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], amelyet a `require` segítségével beilleszthet a szkriptjébe, és máris kényelmes automatikus betöltés áll rendelkezésére az egész alkalmazás számára: +A RobotLoader egyetlen önálló fájlként [letölthető `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], amelyet a `require` segítségével a szkriptjébe illeszthet, és azonnal élvezheti az egész alkalmazás kényelmes automatikus betöltését. ```php require '/path/to/RobotLoader.php'; $loader = new Nette\Loaders\RobotLoader; -// ... +//... ``` -Ha olyan alkalmazást készít, amely a [Composert |best-practices:composer] használja, akkor azon keresztül telepítheti: +Ha [Composer |best-practices:composer] segítségével építesz alkalmazást, akkor telepítheted a: ```shell composer require nette/robot-loader ``` -Használat: .[#toc-usage] ------------------------- +Használat .[#toc-usage] +----------------------- -Ahogy a Google robot feltérképezi és indexeli a weboldalakat, a [RobotLoader |api:Nette\Loaders\RobotLoader] is feltérképezi az összes PHP szkriptet, és rögzíti, hogy milyen osztályokat és interfészeket találtak bennük. Ezek a rekordok a gyorsítótárba kerülnek, és minden későbbi lekérdezés során felhasználásra kerülnek. Csak azt kell megadni, hogy milyen könyvtárakat indexeljen és hova mentse a gyorsítótárat: +Hasonlóan ahhoz, ahogyan a Google robot feltérképezi és indexeli a weboldalakat, a [RobotLoader |api:Nette\Loaders\RobotLoader] végigmegy az összes PHP szkripten, és megjegyzi, hogy milyen osztályokat, interfészeket, tulajdonságokat és enumokat talált. Ezután az eredményeket a gyorsítótárban tárolja, hogy a későbbi lekérdezések során felhasználhassa. Csak azt kell megadni, hogy mely könyvtárakon menjen keresztül, és hol tárolja a gyorsítótárat: ```php $loader = new Nette\Loaders\RobotLoader; -// a RobotLoader által indexelendő könyvtárak (beleértve az alkönyvtárakat is) +// A RobotLoader által indexelendő könyvtárak (beleértve az alkönyvtárakat is) $loader->addDirectory(__DIR__ . '/app'); $loader->addDirectory(__DIR__ . '/libs'); -// 'temp' könyvtár használata a gyorsítótárhoz +// A gyorsítótárazást a 'temp' könyvtárra állítsa be $loader->setTempDirectory(__DIR__ . '/temp'); -$loader->register(); // RobotLoader futtatása +$loader->register(); // RobotLoader aktiválása ``` -És ez minden. Mostantól kezdve nem kell a `require` címet használnod. Nagyszerű, nem igaz? +És ennyi, innentől kezdve nem kell használnunk a `require` címet. Félelmetes! -Ha a RobotLoader az indexelés során duplikált osztálynévvel találkozik, kivételt dob, és tájékoztatja Önt erről. A RobotLoader automatikusan frissíti a gyorsítótárat is, ha olyan osztályt kell betöltenie, amelyet nem ismer. Javasoljuk ennek kikapcsolását a produktív szervereken, lásd a [Caching |#Caching]. +Ha a RobotLoader az indexelés során duplikált osztálynévvel találkozik, akkor kivételt dob és értesítést küld. A RobotLoader automatikusan frissíti a gyorsítótárat is, ha egy ismeretlen osztályt kell betöltenie. Javasoljuk, hogy ezt kapcsolja ki a termelő szervereken, lásd [Cache |#Caching]. -Ha azt szeretné, hogy a RobotLoader kihagyjon néhány könyvtárat, használja a `$loader->excludeDirectory('temp')` címet (többször is meghívható, vagy több könyvtárat is átadhat). +Ha azt szeretné, hogy a RobotLoader kihagyjon bizonyos könyvtárakat, használja a `$loader->excludeDirectory('temp')` címet (többször is hívható, vagy több könyvtárat is átadhat). -Alapértelmezés szerint a RobotLoader a PHP-fájlok hibáit a `ParseError` kivétel dobásával jelzi. Ez kikapcsolható a `$loader->reportParseErrors(false)` segítségével. +Alapértelmezés szerint a RobotLoader a PHP-fájlok hibáit a `ParseError` kivétel dobásával jelzi. Ez a `$loader->reportParseErrors(false)` használatával elnyomható. Nette alkalmazás .[#toc-nette-application] @@ -73,7 +76,7 @@ A Nette alkalmazáson belül, ahol a `$configurator` a `Bootstrap.php` oldalon t ```php $configurator = new Nette\Bootstrap\Configurator; -// ... +//... $configurator->setTempDirectory(__DIR__ . '/../temp'); $configurator->createRobotLoader() ->addDirectory(__DIR__) @@ -82,27 +85,29 @@ $configurator->createRobotLoader() ``` -PHP Files Analyzer .[#toc-php-files-analyzer] ---------------------------------------------- +PHP fájlok elemzője .[#toc-php-files-analyzer] +---------------------------------------------- -A RobotLoader használható pusztán osztályok, interfészek és tulajdonságok keresésére is a PHP fájlokban **az automatikus betöltés funkció használata nélkül**: +A RobotLoader használható pusztán osztályok, interfészek, tulajdonságok és enumok keresésére PHP fájlokban **az automatikus betöltés funkció használata nélkül** is: ```php $loader = new Nette\Loaders\RobotLoader; $loader->addDirectory(__DIR__ . '/app'); -// Átvizsgálja a könyvtárakat osztályok / interfészek / tulajdonságok után. +// Átvizsgálja a könyvtárakat osztályok/interfészek/traits/enumok után. $loader->rebuild(); // Visszaadja az osztály => fájlnév párok tömbjét. $res = $loader->getIndexedClasses(); ``` -Ilyen használat esetén is használhatja a gyorsítótárat. Ennek eredményeképpen a nem módosított fájlok nem kerülnek ismételten elemzésre az újbóli szkennelés során: +Még ilyen használat esetén is kihasználhatja a gyorsítótárazást. Ez biztosítja, hogy a változatlan fájlok nem lesznek újra beolvasva: ```php $loader = new Nette\Loaders\RobotLoader; $loader->addDirectory(__DIR__ . '/app'); + +// A gyorsítótár beállítása a 'temp' könyvtárba $loader->setTempDirectory(__DIR__ . '/temp'); // Könyvtárak keresése a gyorsítótár segítségével @@ -113,26 +118,26 @@ $res = $loader->getIndexedClasses(); ``` -Tárolás .[#toc-caching] +Caching .[#toc-caching] ----------------------- -A RobotLoader nagyon gyors, mert okosan használja a gyorsítótárat. +A RobotLoader nagyon gyors, mert okosan használja a gyorsítótárazást. -A vele való fejlesztés során gyakorlatilag fogalmad sincs arról, hogy a háttérben fut. Folyamatosan frissíti a gyorsítótárat, mert tudja, hogy osztályokat és fájlokat lehet létrehozni, törölni, átnevezni stb. És nem vizsgálja ismételten a nem módosított fájlokat. +A fejlesztés során alig észrevehető, hogy a háttérben fut. Folyamatosan frissíti a gyorsítótárát, figyelembe véve, hogy osztályok és fájlok hozhatók létre, törölhetők, átnevezhetők stb. És nem vizsgálja újra a változatlan fájlokat. -Termelőszervereken való használat esetén viszont javasoljuk, hogy a `$loader->setAutoRefresh(false)` segítségével tiltsuk le a gyorsítótár frissítését (ez automatikusan megtörténik a Nette alkalmazásban), mert a fájlok nem változnak. Ugyanakkor a tárhelyre történő új verzió feltöltésekor **tisztítani kell a gyorsítótárat**. +Egy termelő szerveren viszont ajánlott kikapcsolni a gyorsítótár frissítését a `$loader->setAutoRefresh(false)` segítségével (egy Nette alkalmazásban ez automatikusan megtörténik), mivel a fájlok nem változnak. Ugyanakkor egy új verzió tárhelyre történő feltöltésekor **tisztítani kell a gyorsítótárat**. -Természetesen a fájlok kezdeti beolvasása, ha a gyorsítótár még nem létezik, nagyobb alkalmazásoknál néhány másodpercig is eltarthat. A RobotLoader beépített megelőzéssel rendelkezik a "cache stampede":https://en.wikipedia.org/wiki/Cache_stampede ellen. -Ez az a helyzet, amikor a termelő szerver nagyszámú egyidejű kérést kap, és mivel a RobotLoader gyorsítótár még nem létezik, mindegyik elkezdené a fájlok beolvasását. Ami megnöveli a CPU és a fájlrendszer használatát. -Szerencsére a RobotLoader úgy működik, hogy több egyidejű kérés esetén csak az első szál indexeli a fájlokat, létrehozza a gyorsítótárat, a többiek várnak, majd használják a gyorsítótárat. +A kezdeti fájlszkennelés, amikor a gyorsítótár még nem létezik, nagyobb alkalmazásoknál természetesen eltarthat egy pillanatig. A RobotLoader beépített megelőzéssel rendelkezik a "cache stampede":https://en.wikipedia.org/wiki/Cache_stampede ellen. +Ez az a helyzet, amikor egy termelő szerveren nagyszámú egyidejű kérés indítaná el a RobotLoader-t, és mivel a gyorsítótár még nem létezik, mindegyik elkezdené a fájlok beolvasását, ami túlterhelné a szervert. +Szerencsére a RobotLoader úgy működik, hogy csak az első szál indexeli a fájlokat, létrehozza a gyorsítótárat, a többi pedig vár, majd használja a gyorsítótárat. PSR-4 .[#toc-psr-4] ------------------- -A Composer ma már a PSR-4 szabványnak megfelelően használható [automatikus betöltésre |best-practices:composer#autoloading]. Egyszerűen fogalmazva, ez egy olyan rendszer, ahol a névterek és az osztálynevek megfelelnek a könyvtárszerkezetnek és a fájlneveknek, azaz a `App\Router\RouterFactory` a `/path/to/App/Router/RouterFactory.php` fájlban található. +Manapság a [Composert |best-practices:composer#autoloading] használhatja [automatikus betöltésre |best-practices:composer#autoloading], miközben betartja a PSR-4-et. Egyszerűen fogalmazva, ez egy olyan rendszer, ahol a névterek és az osztályok nevei megfelelnek a könyvtárszerkezetnek és a fájlneveknek, pl. a `App\Router\RouterFactory` a `/path/to/App/Router/RouterFactory.php` fájlban lesz. -A RobotLoader nem kötődik semmilyen rögzített struktúrához, ezért hasznos olyan helyzetekben, amikor nem felel meg a PHP-ban névterekként kialakított könyvtárszerkezet, vagy amikor olyan alkalmazást fejlesztünk, amely történelmileg nem használ ilyen konvenciókat. Az is lehetséges, hogy mindkét betöltőt együtt használjuk. +A RobotLoader nem kötődik semmilyen rögzített struktúrához, így hasznos olyan helyzetekben, amikor nem akarjuk, hogy a könyvtárstruktúra pontosan úgy legyen kialakítva, mint a PHP névterek, vagy amikor olyan alkalmazást fejlesztünk, amely történetileg nem használ ilyen konvenciókat. Az is lehetséges, hogy mindkét betöltőt együtt használjuk. {{leftbar: nette:@menu-topics}} diff --git a/robot-loader/it/@home.texy b/robot-loader/it/@home.texy index f61f8f3d65..e7a445473f 100644 --- a/robot-loader/it/@home.texy +++ b/robot-loader/it/@home.texy @@ -5,65 +5,68 @@ RobotLoader: Caricamento automatico delle classi RobotLoader è uno strumento che consente il caricamento automatico delle classi per l'intera applicazione, comprese le librerie di terze parti. -- sbarazzarsi di tutti `require` -- vengono caricati solo gli script necessari -- non richiede rigide convenzioni di denominazione delle directory o dei file +- Eliminate tutte le dichiarazioni `require` +- Vengono caricati solo gli script necessari +- Non richiede convenzioni di denominazione rigide per le directory o i file +- Estremamente veloce +- Nessun aggiornamento manuale della cache, tutto viene eseguito automaticamente +- Libreria matura, stabile e ampiamente utilizzata
    -Quindi possiamo dimenticare i famosi blocchi di codice: +Possiamo quindi dimenticarci di questi blocchi di codice già noti: ```php require_once 'Utils/Page.php'; require_once 'Utils/Style.php'; require_once 'Utils/Paginator.php'; -// ... +//... ``` Installazione .[#toc-installation] ---------------------------------- -È possibile scaricare RobotLoader come un [singolo file standalone `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], che può essere incluso nel proprio script utilizzando `require`, e disporre immediatamente di un comodo caricamento automatico per l'intera applicazione: +È possibile scaricare RobotLoader come un [singolo file standalone `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], da includere con `require` nel proprio script, e godere immediatamente di un comodo caricamento automatico per l'intera applicazione. ```php require '/path/to/RobotLoader.php'; $loader = new Nette\Loaders\RobotLoader; -// ... +//... ``` -Se state costruendo un'applicazione che utilizza [Composer |best-practices:composer], potete installarlo attraverso di esso: +Se state costruendo un'applicazione usando [Composer |best-practices:composer], potete installarlo tramite: ```shell composer require nette/robot-loader ``` -Uso .[#toc-usage] ------------------ +Utilizzo .[#toc-usage] +---------------------- -Come il robot di Google effettua la scansione e l'indicizzazione dei siti web, [RobotLoader |api:Nette\Loaders\RobotLoader] effettua la scansione di tutti gli script PHP e registra quali classi e interfacce sono state trovate in essi. Questi record vengono poi salvati nella cache e utilizzati durante tutte le richieste successive. È sufficiente specificare quali directory indicizzare e dove salvare la cache: +Analogamente a come il robot di Google effettua il crawling e l'indicizzazione delle pagine web, [RobotLoader |api:Nette\Loaders\RobotLoader] esamina tutti gli script PHP e annota le classi, le interfacce, i tratti e gli enum che ha trovato. Quindi memorizza i risultati nella cache per utilizzarli nelle richieste successive. È sufficiente specificare quali directory deve attraversare e dove memorizzare la cache: ```php $loader = new Nette\Loaders\RobotLoader; -// le directory da indicizzare da RobotLoader (incluse le sottodirectory) +// Directory da indicizzare per RobotLoader (incluse le sottodirectory) $loader->addDirectory(__DIR__ . '/app'); $loader->addDirectory(__DIR__ . '/libs'); -// utilizzare la cartella 'temp' per la cache +// Impostare la cache sulla directory "temp". $loader->setTempDirectory(__DIR__ . '/temp'); -$loader->register(); // Eseguire il RobotLoader +$loader->register(); // Attivare RobotLoader ``` -E questo è tutto. D'ora in poi, non sarà più necessario usare `require`. Fantastico, non è vero? +E questo è tutto, da questo momento in poi non abbiamo più bisogno di usare `require`. Fantastico! -Quando RobotLoader incontra un nome di classe duplicato durante l'indicizzazione, lancia un'eccezione e informa l'utente. RobotLoader aggiorna automaticamente la cache quando deve caricare una classe che non conosce. Si consiglia di disabilitare questa funzione sui server di produzione, vedere [Cache |#Caching]. +Se RobotLoader incontra un nome di classe duplicato durante l'indicizzazione, lancerà un'eccezione e ne darà notifica. RobotLoader aggiorna automaticamente la cache quando deve caricare una classe sconosciuta. Si consiglia di disattivare questa funzione sui server di produzione, vedere [Cache |#Caching]. -Se si desidera che RobotLoader salti alcune directory, utilizzare `$loader->excludeDirectory('temp')` (può essere chiamato più volte o si possono passare più directory). +Se si desidera che RobotLoader salti alcune directory, utilizzare `$loader->excludeDirectory('temp')` (può essere chiamato più volte o passare più directory). -Per impostazione predefinita, RobotLoader segnala gli errori nei file PHP lanciando l'eccezione `ParseError`. Può essere disabilitato tramite `$loader->reportParseErrors(false)`. +Per impostazione predefinita, RobotLoader segnala gli errori nei file PHP lanciando un'eccezione `ParseError`. Questa può essere soppressa usando `$loader->reportParseErrors(false)`. Applicazione Nette .[#toc-nette-application] @@ -73,7 +76,7 @@ All'interno dell'applicazione Nette, dove `$configurator` è utilizzato in `Boot ```php $configurator = new Nette\Bootstrap\Configurator; -// ... +//... $configurator->setTempDirectory(__DIR__ . '/../temp'); $configurator->createRobotLoader() ->addDirectory(__DIR__) @@ -85,27 +88,29 @@ $configurator->createRobotLoader() Analizzatore di file PHP .[#toc-php-files-analyzer] --------------------------------------------------- -RobotLoader può essere usato anche solo per trovare classi, interfacce e tratti nei file PHP **senza** usare la funzione di caricamento automatico: +RobotLoader può essere usato anche solo per trovare classi, interfacce, tratti ed enum nei file PHP **senza** usare la funzione di caricamento automatico: ```php $loader = new Nette\Loaders\RobotLoader; $loader->addDirectory(__DIR__ . '/app'); -// Esegue la scansione delle directory per classi, interfacce e tratti. +// Esegue la scansione delle directory per classi/interfacce/tratti/enum $loader->rebuild(); // Restituisce un array di coppie classe => nome file $res = $loader->getIndexedClasses(); ``` -Anche in questo caso, è possibile utilizzare la cache. Di conseguenza, i file non modificati non verranno analizzati ripetutamente durante la ricognizione: +Anche con questo tipo di utilizzo, è possibile utilizzare la cache. In questo modo si garantisce che i file invariati non vengano ricanalizzati: ```php $loader = new Nette\Loaders\RobotLoader; $loader->addDirectory(__DIR__ . '/app'); + +// Imposta la cache sulla directory 'temp' $loader->setTempDirectory(__DIR__ . '/temp'); -// Esegue la scansione delle directory utilizzando una cache +// Esegue la scansione delle directory utilizzando la cache $loader->refresh(); // Restituisce un array di coppie classe => nome file @@ -118,21 +123,21 @@ Caching .[#toc-caching] RobotLoader è molto veloce perché utilizza in modo intelligente la cache. -Quando si sviluppa con esso, non si ha praticamente idea che venga eseguito in background. Aggiorna continuamente la cache perché sa che le classi e i file possono essere creati, cancellati, rinominati, ecc. E non esegue ripetutamente la scansione di file non modificati. +Durante lo sviluppo, quasi non ci si accorge che è in esecuzione in background. Aggiorna continuamente la sua cache, considerando che le classi e i file possono essere creati, cancellati, rinominati, ecc. E non esegue una nuova scansione dei file invariati. -Se si utilizza su un server di produzione, invece, si consiglia di disabilitare l'aggiornamento della cache tramite `$loader->setAutoRefresh(false)` (ciò avviene automaticamente nell'applicazione Nette), perché i file non vengono modificati. Allo stesso tempo, è necessario **pulire la cache** quando si carica una nuova versione sull'hosting. +Su un server di produzione, invece, si consiglia di disattivare gli aggiornamenti della cache utilizzando `$loader->setAutoRefresh(false)` (in un'applicazione Nette, questo avviene automaticamente), perché i file non cambiano. Allo stesso tempo, è necessario **pulire la cache** quando si carica una nuova versione sull'hosting. -Naturalmente, la scansione iniziale dei file, quando la cache non esiste già, può richiedere alcuni secondi per le applicazioni più grandi. RobotLoader ha una prevenzione integrata contro la "fuga dalla cache":https://en.wikipedia.org/wiki/Cache_stampede. -Si tratta di una situazione in cui il server di produzione riceve un gran numero di richieste simultanee e, poiché la cache di RobotLoader non esiste ancora, tutte iniziano a scansionare i file. Il che fa impennare l'utilizzo della CPU e del filesystem. -Fortunatamente, RobotLoader funziona in modo tale che, in caso di più richieste contemporanee, solo il primo thread indicizza i file, crea una cache, gli altri aspettano e poi utilizzano la cache. +La scansione iniziale dei file, quando la cache non esiste ancora, può naturalmente richiedere un certo tempo per le applicazioni più grandi. RobotLoader ha una prevenzione integrata contro la "fuga dalla cache":https://en.wikipedia.org/wiki/Cache_stampede. +Si tratta di una situazione in cui un gran numero di richieste simultanee su un server di produzione attiverebbe RobotLoader e, poiché la cache non esiste ancora, tutti inizierebbero a scansionare i file, sovraccaricando il server. +Fortunatamente, RobotLoader funziona in modo tale che solo il primo thread indicizza i file, crea la cache e gli altri attendono e poi utilizzano la cache. PSR-4 .[#toc-psr-4] ------------------- -Oggi Composer può essere utilizzato per l'[autocaricamento |best-practices:composer#autoloading] in conformità al PSR-4. In parole povere, si tratta di un sistema in cui gli spazi dei nomi e i nomi delle classi corrispondono alla struttura delle directory e ai nomi dei file, ad esempio `App\Router\RouterFactory` si trova nel file `/path/to/App/Router/RouterFactory.php`. +Al giorno d'oggi, è possibile utilizzare [Composer per l'autocaricamento |best-practices:composer#autoloading], pur rispettando il sistema PSR-4. In parole povere, si tratta di un sistema in cui gli spazi dei nomi e i nomi delle classi corrispondono alla struttura delle directory e ai nomi dei file, ad esempio `App\Router\RouterFactory` sarà nel file `/path/to/App/Router/RouterFactory.php`. -RobotLoader non è legato a nessuna struttura fissa, quindi è utile in situazioni in cui non è opportuno avere la struttura delle directory progettata come spazi dei nomi in PHP, oppure quando si sta sviluppando un'applicazione che storicamente non ha usato tali convenzioni. È anche possibile utilizzare entrambi i caricatori insieme. +RobotLoader non è legato a nessuna struttura fissa, quindi è utile in situazioni in cui non si vuole avere la struttura delle cartelle esattamente come gli spazi dei nomi di PHP, o quando si sviluppa un'applicazione che storicamente non usa tali convenzioni. È anche possibile utilizzare entrambi i caricatori insieme. {{leftbar: nette:@menu-topics}} diff --git a/robot-loader/pl/@home.texy b/robot-loader/pl/@home.texy index d95d91ac81..46a73a98ae 100644 --- a/robot-loader/pl/@home.texy +++ b/robot-loader/pl/@home.texy @@ -1,79 +1,82 @@ -RobotLoader: autoloadowanie klas -******************************** +RobotLoader: Automatyczne ładowanie klas +****************************************
    -RobotLoader to narzędzie, które daje wygodę automatycznego ładowania klas dla całej aplikacji, w tym bibliotek firm trzecich. +RobotLoader to narzędzie, które zapewnia komfort automatycznego ładowania klas dla całej aplikacji, w tym bibliotek innych firm. -- Pozbywamy się wszystkich `require` -- zostaną załadowane tylko niezbędne skrypty -- nie wymaga ścisłych konwencji nazewnictwa dla katalogów i plików +- Wyeliminuj wszystkie instrukcje `require` +- Załadowane zostaną tylko niezbędne skrypty +- Nie wymaga ścisłych konwencji nazewnictwa katalogów lub plików +- Niezwykle szybki +- Brak ręcznych aktualizacji pamięci podręcznej, wszystko działa automatycznie +- Dojrzała, stabilna i szeroko stosowana biblioteka
    -Możemy więc zapomnieć o tych znanych nam blokach kodu: +Możemy więc zapomnieć o tych znanych blokach kodu: ```php require_once 'Utils/Page.php'; require_once 'Utils/Style.php'; require_once 'Utils/Paginator.php'; -// ... +//... ``` Instalacja .[#toc-installation] ------------------------------- -RobotLoader można pobrać jako [pojedynczy, samodzielny plik `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], który można dołączyć do skryptu za pomocą `require` i natychmiast uzyskać wygodny autoloading dla całej aplikacji: +RobotLoader można pobrać jako [pojedynczy samodzielny plik `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], który można dołączyć za pomocą `require` do skryptu i natychmiast cieszyć się wygodnym automatycznym ładowaniem całej aplikacji. ```php require '/path/to/RobotLoader.php'; $loader = new Nette\Loaders\RobotLoader; -// ... +//... ``` -Jeśli tworzysz aplikację korzystającą z [Composera |best-practices:composer], możesz ją zainstalować za jego pośrednictwem: +Jeśli budujesz aplikację przy użyciu [Composera |best-practices:composer], możesz zainstalować go za pośrednictwem: ```shell composer require nette/robot-loader ``` -Korzystanie z .[#toc-usage] ---------------------------- +Użycie .[#toc-usage] +-------------------- -Podobnie jak robot Google indeksuje strony internetowe, [RobotLoader |api:Nette\Loaders\RobotLoader] przeszukuje wszystkie skrypty PHP i notuje, jakie klasy, interfejsy i cechy w nich znalazł. Następnie buforuje wyniki swojej eksploracji i używa ich w następnym żądaniu. Wystarczy więc określić, które katalogi mają być indeksowane i gdzie mają być buforowane: +Podobnie jak robot Google przeszukuje i indeksuje strony internetowe, [RobotLoader |api:Nette\Loaders\RobotLoader] przechodzi przez wszystkie skrypty PHP i odnotowuje znalezione klasy, interfejsy, cechy i wyliczenia. Następnie przechowuje wyniki w pamięci podręcznej do wykorzystania w kolejnych żądaniach. Wystarczy określić, przez które katalogi ma przechodzić i gdzie przechowywać pamięć podręczną: ```php $loader = new Nette\Loaders\RobotLoader; -// katalogi, które mają być indeksowane przez RobotLoader (łącznie z podkatalogami) +// Katalogi do indeksowania przez RobotLoader (w tym podkatalogi) $loader->addDirectory(__DIR__ . '/app'); $loader->addDirectory(__DIR__ . '/libs'); -// ustaw buforowanie w katalogu 'temp' +// Ustaw buforowanie na katalog "temp $loader->setTempDirectory(__DIR__ . '/temp'); -$loader->register(); // uruchom RobotLoader +$loader->register(); // Aktywuj RobotLoader ``` -To wszystko, od tej pory nie musimy używać `require`. Świetnie! +I to wszystko, od tego momentu nie musimy używać `require`. Super! -Jeśli RobotLoader napotka zduplikowaną nazwę klasy podczas indeksowania, rzuca wyjątek i informuje o tym. RobotLoader również automatycznie aktualizuje pamięć podręczną, gdy musi załadować klasę, której nie zna. Zalecamy wyłączenie tego na serwerach produkcyjnych, zobacz [Caching |#Caching]. +Jeśli RobotLoader napotka zduplikowaną nazwę klasy podczas indeksowania, zgłosi wyjątek i powiadomi o tym użytkownika. RobotLoader automatycznie aktualizuje również pamięć podręczną, gdy musi załadować nieznaną klasę. Zalecamy wyłączenie tej opcji na serwerach produkcyjnych, patrz [Buforowanie |#Caching]. -Jeśli chcesz, aby RobotLoader pominął niektóre katalogi, użyj `$loader->excludeDirectory('temp')` (możesz wykonać wiele połączeń lub przekazać wiele katalogów). +Jeśli chcesz, aby RobotLoader pomijał określone katalogi, użyj `$loader->excludeDirectory('temp')` (można wywołać wiele razy lub przekazać wiele katalogów). -Domyślnie RobotLoader zgłasza błędy w plikach PHP rzucając wyjątek `ParseError`. Można to nadpisać za pomocą `$loader->reportParseErrors(false)`. +Domyślnie RobotLoader zgłasza błędy w plikach PHP, rzucając wyjątek `ParseError`. Można to wyłączyć za pomocą `$loader->reportParseErrors(false)`. -Aplikacje Nette .[#toc-nette-application] +Aplikacja Nette .[#toc-nette-application] ----------------------------------------- -Wewnątrz aplikacji Nette, gdzie w pliku startowym używany jest obiekt `Bootstrap.php` `$configurator` , notacja może być uproszczona: +Wewnątrz aplikacji Nette, gdzie `$configurator` jest używany w `Bootstrap.php`, można skonfigurować RobotLoader w ten sposób: ```php $configurator = new Nette\Bootstrap\Configurator; -// ... +//... $configurator->setTempDirectory(__DIR__ . '/../temp'); $configurator->createRobotLoader() ->addDirectory(__DIR__) @@ -85,54 +88,56 @@ $configurator->createRobotLoader() Analizator plików PHP .[#toc-php-files-analyzer] ------------------------------------------------ -RobotLoader może być również użyty do wyszukiwania klas, interfejsów i cech w plikach PHP **bez** użycia funkcji autoloadingu: +RobotLoader może być również używany wyłącznie do wyszukiwania klas, interfejsów, cech i wyliczeń w plikach PHP **bez** korzystania z funkcji automatycznego ładowania: ```php $loader = new Nette\Loaders\RobotLoader; $loader->addDirectory(__DIR__ . '/app'); -// skanuje katalogi w poszukiwaniu klas/interfejsów/traitów +// Skanuje katalogi w poszukiwaniu klas/interfejsów/traits/enums $loader->rebuild(); -// zwraca tablicę par class => filename +// Zwraca tablicę par klasa => nazwa pliku $res = $loader->getIndexedClasses(); ``` -W ten sposób można również wykorzystać cache. Dzięki temu niezmienione pliki nie będą ponownie analizowane przy ponownym skanowaniu: +Nawet przy takim użyciu można wykorzystać buforowanie. Gwarantuje to, że niezmienione pliki nie będą ponownie skanowane: ```php $loader = new Nette\Loaders\RobotLoader; $loader->addDirectory(__DIR__ . '/app'); + +// Ustawia buforowanie na katalog "temp $loader->setTempDirectory(__DIR__ . '/temp'); -// skanuje katalogi używając pamięci podręcznej +// Skanuje katalogi przy użyciu pamięci podręcznej $loader->refresh(); -// zwraca tablicę par class => filename +// Zwraca tablicę par klasa => nazwa pliku $res = $loader->getIndexedClasses(); ``` -Caching .[#toc-caching] ------------------------ +Buforowanie .[#toc-caching] +--------------------------- RobotLoader jest bardzo szybki, ponieważ sprytnie wykorzystuje buforowanie. -Rozwijając się z nim, jesteś praktycznie nieświadomy, że działa on w tle. Stale aktualizuje swoją pamięć podręczną, ponieważ bierze pod uwagę, że klasy i pliki mogą być tworzone, znikać, zmieniać nazwy itp. I nie skanuje wielokrotnie plików, które nie uległy zmianie. +Podczas programowania prawie nie widać, że działa w tle. Stale aktualizuje swoją pamięć podręczną, biorąc pod uwagę, że klasy i pliki mogą być tworzone, usuwane, zmieniane nazwy itp. I nie skanuje ponownie niezmienionych plików. -Z drugiej strony, podczas wdrażania na serwerze produkcyjnym, zalecamy wyłączenie aktualizacji pamięci podręcznej za pomocą `$loader->setAutoRefresh(false)` (robi to automatycznie w aplikacji Nette), ponieważ pliki nie ulegają zmianie. Jednocześnie po wgraniu nowej wersji na hosting konieczne jest **wyczyszczenie cache**. +Z drugiej strony na serwerze produkcyjnym zalecamy wyłączenie aktualizacji pamięci podręcznej za pomocą `$loader->setAutoRefresh(false)` (w aplikacji Nette dzieje się to automatycznie), ponieważ pliki się nie zmieniają. Jednocześnie konieczne jest **wyczyszczenie pamięci podręcznej** podczas przesyłania nowej wersji na hosting. -Początkowe skanowanie plików, gdy pamięć podręczna jeszcze nie istnieje, może zająć chwilę w przypadku większych aplikacji. RobotLoader ma wbudowane zapobieganie przed "cache stampede":https://en.wikipedia.org/wiki/Cache_stampede. -Jest to sytuacja, w której duża liczba współbieżnych żądań spotyka się na serwerze produkcyjnym i uruchamia RobotLoader, a ponieważ pamięć podręczna jeszcze nie istnieje, wszystkie zaczęłyby skanować pliki. Co spowodowałoby nieproporcjonalne obciążenie serwera. -Na szczęście sposób działania RobotLoader polega na tym, że gdy istnieje wiele współbieżnych żądań, tylko pierwszy wątek indeksuje pliki, tworzy pamięć podręczną, pozostałe czekają, a następnie używają pamięci podręcznej. +Początkowe skanowanie plików, gdy pamięć podręczna jeszcze nie istnieje, może oczywiście zająć chwilę w przypadku większych aplikacji. RobotLoader ma wbudowaną ochronę przed "cache stampede":https://en.wikipedia.org/wiki/Cache_stampede. +Jest to sytuacja, w której duża liczba jednoczesnych żądań na serwerze produkcyjnym uruchomiłaby RobotLoader, a ponieważ pamięć podręczna jeszcze nie istnieje, wszystkie zaczęłyby skanować pliki, co przeciążyłoby serwer. +Na szczęście RobotLoader działa w taki sposób, że tylko pierwszy wątek indeksuje pliki, tworzy pamięć podręczną, a reszta czeka, a następnie korzysta z pamięci podręcznej. PSR-4 .[#toc-psr-4] ------------------- -Dziś [Composer |best-practices:composer#Autoloading] może być [używany |best-practices:composer#Autoloading] do [autoloadingu |best-practices:composer#Autoloading], jeśli przestrzega się PSR-4. Najprościej mówiąc, jest to system, w którym przestrzenie nazw i nazwy klas odpowiadają strukturom katalogów i nazwom plików, więc na przykład `App\Router\RouterFactory` będzie w pliku `/path/to/App/Router/RouterFactory.php`. +Obecnie można używać [Composera do automatycznego ładowania |best-practices:composer#autoloading] przy jednoczesnym przestrzeganiu PSR-4. Mówiąc najprościej, jest to system, w którym przestrzenie nazw i nazwy klas odpowiadają strukturze katalogów i nazwom plików, np. `App\Router\RouterFactory` będzie w pliku `/path/to/App/Router/RouterFactory.php`. -RobotLoader nie jest przywiązany do żadnej stałej struktury, więc jest przydatny w sytuacjach, gdy nie czujesz się komfortowo z posiadaniem struktury katalogów zaprojektowanej w taki sam sposób jak przestrzenie nazw PHP, lub gdy rozwijasz aplikację, która historycznie nie używała takich konwencji. Możliwe jest również stosowanie obu ładowarek razem. +RobotLoader nie jest powiązany z żadną stałą strukturą, więc jest przydatny w sytuacjach, w których nie chcesz, aby struktura katalogów była zaprojektowana dokładnie tak, jak przestrzenie nazw PHP, lub podczas tworzenia aplikacji, która historycznie nie używa takich konwencji. Możliwe jest również użycie obu programów ładujących razem. {{leftbar: nette:@menu-topics}} diff --git a/robot-loader/pt/@home.texy b/robot-loader/pt/@home.texy index 7ce9c57336..29072ad47b 100644 --- a/robot-loader/pt/@home.texy +++ b/robot-loader/pt/@home.texy @@ -3,77 +3,80 @@ RobotLoader: Carregamento automático de classe
    -RobotLoader é uma ferramenta que lhe dá conforto de carregamento automatizado de classe para toda a sua aplicação, incluindo bibliotecas de terceiros. +O RobotLoader é uma ferramenta que proporciona a você o conforto do carregamento automático de classes para todo o seu aplicativo, incluindo bibliotecas de terceiros. -- se livrar de todos `require` -- somente os scripts necessários são carregados -- não requer convenções rigorosas de diretório ou de nomes de arquivos +- Elimine todas as declarações `require` +- Somente os scripts necessários serão carregados +- Não requer convenções de nomenclatura rígidas para diretórios ou arquivos +- Extremamente rápido +- Sem atualizações manuais do cache, tudo é executado automaticamente +- Biblioteca madura, estável e amplamente utilizada
    -Assim, podemos esquecer esses famosos blocos de código: +Portanto, podemos esquecer esses blocos de código conhecidos: ```php require_once 'Utils/Page.php'; require_once 'Utils/Style.php'; require_once 'Utils/Paginator.php'; -// ... +//... ``` Instalação .[#toc-installation] ------------------------------- -Você pode fazer o download do RobotLoader como um [único arquivo autônomo `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], que pode ser incluído no seu script usando `require`, e ter imediatamente um carregamento automático conveniente para todo o seu aplicativo: +Você pode fazer o download do RobotLoader como um [único arquivo autônomo `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], que você inclui usando `require` no seu script, e imediatamente aproveita o carregamento automático confortável para todo o aplicativo. ```php require '/path/to/RobotLoader.php'; $loader = new Nette\Loaders\RobotLoader; -// ... +//... ``` -Se estiver criando um aplicativo que usa [o Composer |best-practices:composer], poderá instalá-lo por meio dele: +Se estiver criando um aplicativo usando o [Composer |best-practices:composer], poderá instalá-lo via: ```shell composer require nette/robot-loader ``` -Utilização .[#toc-usage] ------------------------- +Uso .[#toc-usage] +----------------- -Como o robô Google rastreia e indexa websites, o [RobotLoader |api:Nette\Loaders\RobotLoader] rastreia todos os scripts PHP e registra quais classes e interfaces foram encontradas neles. Estes registros são então salvos em cache e utilizados durante todas as solicitações subseqüentes. Basta especificar quais diretórios indexar e onde salvar o cache: +Semelhante à forma como o robô do Google rastreia e indexa as páginas da Web, o [RobotLoader |api:Nette\Loaders\RobotLoader] percorre todos os scripts PHP e anota quais classes, interfaces, características e enums encontrou. Em seguida, ele armazena os resultados no cache para uso em solicitações subsequentes. Você só precisa especificar quais diretórios ele deve percorrer e onde armazenar o cache: ```php $loader = new Nette\Loaders\RobotLoader; -// diretórios a serem indexados pelo RobotLoader (incluindo subdiretórios) +// Diretórios para o RobotLoader indexar (incluindo subdiretórios) $loader->addDirectory(__DIR__ . '/app'); $loader->addDirectory(__DIR__ . '/libs'); -// usar diretório 'temp' para cache +// Defina o armazenamento em cache para o diretório "temp". $loader->setTempDirectory(__DIR__ . '/temp'); -$loader->register(); // Executar o RobotLoader +$loader->register(); // Ativar o RobotLoader ``` -E isso é tudo. De agora em diante, você não precisa usar `require`. Ótimo, não é? +E pronto, a partir de agora, não precisamos mais usar o `require`. Fantástico! -Quando o RobotLoader encontra um nome de classe duplicado durante a indexação, ele lança uma exceção e o informa sobre isso. O RobotLoader também atualiza automaticamente o cache quando ele tem que carregar uma classe que não conhece. Recomendamos desativar isto nos servidores de produção, veja [Caching |#Caching]. +Se o RobotLoader encontrar um nome de classe duplicado durante a indexação, ele lançará uma exceção e o notificará. O RobotLoader também atualiza automaticamente o cache quando precisa carregar uma classe desconhecida. Recomendamos desativar isso nos servidores de produção, consulte [Cache |#Caching]. -Se você quiser que RobotLoader salte alguns diretórios, use `$loader->excludeDirectory('temp')` (pode ser chamado várias vezes ou você pode passar por vários diretórios). +Se você quiser que o RobotLoader ignore determinados diretórios, use `$loader->excludeDirectory('temp')` (pode ser chamado várias vezes ou passar vários diretórios). -Por padrão, o RobotLoader reporta erros em arquivos PHP lançando a exceção `ParseError`. Ele pode ser desativado via `$loader->reportParseErrors(false)`. +Por padrão, o RobotLoader relata erros nos arquivos PHP lançando uma exceção `ParseError`. Isso pode ser suprimido usando `$loader->reportParseErrors(false)`. -Aplicação Nette .[#toc-nette-application] ------------------------------------------ +Aplicativo Nette .[#toc-nette-application] +------------------------------------------ -Dentro da aplicação Nette, onde `$configurator` é usado em `Bootstrap.php`, você pode configurar o RobotLoader desta forma: +Dentro do aplicativo Nette, onde `$configurator` é usado em `Bootstrap.php`, você pode configurar o RobotLoader dessa forma: ```php $configurator = new Nette\Bootstrap\Configurator; -// ... +//... $configurator->setTempDirectory(__DIR__ . '/../temp'); $configurator->createRobotLoader() ->addDirectory(__DIR__) @@ -85,54 +88,56 @@ $configurator->createRobotLoader() Analisador de arquivos PHP .[#toc-php-files-analyzer] ----------------------------------------------------- -RobotLoader também pode ser usado puramente para encontrar classes, interfaces e traços em arquivos PHP **sem*** usando o recurso de auto-carregamento: +O RobotLoader também pode ser usado exclusivamente para localizar classes, interfaces, características e enums em arquivos PHP **sem** usar a função de carregamento automático: ```php $loader = new Nette\Loaders\RobotLoader; $loader->addDirectory(__DIR__ . '/app'); -// Escaneia diretórios de classes / interfaces / traços +// Procura nos diretórios por classes/interfaces/traits/enums $loader->rebuild(); -// Retorna matriz de classe => pares de nomes de arquivo +// Retorna uma matriz de pares classe => nome do arquivo $res = $loader->getIndexedClasses(); ``` -Mesmo com tal uso, você pode usar o cache. Como resultado, os arquivos não modificados não serão analisados repetidamente durante a nova digitalização: +Mesmo com esse uso, você pode utilizar o cache. Isso garante que os arquivos inalterados não sejam verificados novamente: ```php $loader = new Nette\Loaders\RobotLoader; $loader->addDirectory(__DIR__ . '/app'); + +// Definir o cache para o diretório "temp". $loader->setTempDirectory(__DIR__ . '/temp'); -// Escaneia diretórios usando um cache +// Examina os diretórios usando o cache $loader->refresh(); -// Retorna matriz de classe => pares de nomes de arquivo +// Retorna uma matriz de pares classe => nome do arquivo $res = $loader->getIndexedClasses(); ``` -Caching .[#toc-caching] ------------------------ +Armazenamento em cache .[#toc-caching] +-------------------------------------- O RobotLoader é muito rápido porque usa o cache de forma inteligente. -Ao se desenvolver com ele, você não tem praticamente nenhuma idéia de que ele corre sobre o fundo. Ele atualiza continuamente o cache porque sabe que classes e arquivos podem ser criados, apagados, renomeados, etc. E ele não escaneia repetidamente arquivos não modificados. +Durante o desenvolvimento, você mal percebe que ele está sendo executado em segundo plano. Ele atualiza continuamente o cache, considerando que as classes e os arquivos podem ser criados, excluídos, renomeados, etc. E ele não verifica novamente os arquivos não alterados. -Quando usado em um servidor de produção, por outro lado, recomendamos desativar a atualização do cache usando `$loader->setAutoRefresh(false)` (isto é feito automaticamente na Aplicação Nette), porque os arquivos não estão mudando. Ao mesmo tempo, é necessário **clarar o cache** ao fazer o upload de uma nova versão na hospedagem. +Em um servidor de produção, por outro lado, recomendamos desativar as atualizações de cache usando `$loader->setAutoRefresh(false)` (em um aplicativo Nette, isso acontece automaticamente), porque os arquivos não são alterados. Ao mesmo tempo, é necessário **limpar o cache** ao fazer o upload de uma nova versão para a hospedagem. -Naturalmente, a digitalização inicial dos arquivos, quando o cache ainda não existe, pode levar alguns segundos para aplicações maiores. O RobotLoader tem prevenção embutida contra a "debandada do cache:https://en.wikipedia.org/wiki/Cache_stampede". -Esta é uma situação em que o servidor de produção recebe um grande número de solicitações simultâneas e como o cache do RobotLoader ainda não existe, todos eles começariam a escanear os arquivos. O que aumenta o uso da CPU e do sistema de arquivos. -Felizmente, o RobotLoader trabalha de tal forma que para múltiplas solicitações simultâneas, apenas o primeiro thread indexa os arquivos, cria um cache, os outros esperam, e então usam o cache. +A verificação inicial do arquivo, quando o cache ainda não existe, pode naturalmente demorar um pouco para aplicativos maiores. O RobotLoader tem uma prevenção integrada contra a "debandada do cache":https://en.wikipedia.org/wiki/Cache_stampede. +Essa é uma situação em que um grande número de solicitações simultâneas em um servidor de produção acionaria o RobotLoader e, como o cache ainda não existe, todos eles começariam a verificar os arquivos, o que sobrecarregaria o servidor. +Felizmente, o RobotLoader funciona de tal forma que somente o primeiro thread indexa os arquivos, cria o cache, e os demais esperam e usam o cache. PSR-4 .[#toc-psr-4] ------------------- -Hoje, o Composer pode ser usado para [autocarga |best-practices:composer#autoloading] em conformidade com o PSR-4. Dito simplesmente, é um sistema onde os namespaces e nomes de classes correspondem à estrutura do diretório e nomes de arquivos, ou seja, `App\Router\RouterFactory` está localizado no arquivo `/path/to/App/Router/RouterFactory.php`. +Atualmente, você pode usar o [Composer para carregamento automático |best-practices:composer#autoloading] enquanto adere ao PSR-4. Simplificando, é um sistema em que os namespaces e os nomes das classes correspondem à estrutura de diretórios e aos nomes de arquivos, por exemplo, `App\Router\RouterFactory` estará no arquivo `/path/to/App/Router/RouterFactory.php`. -O RobotLoader não está ligado a nenhuma estrutura fixa, portanto, é útil em situações em que não lhe convém ter a estrutura de diretório projetada como namespaces em PHP, ou quando você está desenvolvendo uma aplicação que historicamente não utilizou tais convenções. Também é possível utilizar os dois carregadores em conjunto. +O RobotLoader não está vinculado a nenhuma estrutura fixa, portanto, é útil em situações em que você não deseja que a estrutura de diretórios seja projetada exatamente como os namespaces do PHP ou ao desenvolver um aplicativo que historicamente não usa essas convenções. Também é possível usar os dois carregadores juntos. {{leftbar: nette:@menu-topics}} diff --git a/robot-loader/ro/@home.texy b/robot-loader/ro/@home.texy index 882200243f..e08d982462 100644 --- a/robot-loader/ro/@home.texy +++ b/robot-loader/ro/@home.texy @@ -5,35 +5,38 @@ RobotLoader: Încărcarea automată a clasei RobotLoader este un instrument care vă oferă confortul încărcării automate a claselor pentru întreaga dumneavoastră aplicație, inclusiv pentru bibliotecile de la terți. -- scăpați de toate `require` -- sunt încărcate doar scripturile necesare -- nu necesită convenții stricte de denumire a directoarelor sau a fișierelor +- Eliminați toate declarațiile `require` +- Doar scripturile necesare vor fi încărcate +- Nu necesită convenții de denumire stricte pentru directoare sau fișiere +- Extrem de rapid +- Fără actualizări manuale ale cache-ului, totul se execută automat +- Bibliotecă matură, stabilă și utilizată pe scară largă
    -Așadar, putem să uităm de acele celebre blocuri de cod: +Astfel, putem uita de aceste blocuri de cod familiare: ```php require_once 'Utils/Page.php'; require_once 'Utils/Style.php'; require_once 'Utils/Paginator.php'; -// ... +//... ``` Instalare .[#toc-installation] ------------------------------ -Puteți descărca RobotLoader ca un [singur fișier independent `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], pe care îl puteți include în scriptul dvs. folosind `require`, și puteți avea imediat o încărcare automată convenabilă pentru întreaga aplicație: +Puteți descărca RobotLoader ca un [singur fișier independent `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], pe care îl includeți folosind `require` în scriptul dumneavoastră și vă bucurați instantaneu de o încărcare automată confortabilă pentru întreaga aplicație. ```php require '/path/to/RobotLoader.php'; $loader = new Nette\Loaders\RobotLoader; -// ... +//... ``` -Dacă construiți o aplicație care utilizează [Composer |best-practices:composer], îl puteți instala prin intermediul acestuia: +Dacă construiți o aplicație utilizând [Composer |best-practices:composer], îl puteți instala prin intermediul: ```shell composer require nette/robot-loader @@ -43,27 +46,27 @@ composer require nette/robot-loader Utilizare .[#toc-usage] ----------------------- -La fel cum robotul Google răscolește și indexează site-urile web, [RobotLoader |api:Nette\Loaders\RobotLoader] răscolește toate scripturile PHP și înregistrează ce clase și interfețe au fost găsite în ele. Aceste înregistrări sunt apoi salvate în memoria cache și utilizate în timpul tuturor cererilor ulterioare. Trebuie doar să specificați ce directoare să indexați și unde să salvați memoria cache: +Similar cu modul în care robotul Google răscolește și indexează paginile web, [RobotLoader |api:Nette\Loaders\RobotLoader] parcurge toate scripturile PHP și notează ce clase, interfețe, trăsături și enumerații a găsit. Apoi stochează rezultatele în memoria cache pentru a le utiliza în cererile ulterioare. Trebuie doar să specificați prin ce directoare trebuie să treacă și unde să stocheze memoria cache: ```php $loader = new Nette\Loaders\RobotLoader; -// directoare care urmează să fie indexate de RobotLoader (inclusiv subdirectoarele) +// Directoare pe care RobotLoader trebuie să le indexeze (inclusiv subdirectoare) $loader->addDirectory(__DIR__ . '/app'); $loader->addDirectory(__DIR__ . '/libs'); -// utilizați directorul "temp" pentru memoria cache +// Setați memoria cache în directorul "temp". $loader->setTempDirectory(__DIR__ . '/temp'); -$loader->register(); // Rulați RobotLoader +$loader->register(); // Activați RobotLoader ``` -Și asta e tot. De acum încolo, nu mai este nevoie să utilizați `require`. Minunat, nu-i așa? +Și gata, din acest moment nu mai este nevoie să folosim `require`. Minunat! -Atunci când RobotLoader întâlnește un nume de clasă duplicat în timpul indexării, acesta aruncă o excepție și vă informează despre aceasta. De asemenea, RobotLoader actualizează automat memoria cache atunci când trebuie să încarce o clasă pe care nu o cunoaște. Vă recomandăm să dezactivați acest lucru pe serverele de producție, consultați [Caching |#Caching]. +Dacă RobotLoader întâlnește un nume de clasă duplicat în timpul indexării, va arunca o excepție și vă va notifica. De asemenea, RobotLoader actualizează automat memoria cache atunci când trebuie să încarce o clasă necunoscută. Vă recomandăm să dezactivați acest lucru pe serverele de producție, consultați [Caching |#Caching]. -Dacă doriți ca RobotLoader să sară peste unele directoare, utilizați `$loader->excludeDirectory('temp')` (poate fi apelat de mai multe ori sau puteți trece mai multe directoare). +Dacă doriți ca RobotLoader să sară peste anumite directoare, utilizați `$loader->excludeDirectory('temp')` (poate fi apelat de mai multe ori sau poate trece mai multe directoare). -În mod implicit, RobotLoader raportează erorile din fișierele PHP prin aruncarea excepției `ParseError`. Aceasta poate fi dezactivată prin intermediul `$loader->reportParseErrors(false)`. +În mod implicit, RobotLoader raportează erorile din fișierele PHP prin aruncarea unei excepții `ParseError`. Acest lucru poate fi suprimat folosind `$loader->reportParseErrors(false)`. Aplicația Nette .[#toc-nette-application] @@ -73,7 +76,7 @@ Aplicația Nette .[#toc-nette-application] ```php $configurator = new Nette\Bootstrap\Configurator; -// ... +//... $configurator->setTempDirectory(__DIR__ . '/../temp'); $configurator->createRobotLoader() ->addDirectory(__DIR__) @@ -85,27 +88,29 @@ $configurator->createRobotLoader() Analizator de fișiere PHP .[#toc-php-files-analyzer] ---------------------------------------------------- -RobotLoader poate fi, de asemenea, utilizat pur și simplu pentru a găsi clase, interfețe și trăsături în fișierele PHP **fără** a utiliza funcția de încărcare automată: +RobotLoader poate fi, de asemenea, utilizat pur și simplu pentru a găsi clase, interfețe, trăsături și enumerații în fișierele PHP **fără** a utiliza funcția de încărcare automată: ```php $loader = new Nette\Loaders\RobotLoader; $loader->addDirectory(__DIR__ . '/app'); -// Scanează directoarele pentru clase / interfețe / trăsături +// Scanează directoarele pentru clase/interfețe/trăsături/enume $loader->rebuild(); // Returnează o matrice de perechi clasă => nume de fișier $res = $loader->getIndexedClasses(); ``` -Chiar și în cazul unei astfel de utilizări, puteți utiliza memoria cache. Ca urmare, fișierele nemodificate nu vor fi analizate în mod repetat la o nouă scanare: +Chiar și în cazul unei astfel de utilizări, puteți utiliza memoria cache. Acest lucru asigură că fișierele neschimbate nu vor fi scanate din nou: ```php $loader = new Nette\Loaders\RobotLoader; $loader->addDirectory(__DIR__ . '/app'); + +// Setați memoria cache în directorul "temp $loader->setTempDirectory(__DIR__ . '/temp'); -// Scanează directoarele folosind o memorie cache +// Scanează directoarele folosind memoria cache $loader->refresh(); // Returnează o matrice de perechi clasă => nume de fișier @@ -116,23 +121,23 @@ $res = $loader->getIndexedClasses(); Caching .[#toc-caching] ----------------------- -RobotLoader este foarte rapid pentru că utilizează în mod inteligent memoria cache. +RobotLoader este foarte rapid pentru că folosește în mod inteligent memoria cache. -Atunci când dezvoltați cu el, practic nu aveți nicio idee că rulează în fundal. Actualizează continuu memoria cache deoarece știe că clasele și fișierele pot fi create, șterse, redenumite etc. Și nu scanează în mod repetat fișierele nemodificate. +În timpul dezvoltării, abia dacă veți observa că rulează în fundal. Își actualizează continuu memoria cache, având în vedere că clasele și fișierele pot fi create, șterse, redenumite etc. Și nu scanează din nou fișierele neschimbate. -Pe de altă parte, atunci când este utilizat pe un server de producție, vă recomandăm să dezactivați actualizarea cache-ului utilizând `$loader->setAutoRefresh(false)` (acest lucru se face automat în aplicația Nette), deoarece fișierele nu se modifică. În același timp, este necesar să **curățați memoria cache** atunci când încărcați o nouă versiune pe hosting. +Pe de altă parte, pe un server de producție, vă recomandăm să dezactivați actualizările cache-ului utilizând `$loader->setAutoRefresh(false)` (într-o aplicație Nette, acest lucru se întâmplă automat), deoarece fișierele nu se modifică. În același timp, este necesar să **curățați memoria cache** atunci când încărcați o nouă versiune la găzduire. -Desigur, scanarea inițială a fișierelor, atunci când memoria cache nu există deja, poate dura câteva secunde pentru aplicațiile mari. RobotLoader are încorporată o prevenire împotriva "cache stampede":https://en.wikipedia.org/wiki/Cache_stampede. -Aceasta este o situație în care serverul de producție primește un număr mare de cereri concurente și, deoarece memoria cache a RobotLoader nu există încă, toate ar începe să scaneze fișierele. Ceea ce crește brusc utilizarea CPU și a sistemului de fișiere. -Din fericire, RobotLoader funcționează în așa fel încât, pentru mai multe cereri concurente, doar primul fir indexează fișierele, creează o memorie cache, ceilalți așteaptă și apoi folosesc memoria cache. +Scanarea inițială a fișierelor, atunci când memoria cache nu există încă, poate dura în mod natural un moment pentru aplicațiile mari. RobotLoader are încorporată o prevenire împotriva "cache stampede":https://en.wikipedia.org/wiki/Cache_stampede. +Aceasta este o situație în care un număr mare de solicitări simultane pe un server de producție ar declanșa RobotLoader și, deoarece memoria cache nu există încă, toate ar începe să scaneze fișiere, ceea ce ar supraîncărca serverul. +Din fericire, RobotLoader funcționează în așa fel încât doar primul fir indexează fișierele, creează memoria cache, iar restul așteaptă și apoi utilizează memoria cache. PSR-4 .[#toc-psr-4] ------------------- -În prezent, Composer poate fi utilizat pentru [încărcarea automată |best-practices:composer#autoloading] în conformitate cu PSR-4. Spunând simplu, este un sistem în care spațiile de nume și numele claselor corespund structurii directoarelor și numelor de fișiere, adică `App\Router\RouterFactory` se află în fișierul `/path/to/App/Router/RouterFactory.php`. +În prezent, puteți utiliza [Composer pentru încărcare automată |best-practices:composer#autoloading], respectând în același timp PSR-4. Pe scurt, este un sistem în care spațiile de nume și numele claselor corespund structurii directoarelor și numelor de fișiere, de exemplu, `App\Router\RouterFactory` va fi în fișierul `/path/to/App/Router/RouterFactory.php`. -RobotLoader nu este legat de nicio structură fixă, prin urmare, este util în situațiile în care nu vă convine ca structura directoarelor să fie concepută ca spații de nume în PHP sau atunci când dezvoltați o aplicație care, din punct de vedere istoric, nu a folosit astfel de convenții. De asemenea, este posibil să se utilizeze ambele încărcătoare împreună. +RobotLoader nu este legat de nicio structură fixă, deci este util în situațiile în care nu doriți ca structura directoarelor să fie concepută exact ca spațiile de nume PHP sau atunci când dezvoltați o aplicație care, din punct de vedere istoric, nu folosește astfel de convenții. De asemenea, este posibil să folosiți ambele încărcătoare împreună. {{leftbar: nette:@menu-topics}} diff --git a/robot-loader/ru/@home.texy b/robot-loader/ru/@home.texy index e050f34605..8423289cb7 100644 --- a/robot-loader/ru/@home.texy +++ b/robot-loader/ru/@home.texy @@ -1,39 +1,42 @@ -RobotLoader: Класс автозагрузки -******************************* +RobotLoader: Автозагрузка классов +*********************************
    -RobotLoader — это инструмент, обеспечивающий автоматическую загрузку классов для всего приложения, включая библиотеки сторонних разработчиков. +RobotLoader - это инструмент, обеспечивающий удобство автоматической загрузки классов для всего приложения, включая библиотеки сторонних разработчиков. -- избавиться от всех `require` -- загружаются только необходимые скрипты -- не требует строгих соглашений об именовании каталогов или файлов +- Исключите все утверждения `require`. +- Загружаются только необходимые скрипты +- Не требует строгих соглашений об именовании каталогов и файлов +- Чрезвычайно быстро +- Не нужно вручную обновлять кэш, все выполняется автоматически +- Зрелая, стабильная и широко используемая библиотека
    -Так что мы можем забыть об этих знаменитых блоках кода: +Таким образом, мы можем забыть об этих привычных блоках кода: ```php require_once 'Utils/Page.php'; require_once 'Utils/Style.php'; require_once 'Utils/Paginator.php'; -// ... +//... ``` Установка .[#toc-installation] ------------------------------ -Вы можете загрузить RobotLoader в виде [отдельного файла `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], который можно включить в свой скрипт с помощью `require`, и сразу же получить удобную автозагрузку для всего приложения: +Вы можете загрузить RobotLoader в виде [отдельного файла `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], который вы включаете с помощью `require` в свой скрипт и сразу же получаете удобную автозагрузку для всего приложения. ```php require '/path/to/RobotLoader.php'; $loader = new Nette\Loaders\RobotLoader; -// ... +//... ``` -Если вы создаете приложение, использующее [Composer |best-practices:composer], вы можете установить его через него: +Если вы собираете приложение с помощью [Composer |best-practices:composer], то установить его можно через: ```shell composer require nette/robot-loader @@ -43,37 +46,37 @@ composer require nette/robot-loader Использование .[#toc-usage] --------------------------- -Подобно тому, как робот Google просматривает и индексирует сайты, [RobotLoader |api:Nette\Loaders\RobotLoader] просматривает все PHP-скрипты и записывает, какие классы и интерфейсы были в них найдены. Затем эти записи сохраняются в кэше и используются при всех последующих запросах. Вам просто нужно указать, какие каталоги индексировать и где сохранять кэш: +Подобно тому, как робот Google просматривает и индексирует веб-страницы, [RobotLoader |api:Nette\Loaders\RobotLoader] просматривает все PHP-скрипты и отмечает, какие классы, интерфейсы, трейты и перечисления он нашел. Затем он сохраняет результаты в кэше для использования при последующих запросах. Вам нужно только указать, по каким каталогам он должен пройти и где хранить кэш: ```php $loader = new Nette\Loaders\RobotLoader; -// каталоги, которые будут индексироваться RobotLoader (включая подкаталоги) +// Каталоги для индексации RobotLoader (включая подкаталоги) $loader->addDirectory(__DIR__ . '/app'); $loader->addDirectory(__DIR__ . '/libs'); -// использовать каталог 'temp' для кэша +// Установите кэширование в каталог 'temp' $loader->setTempDirectory(__DIR__ . '/temp'); -$loader->register(); // Run the RobotLoader +$loader->register(); // Активировать RobotLoader ``` -И это всё. С этого момента вам не нужно использовать `require`. Здорово, не так ли? +И все, с этого момента нам не нужно использовать `require`. Круто! -Когда RobotLoader сталкивается с дублированием имени класса во время индексирования, он выбрасывает исключение и сообщает вам об этом. RobotLoader также автоматически обновляет кэш, когда ему нужно загрузить неизвестный ему класс. Мы рекомендуем отключить это на производственных серверах, см. [#Кэширование]. +Если в процессе индексирования RobotLoader столкнется с дублированием имени класса, он выбросит исключение и сообщит об этом. RobotLoader также автоматически обновляет кэш, когда ему необходимо загрузить неизвестный класс. Мы рекомендуем отключить эту функцию на рабочих серверах, см. раздел " [Кэширование |#Caching]". -Если вы хотите, чтобы RobotLoader пропускал некоторые каталоги, используйте `$loader->excludeDirectory('temp')` (его можно вызвать несколько раз или передать несколько каталогов). +Если вы хотите, чтобы RobotLoader пропускал определенные каталоги, используйте команду `$loader->excludeDirectory('temp')` (может вызываться несколько раз или передавать несколько каталогов). -По умолчанию RobotLoader сообщает об ошибках в PHP-файлах, бросая исключение `ParseError`. Его можно отключить с помощью `$loader->reportParseErrors(false)`. +По умолчанию RobotLoader сообщает об ошибках в PHP-файлах, выбрасывая исключение `ParseError`. Это может быть подавлено с помощью `$loader->reportParseErrors(false)`. -Приложение Nette .[#toc-nette-application] ------------------------------------------- +Nette Application .[#toc-nette-application] +------------------------------------------- -Внутри приложения Nette, где `$configurator` используется в `Bootstrap.php`, вы можете настроить RobotLoader таким образом: +Внутри Nette Application, где `$configurator` используется в `Bootstrap.php`, можно настроить RobotLoader таким образом: ```php $configurator = new Nette\Bootstrap\Configurator; -// ... +//... $configurator->setTempDirectory(__DIR__ . '/../temp'); $configurator->createRobotLoader() ->addDirectory(__DIR__) @@ -82,27 +85,29 @@ $configurator->createRobotLoader() ``` -Анализатор файлов PHP .[#toc-php-files-analyzer] +Анализатор PHP-файлов .[#toc-php-files-analyzer] ------------------------------------------------ -RobotLoader также можно использовать чисто для поиска классов, интерфейсов и трейтов в PHP-файлах **без** использования функции автозагрузки: +RobotLoader также может быть использован чисто для поиска классов, интерфейсов, трейтов и перечислений в PHP-файлах **без** использования функции автозагрузки: ```php $loader = new Nette\Loaders\RobotLoader; $loader->addDirectory(__DIR__ . '/app'); -// Сканирует каталоги на наличие классов / интерфейсов / трейтов +// Сканирует каталоги на наличие классов/интерфейсов/трайтов/энумов $loader->rebuild(); // Возвращает массив пар класс => имя файла $res = $loader->getIndexedClasses(); ``` -Даже при таком использовании вы можете использовать кэш. В результате немодифицированные файлы не будут повторно анализироваться при повторном сканировании: +Даже при таком использовании можно использовать кэширование. Это гарантирует, что неизмененные файлы не будут сканироваться повторно: ```php $loader = new Nette\Loaders\RobotLoader; $loader->addDirectory(__DIR__ . '/app'); + +// Установить кэширование в каталог 'temp' $loader->setTempDirectory(__DIR__ . '/temp'); // Сканирование каталогов с использованием кэша @@ -116,23 +121,23 @@ $res = $loader->getIndexedClasses(); Кэширование .[#toc-caching] --------------------------- -RobotLoader работает очень быстро, потому что он разумно использует кэш. +RobotLoader работает очень быстро, поскольку в нем разумно используется кэширование. -При разработке с ним вы практически не замечаете, что он работает в фоновом режиме. Он постоянно обновляет кэш, поскольку знает, что классы и файлы могут быть созданы, удалены, переименованы и т. д. И он не сканирует повторно немодифицированные файлы. +Во время разработки вы едва ли заметите, что он работает в фоновом режиме. Он постоянно обновляет свой кэш, учитывая, что классы и файлы могут создаваться, удаляться, переименовываться и т.д. При этом повторное сканирование неизмененных файлов не производится. -При использовании на рабочем сервере, с другой стороны, мы рекомендуем отключить обновление кэша с помощью `$loader->setAutoRefresh(false)` (это делается автоматически в приложении Nette), поскольку файлы не меняются. В то же время, необходимо **очистить кэш** при загрузке новой версии на хостинг. +На рабочем же сервере мы рекомендуем отключить обновление кэша с помощью `$loader->setAutoRefresh(false)` (в Nette Application это происходит автоматически), поскольку файлы не меняются. В то же время при загрузке новой версии на хостинг необходимо **очищать кэш**. -Конечно, первоначальное сканирование файлов, когда кэш ещё не существует, может занять несколько секунд для больших приложений. RobotLoader имеет встроенную защиту от "cache stampede":https://en.wikipedia.org/wiki/Cache_stampede. -Это ситуация, когда производственный сервер получает большое количество одновременных запросов, и поскольку кэш RobotLoader ещё не существует, все они начнут сканировать файлы. Это увеличивает нагрузку на процессор и файловую систему. -К счастью, RobotLoader работает таким образом, что при нескольких одновременных запросах только первый поток индексирует файлы, создает кэш, остальные ждут, а затем используют кэш. +Первоначальное сканирование файлов, когда кэш еще не существует, естественно, может занять некоторое время для больших приложений. RobotLoader имеет встроенную защиту от "cache stampede":https://en.wikipedia.org/wiki/Cache_stampede. +Это ситуация, когда большое количество одновременных запросов на рабочем сервере вызовет RobotLoader, и поскольку кэш еще не существует, все они начнут сканировать файлы, что приведет к перегрузке сервера. +К счастью, RobotLoader работает таким образом, что только первый поток индексирует файлы, создает кэш, а остальные ждут и затем используют кэш. -PSR-4 ------ +PSR-4 .[#toc-psr-4] +------------------- -Сегодня Composer можно использовать для [автозагрузки|best-practices:composer#Autoloading] в соответствии с PSR-4. Проще говоря, это система, в которой пространства имен и имена классов соответствуют структуре каталогов и именам файлов, т. е. `App\Router\RouterFactory` находится в файле `/path/to/App/Router/RouterFactory.php`. +В настоящее время [для автозагрузки |best-practices:composer#autoloading] можно использовать [Composer |best-practices:composer#autoloading], придерживаясь при этом PSR-4. Проще говоря, это система, в которой пространства имен и имена классов соответствуют структуре каталогов и именам файлов, например, `App\Router\RouterFactory` будет находиться в файле `/path/to/App/Router/RouterFactory.php`. -RobotLoader не привязан к какой-либо фиксированной структуре, поэтому он полезен в ситуациях, когда вам не подходит структура каталогов, оформленная в виде пространств имен в PHP, или когда вы разрабатываете приложение, в котором исторически не используются такие соглашения. Также можно использовать оба загрузчика вместе. +RobotLoader не привязан к какой-либо фиксированной структуре, поэтому он полезен в ситуациях, когда не требуется, чтобы структура каталогов была оформлена в точном соответствии с пространствами имен PHP, или при разработке приложения, в котором исторически не используются подобные соглашения. Также возможно совместное использование обоих загрузчиков. {{leftbar: nette:@menu-topics}} diff --git a/robot-loader/sl/@home.texy b/robot-loader/sl/@home.texy index 9415d0f3c7..ce31e031db 100644 --- a/robot-loader/sl/@home.texy +++ b/robot-loader/sl/@home.texy @@ -5,35 +5,38 @@ RobotLoader: Samodejno nalaganje razreda RobotLoader je orodje, ki omogoča samodejno nalaganje razredov za celotno aplikacijo, vključno s knjižnicami tretjih oseb. -- znebite se vseh `require` -- naložijo se samo potrebni skripti -- ne zahteva strogih konvencij za poimenovanje imenikov ali datotek +- Odpravite vse izjave `require` +- Nalagali se bodo samo potrebni skripti +- Ne zahteva strogih poimenovalnih konvencij za imenike ali datoteke +- Izjemno hitro +- Ni ročnih posodobitev predpomnilnika, vse poteka samodejno +- Zrela, stabilna in široko uporabljena knjižnica
    -Zato lahko pozabimo na tiste znamenite bloke kode: +Tako lahko pozabimo na te znane bloke kode: ```php require_once 'Utils/Page.php'; require_once 'Utils/Style.php'; require_once 'Utils/Paginator.php'; -// ... +//... ``` Namestitev .[#toc-installation] ------------------------------- -RobotLoader lahko prenesete kot [eno samostojno datoteko `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], ki jo lahko vključite v svojo skripto z uporabo `require` in takoj dobite priročno samodejno polnjenje za celotno aplikacijo: +RobotLoader lahko prenesete kot [eno samostojno datoteko `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], ki jo s pomočjo `require` vključite v svojo skripto, in takoj uživate v udobnem samodejnem nalaganju za celotno aplikacijo. ```php require '/path/to/RobotLoader.php'; $loader = new Nette\Loaders\RobotLoader; -// ... +//... ``` -Če gradite aplikacijo, ki uporablja [program Composer |best-practices:composer], ga lahko namestite prek njega: +Če gradite aplikacijo z uporabo programa [Composer |best-practices:composer], ga lahko namestite prek: ```shell composer require nette/robot-loader @@ -43,37 +46,37 @@ composer require nette/robot-loader Uporaba .[#toc-usage] --------------------- -Podobno kot robot Google preiskuje in indeksira spletna mesta, [RobotLoader |api:Nette\Loaders\RobotLoader] preiskuje vse skripte PHP in beleži, katere razrede in vmesnike je našel v njih. Ti zapisi se nato shranijo v predpomnilnik in uporabijo pri vseh naslednjih zahtevah. Določiti morate le, katere imenike indeksirati in kam shraniti predpomnilnik: +Podobno kot robot Google preiskuje in indeksira spletne strani, [RobotLoader |api:Nette\Loaders\RobotLoader] pregleda vse skripte PHP in zapiše, katere razrede, vmesnike, lastnosti in enume je našel. Rezultate nato shrani v predpomnilnik za uporabo pri naslednjih zahtevah. Določiti morate le, katere imenike naj pregleda in kje naj shrani predpomnilnik: ```php $loader = new Nette\Loaders\RobotLoader; -// imeniki, ki jih bo indeksiral RobotLoader (vključno s podimeniki). +// imeniki za indeksiranje RobotLoaderja (vključno s podimeniki) $loader->addDirectory(__DIR__ . '/app'); $loader->addDirectory(__DIR__ . '/libs'); -// uporabite imenik 'temp' za predpomnilnik +// Nastavitev predpomnjenja na imenik 'temp' $loader->setTempDirectory(__DIR__ . '/temp'); -$loader->register(); // Zaženite RobotLoader +$loader->register(); // Aktivirajte RobotLoader ``` -In to je vse. Od zdaj naprej vam ni treba več uporabljati `require`. Super, kajne? +In to je to, od te točke naprej nam ni treba več uporabljati `require`. Odlično! -Ko RobotLoader med indeksiranjem naleti na podvojeno ime razreda, vrže izjemo in vas o tem obvesti. RobotLoader tudi samodejno posodobi predpomnilnik, kadar mora naložiti razred, ki ga ne pozna. Priporočamo, da to onemogočite v produkcijskih strežnikih, glejte poglavje [Predpomnilnik |#Caching]. +Če RobotLoader med indeksiranjem naleti na podvojeno ime razreda, bo vrgel izjemo in vas o tem obvestil. RobotLoader tudi samodejno posodobi predpomnilnik, kadar mora naložiti neznan razred. Priporočamo, da to izklopite na produkcijskih strežnikih, glejte [Predpomnilnik |#Caching]. -Če želite, da RobotLoader preskoči nekatere imenike, uporabite `$loader->excludeDirectory('temp')` (lahko ga pokličete večkrat ali posredujete več imenikov). +Če želite, da RobotLoader preskoči določene imenike, uporabite `$loader->excludeDirectory('temp')` (lahko ga pokličete večkrat ali posredujete več imenikov). -Privzeto RobotLoader poroča o napakah v datotekah PHP tako, da vrže izjemo `ParseError`. To lahko onemogočite prek `$loader->reportParseErrors(false)`. +Privzeto RobotLoader poroča o napakah v datotekah PHP tako, da vrže izjemo `ParseError`. To lahko odpravite z uporabo `$loader->reportParseErrors(false)`. -Nette aplikacija .[#toc-nette-application] ------------------------------------------- +Neto aplikacija .[#toc-nette-application] +----------------------------------------- -Znotraj aplikacije Nette, kjer se `$configurator` uporablja v `Bootstrap.php`, lahko RobotLoader nastavite na ta način: +Znotraj aplikacije Nette Application, kjer se `$configurator` uporablja v `Bootstrap.php`, lahko RobotLoader nastavite na ta način: ```php $configurator = new Nette\Bootstrap\Configurator; -// ... +//... $configurator->setTempDirectory(__DIR__ . '/../temp'); $configurator->createRobotLoader() ->addDirectory(__DIR__) @@ -82,27 +85,29 @@ $configurator->createRobotLoader() ``` -PHP Files Analyzer .[#toc-php-files-analyzer] ---------------------------------------------- +Analizator datotek PHP .[#toc-php-files-analyzer] +------------------------------------------------- -RobotLoader lahko uporabite tudi za iskanje razredov, vmesnikov in lastnosti v datotekah PHP, ne da bi uporabili funkcijo samodejnega nalaganja: +RobotLoader lahko uporabite tudi za iskanje razredov, vmesnikov, lastnosti in enumov v datotekah PHP, ne da bi uporabili funkcijo samodejnega nalaganja: ```php $loader = new Nette\Loaders\RobotLoader; $loader->addDirectory(__DIR__ . '/app'); -// Pregledovanje imenikov za razrede / vmesnike / lastnosti +// Pregleduje imenike za razrede/interfaces/traits/enums $loader->rebuild(); // Vrne polje parov razred => ime datoteke $res = $loader->getIndexedClasses(); ``` -Tudi pri takšni uporabi lahko uporabite predpomnilnik. Zaradi tega se nespremenjene datoteke pri ponovnem iskanju ne bodo večkrat analizirale: +Tudi pri takšni uporabi lahko uporabite predpomnjenje. To zagotavlja, da se nespremenjene datoteke ne bodo ponovno iskale: ```php $loader = new Nette\Loaders\RobotLoader; $loader->addDirectory(__DIR__ . '/app'); + +// Nastavite predpomnjenje v imenik 'temp' $loader->setTempDirectory(__DIR__ . '/temp'); // Pregleduje imenike z uporabo predpomnilnika @@ -116,23 +121,23 @@ $res = $loader->getIndexedClasses(); Predpomnilnik .[#toc-caching] ----------------------------- -RobotLoader je zelo hiter, ker pametno uporablja predpomnilnik. +RobotLoader je zelo hiter, ker pametno uporablja predpomnjenje. -Pri razvijanju z njim praktično ne veste, da deluje v ozadju. Sprotno posodablja predpomnilnik, saj ve, da se razredi in datoteke lahko ustvarjajo, brišejo, preimenujejo itd. In ne pregleduje nespremenjenih datotek večkrat. +Med razvojem skoraj ne opazite, da teče v ozadju. Svoj predpomnilnik nenehno posodablja, saj upošteva, da se razredi in datoteke lahko ustvarjajo, brišejo, preimenujejo itd. Nespremenjenih datotek ne pregleduje ponovno. -Pri uporabi v produkcijskem strežniku pa priporočamo, da posodobitev predpomnilnika onemogočite z uporabo spletne strani `$loader->setAutoRefresh(false)` (to se samodejno izvede v aplikaciji Nette), saj se datoteke ne spreminjajo. Hkrati je treba **izbrisati predpomnilnik** ob prenosu nove različice na gostovanje. +V produkcijskem strežniku pa priporočamo, da posodobitve predpomnilnika izklopite z uporabo spletne strani `$loader->setAutoRefresh(false)` (v aplikaciji Nette se to zgodi samodejno), saj se datoteke ne spreminjajo. Hkrati je treba **izbrisati predpomnilnik** ob prenosu nove različice na gostovanje. -Seveda lahko začetno pregledovanje datotek, ko predpomnilnik še ne obstaja, pri večjih aplikacijah traja nekaj sekund. RobotLoader ima vgrajeno preprečevanje "stampeda predpomnilnika":https://en.wikipedia.org/wiki/Cache_stampede. -To je situacija, ko produkcijski strežnik prejme veliko število hkratnih zahtevkov in ker predpomnilnik RobotLoader še ne obstaja, bi vsi začeli skenirati datoteke. To poveča porabo procesorja in datotečnega sistema. -Na srečo RobotLoader deluje tako, da pri več hkratnih zahtevah le prva nit indeksira datoteke, ustvari predpomnilnik, druge počakajo in nato uporabijo predpomnilnik. +Začetno pregledovanje datotek, ko predpomnilnik še ne obstaja, lahko pri večjih aplikacijah seveda traja nekaj časa. RobotLoader ima vgrajeno preprečevanje "stampeda predpomnilnika":https://en.wikipedia.org/wiki/Cache_stampede. +To je situacija, ko bi veliko število hkratnih zahtevkov v produkcijskem strežniku sprožilo RobotLoader, in ker predpomnilnik še ne obstaja, bi vsi začeli pregledovati datoteke, kar bi preobremenilo strežnik. +Na srečo RobotLoader deluje tako, da samo prva nit indeksira datoteke in ustvari predpomnilnik, ostale pa počakajo in nato uporabijo predpomnilnik. PSR-4 .[#toc-psr-4] ------------------- -Danes se lahko program Composer uporablja za [samodejno polnjenje v |best-practices:composer#autoloading] skladu s PSR-4. Preprosto povedano, gre za sistem, v katerem imenska območja in imena razredov ustrezajo imeniški strukturi in imenom datotek, tj. `App\Router\RouterFactory` se nahaja v datoteki `/path/to/App/Router/RouterFactory.php`. +Danes lahko [za samodejno nalaganje uporabljate program Composer |best-practices:composer#autoloading] in hkrati upoštevate PSR-4. Preprosto povedano, gre za sistem, v katerem imenska območja in imena razredov ustrezajo imeniški strukturi in imenom datotek, npr. `App\Router\RouterFactory` bo v datoteki `/path/to/App/Router/RouterFactory.php`. -RobotLoader ni vezan na nobeno fiksno strukturo, zato je uporaben v primerih, ko vam ne ustreza, da je struktura imenikov zasnovana kot imenski prostori v PHP, ali ko razvijate aplikacijo, ki v preteklosti ni uporabljala takih konvencij. Oba nalagalnika je mogoče uporabljati tudi skupaj. +RobotLoader ni vezan na nobeno fiksno strukturo, zato je uporaben v primerih, ko ne želite, da bi bila struktura imenikov zasnovana povsem enako kot imenski prostori PHP, ali pri razvoju aplikacije, ki v preteklosti ni uporabljala takšnih konvencij. Oba nalagalnika je mogoče uporabljati tudi skupaj. {{leftbar: nette:@menu-topics}} diff --git a/robot-loader/tr/@home.texy b/robot-loader/tr/@home.texy index 4fde195cb7..469aa54554 100644 --- a/robot-loader/tr/@home.texy +++ b/robot-loader/tr/@home.texy @@ -5,35 +5,38 @@ RobotLoader: Sınıf Otomatik Yükleme RobotLoader, üçüncü taraf kütüphaneleri de dahil olmak üzere tüm uygulamanız için otomatik sınıf yükleme rahatlığı sağlayan bir araçtır. -- hepsinden kurtulun `require` -- sadece gerekli komut dosyaları yüklenir -- katı dizin veya dosya adlandırma kuralları gerektirmez +- Tüm `require` ifadelerini ortadan kaldırın +- Yalnızca gerekli komut dosyaları yüklenecektir +- Dizinler veya dosyalar için katı adlandırma kuralları gerektirmez +- Son derece hızlı +- Manuel önbellek güncellemesi yok, her şey otomatik olarak çalışıyor +- Olgun, istikrarlı ve yaygın olarak kullanılan kütüphane
    -Bu yüzden o meşhur kod bloklarını unutabiliriz: +Böylece, bu tanıdık kod bloklarını unutabiliriz: ```php require_once 'Utils/Page.php'; require_once 'Utils/Style.php'; require_once 'Utils/Paginator.php'; -// ... +//... ``` Kurulum .[#toc-installation] ---------------------------- -RobotLoader'ı `require` kullanarak komut [dosyanıza |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php] ekleyebileceğiniz [tek |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php] bir [bağımsız dosya `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php] olarak indirebilir ve hemen tüm uygulamanız için uygun otomatik yüklemeye sahip olabilirsiniz: +RobotLoader'ı, komut dosyanıza `require` kullanarak eklediğiniz tek bir [bağımsız dosya `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php] olarak indirebilir ve anında tüm uygulama için rahat otomatik yüklemenin keyfini çıkarabilirsiniz. ```php require '/path/to/RobotLoader.php'; $loader = new Nette\Loaders\RobotLoader; -// ... +//... ``` - [Composer |best-practices:composer] kullanan bir uygulama geliştiriyorsanız, [Composer |best-practices:composer] aracılığıyla yükleyebilirsiniz: + [Composer |best-practices:composer] kullanarak bir uygulama oluşturuyorsanız, bunu şu yolla yükleyebilirsiniz: ```shell composer require nette/robot-loader @@ -43,37 +46,37 @@ composer require nette/robot-loader Kullanım .[#toc-usage] ---------------------- -Google robotunun web sitelerini taraması ve indekslemesi gibi, [RobotLoader |api:Nette\Loaders\RobotLoader] da tüm PHP betiklerini tarar ve içlerinde hangi sınıfların ve arayüzlerin bulunduğunu kaydeder. Bu kayıtlar daha sonra önbelleğe kaydedilir ve sonraki tüm istekler sırasında kullanılır. Sadece hangi dizinlerin indeksleneceğini ve önbelleğin nereye kaydedileceğini belirtmeniz gerekir: +Google robotunun web sayfalarını tarayıp indekslemesine benzer şekilde, [RobotLoader |api:Nette\Loaders\RobotLoader] tüm PHP betiklerini gözden geçirir ve hangi sınıfları, arayüzleri, özellikleri ve enumları bulduğunu not eder. Daha sonra sonuçları sonraki isteklerde kullanmak üzere önbellekte saklar. Sadece hangi dizinlerden geçmesi gerektiğini ve önbelleğin nerede saklanacağını belirtmeniz gerekir: ```php $loader = new Nette\Loaders\RobotLoader; -// RobotLoader tarafından indekslenecek dizinler (alt dizinler dahil) +// RobotLoader'ın dizine ekleyeceği dizinler (alt dizinler dahil) $loader->addDirectory(__DIR__ . '/app'); $loader->addDirectory(__DIR__ . '/libs'); -// önbellek için 'temp' dizinini kullan +// Önbelleğe almayı 'temp' dizinine ayarlayın $loader->setTempDirectory(__DIR__ . '/temp'); -$loader->register(); // RobotLoader'ı çalıştır +$loader->register(); // RobotLoader'ı Etkinleştir ``` -Ve hepsi bu kadar. Şu andan itibaren `require` adresini kullanmanıza gerek yok. Harika, değil mi? +İşte bu kadar, bu noktadan sonra `require` adresini kullanmamıza gerek yok. Harika! -RobotLoader, indeksleme sırasında yinelenen sınıf adıyla karşılaştığında, bir istisna atar ve sizi bu konuda bilgilendirir. RobotLoader ayrıca bilmediği bir sınıfı yüklemek zorunda kaldığında önbelleği otomatik olarak günceller. Üretim sunucularında bunu [devre |#Caching] dışı bırakmanızı öneririz, bkz. +RobotLoader, indeksleme sırasında yinelenen bir sınıf adıyla karşılaşırsa, bir istisna atacak ve sizi bilgilendirecektir. RobotLoader ayrıca bilinmeyen bir sınıfı yüklemesi gerektiğinde önbelleği otomatik olarak günceller. Üretim sunucularında bunu [kapatmanızı |#Caching] öneririz, bkz. -RobotLoader'ın bazı dizinleri atlamasını istiyorsanız, `$loader->excludeDirectory('temp')` adresini kullanın (birden çok kez çağrılabilir veya birden çok dizin geçebilirsiniz). +RobotLoader'ın belirli dizinleri atlamasını istiyorsanız, `$loader->excludeDirectory('temp')` adresini kullanın (birden çok kez çağrılabilir veya birden çok dizin geçebilir). -Varsayılan olarak, RobotLoader PHP dosyalarındaki hataları `ParseError` istisnası atarak bildirir. `$loader->reportParseErrors(false)` üzerinden devre dışı bırakılabilir. +Varsayılan olarak, RobotLoader PHP dosyalarındaki hataları bir `ParseError` istisnası atarak bildirir. Bu, `$loader->reportParseErrors(false)` kullanılarak bastırılabilir. Nette Uygulama .[#toc-nette-application] ---------------------------------------- -Nette uygulaması içinde, `$configurator` adresinin kullanıldığı `Bootstrap.php` adresinde RobotLoader'ı bu şekilde kurabilirsiniz: + `$configurator` adresinin `Bootstrap.php` adresinde kullanıldığı Nette Uygulaması içinde RobotLoader'ı bu şekilde kurabilirsiniz: ```php $configurator = new Nette\Bootstrap\Configurator; -// ... +//... $configurator->setTempDirectory(__DIR__ . '/../temp'); $configurator->createRobotLoader() ->addDirectory(__DIR__) @@ -85,27 +88,29 @@ $configurator->createRobotLoader() PHP Dosya Çözümleyicisi .[#toc-php-files-analyzer] -------------------------------------------------- -RobotLoader, otomatik yükleme özelliğini kullanmadan ** PHP dosyalarındaki sınıfları, arayüzleri ve özellikleri bulmak için de kullanılabilir: +RobotLoader, otomatik yükleme işlevini kullanmadan ** PHP dosyalarındaki sınıfları, arayüzleri, özellikleri ve enumları bulmak için de kullanılabilir: ```php $loader = new Nette\Loaders\RobotLoader; $loader->addDirectory(__DIR__ . '/app'); -// Sınıflar / arayüzler / özellikler için dizinleri tarar +// Sınıflar/arayüzler/özellikler/enumlar için dizinleri tarar $loader->rebuild(); // Sınıf => dosya adı çiftlerinden oluşan bir dizi döndürür $res = $loader->getIndexedClasses(); ``` -Böyle bir kullanımda bile önbelleği kullanabilirsiniz. Sonuç olarak, değiştirilmemiş dosyalar yeniden taranırken tekrar tekrar analiz edilmeyecektir: +Böyle bir kullanımda bile önbelleğe alma özelliğinden yararlanabilirsiniz. Bu, değişmeyen dosyaların yeniden taranmamasını sağlar: ```php $loader = new Nette\Loaders\RobotLoader; $loader->addDirectory(__DIR__ . '/app'); + +// Önbelleğe almayı 'temp' dizinine ayarlayın $loader->setTempDirectory(__DIR__ . '/temp'); -// Bir önbellek kullanarak dizinleri tarar +// Önbellek kullanarak dizinleri tarar $loader->refresh(); // Sınıf => dosya adı çiftlerinden oluşan bir dizi döndürür @@ -116,23 +121,23 @@ $res = $loader->getIndexedClasses(); Önbellekleme .[#toc-caching] ---------------------------- -RobotLoader çok hızlıdır çünkü önbelleği akıllıca kullanır. +RobotLoader çok hızlıdır çünkü akıllıca önbellekleme kullanır. -Onunla geliştirme yaparken, arka planda çalıştığına dair neredeyse hiçbir fikriniz olmaz. Sınıfların ve dosyaların oluşturulabileceğini, silinebileceğini, yeniden adlandırılabileceğini vb. bildiği için önbelleği sürekli olarak günceller. Ve değiştirilmemiş dosyaları tekrar tekrar taramaz. +Geliştirme sırasında, arka planda çalıştığını neredeyse hiç fark etmezsiniz. Sınıfların ve dosyaların oluşturulabileceğini, silinebileceğini, yeniden adlandırılabileceğini vb. göz önünde bulundurarak önbelleğini sürekli olarak günceller. Ve değişmemiş dosyaları yeniden taramaz. -Öte yandan, bir üretim sunucusunda kullanıldığında, dosyalar değişmediği için `$loader->setAutoRefresh(false)` adresini kullanarak önbellek güncellemesini devre dışı bırakmanızı öneririz (bu, Nette Uygulamasında otomatik olarak yapılır). Aynı zamanda, barındırmaya yeni bir sürüm yüklerken **önbelleği temizlemek** gerekir. +Öte yandan, bir üretim sunucusunda, dosyalar değişmediği için `$loader->setAutoRefresh(false)` adresini kullanarak önbellek güncellemelerini kapatmanızı öneririz (bir Nette Uygulamasında bu otomatik olarak gerçekleşir). Aynı zamanda, barındırmaya yeni bir sürüm yüklerken **önbelleği temizlemek** gerekir. -Elbette, önbellek zaten mevcut olmadığında dosyaların ilk taranması, daha büyük uygulamalar için birkaç saniye sürebilir. RobotLoader, "önbellek izdihamına":https://en.wikipedia.org/wiki/Cache_stampede karşı yerleşik bir önleme sahiptir. -Bu, üretim sunucusunun çok sayıda eşzamanlı istek aldığı bir durumdur ve RobotLoader'ın önbelleği henüz mevcut olmadığından, hepsi dosyaları taramaya başlayacaktır. Bu da CPU ve dosya sistemi kullanımını artırır. -Neyse ki, RobotLoader, birden fazla eşzamanlı istek için, yalnızca ilk iş parçacığı dosyaları indeksleyecek, bir önbellek oluşturacak, diğerleri bekleyecek ve ardından önbelleği kullanacak şekilde çalışır. +Önbellek henüz mevcut olmadığında ilk dosya taraması, daha büyük uygulamalar için doğal olarak biraz zaman alabilir. RobotLoader, "önbellek izdihamına":https://en.wikipedia.org/wiki/Cache_stampede karşı yerleşik bir önleme sahiptir. +Bu, bir üretim sunucusunda çok sayıda eşzamanlı isteğin RobotLoader'ı tetikleyeceği bir durumdur ve önbellek henüz mevcut olmadığından, hepsi sunucuyu aşırı yükleyecek dosyaları taramaya başlayacaktır. +Neyse ki, RobotLoader sadece ilk iş parçacığı dosyaları indeksleyecek, önbelleği oluşturacak ve geri kalanı bekleyecek ve sonra önbelleği kullanacak şekilde çalışır. PSR-4 .[#toc-psr-4] ------------------- -Günümüzde Composer, PSR-4'e uygun olarak [otomatik yükleme |best-practices:composer#autoloading] için kullanılabilmektedir. Basitçe söylemek gerekirse, isim alanlarının ve sınıf isimlerinin dizin yapısına ve dosya isimlerine karşılık geldiği bir sistemdir, yani `App\Router\RouterFactory` `/path/to/App/Router/RouterFactory.php` dosyasında bulunur. +Günümüzde, PSR-4'e bağlı kalarak [Composer'ı otomatik yükleme için |best-practices:composer#autoloading] kullanabilirsiniz. Basitçe söylemek gerekirse, ad alanlarının ve sınıf adlarının dizin yapısına ve dosya adlarına karşılık geldiği bir sistemdir, örneğin, `App\Router\RouterFactory` `/path/to/App/Router/RouterFactory.php` dosyasında olacaktır. -RobotLoader herhangi bir sabit yapıya bağlı değildir, bu nedenle PHP'de ad alanları olarak tasarlanmış dizin yapısına sahip olmanın size uygun olmadığı durumlarda veya tarihsel olarak bu tür sözleşmeleri kullanmayan bir uygulama geliştirirken kullanışlıdır. Her iki yükleyiciyi birlikte kullanmak da mümkündür. +RobotLoader herhangi bir sabit yapıya bağlı değildir, bu nedenle dizin yapısının tam olarak PHP ad alanları gibi tasarlanmasını istemediğiniz durumlarda veya tarihsel olarak bu tür kuralları kullanmayan bir uygulama geliştirirken kullanışlıdır. Her iki yükleyiciyi birlikte kullanmak da mümkündür. {{leftbar: nette:@menu-topics}} diff --git a/robot-loader/uk/@home.texy b/robot-loader/uk/@home.texy index da2070658f..5df8c3a77f 100644 --- a/robot-loader/uk/@home.texy +++ b/robot-loader/uk/@home.texy @@ -1,39 +1,42 @@ -RobotLoader: Клас автозавантаження -********************************** +RobotLoader: Автозавантаження класу +***********************************
    -RobotLoader - це інструмент, що забезпечує автоматичне завантаження класів для всієї програми, включно з бібліотеками сторонніх розробників. +RobotLoader - це інструмент, який надає вам зручність автоматичного завантаження класів для всього вашого додатку, включаючи сторонні бібліотеки. -- позбутися всіх `require` -- завантажуються тільки необхідні скрипти -- не вимагає суворих угод про іменування каталогів або файлів +- Усуньте всі оператори `require` +- Завантажуються лише необхідні скрипти +- Не вимагає суворого дотримання правил іменування каталогів або файлів +- Надзвичайно швидкий +- Ніяких ручних оновлень кешу, все виконується автоматично +- Зріла, стабільна та широко використовувана бібліотека
    -Тож ми можемо забути про ці знамениті блоки коду: +Таким чином, ми можемо забути про ці звичні блоки коду: ```php require_once 'Utils/Page.php'; require_once 'Utils/Style.php'; require_once 'Utils/Paginator.php'; -// ... +//... ``` Встановлення .[#toc-installation] --------------------------------- -Ви можете завантажити RobotLoader як [окремий файл `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], який ви можете включити в свій скрипт за допомогою `require`, і одразу ж мати зручне автозавантаження для всього вашого додатку: +Ви можете завантажити RobotLoader як [окремий файл `RobotLoader.php` |https://github.com/nette/robot-loader/raw/standalone/src/RobotLoader/RobotLoader.php], який ви включаєте за допомогою `require` у ваш скрипт, і миттєво насолоджуватися зручним автозавантаженням для всього додатку. ```php require '/path/to/RobotLoader.php'; $loader = new Nette\Loaders\RobotLoader; -// ... +//... ``` -Якщо ви створюєте додаток, який використовує [Composer |best-practices:composer], ви можете встановити його через нього: +Якщо ви створюєте додаток за допомогою [Composer |best-practices:composer], ви можете встановити його через нього: ```shell composer require nette/robot-loader @@ -43,37 +46,37 @@ composer require nette/robot-loader Використання .[#toc-usage] -------------------------- -Подібно до того, як робот Google переглядає та індексує сайти, [RobotLoader |api:Nette\Loaders\RobotLoader] переглядає всі PHP-скрипти і записує, які класи та інтерфейси були в них знайдені. Потім ці записи зберігаються в кеші та використовуються під час усіх наступних запитів. Вам просто потрібно вказати, які каталоги індексувати і де зберігати кеш: +Подібно до того, як робот Google сканує та індексує веб-сторінки, [RobotLoader |api:Nette\Loaders\RobotLoader] переглядає всі PHP-скрипти і записує, які класи, інтерфейси, риси та зчислення він знайшов. Потім він зберігає результати в кеші для використання в наступних запитах. Вам лише потрібно вказати, через які каталоги він повинен пройти і де зберігати кеш: ```php $loader = new Nette\Loaders\RobotLoader; -// каталоги, які індексуватимуться RobotLoader (включно з підкаталогами) +// Каталоги для індексації RobotLoader (включаючи підкаталоги) $loader->addDirectory(__DIR__ . '/app'); $loader->addDirectory(__DIR__ . '/libs'); -// використовувати каталог 'temp' для кешу +// Встановити кешування для каталогу 'temp' $loader->setTempDirectory(__DIR__ . '/temp'); -$loader->register(); // Запустити RobotLoader +$loader->register(); // Активувати RobotLoader ``` -І це все. З цього моменту вам не потрібно використовувати `require`. Чудово, чи не так? +І все, з цього моменту нам не потрібно використовувати `require`. Чудово! -Коли RobotLoader стикається з дублюванням імені класу під час індексування, він викидає виняток і повідомляє вам про це. RobotLoader також автоматично оновлює кеш, коли йому потрібно завантажити невідомий йому клас. Ми рекомендуємо вимкнути це на виробничих серверах, див. [Кешування |#Кэширование]. +Якщо RobotLoader під час індексації зустріне повторюване ім'я класу, він згенерує виключення і повідомить вас про це. RobotLoader також автоматично оновлює кеш, коли йому потрібно завантажити невідомий клас. Ми рекомендуємо вимкнути цю функцію на виробничих серверах, див. [Кешування |#Caching]. -Якщо ви хочете, щоб RobotLoader пропускав деякі каталоги, використовуйте `$loader->excludeDirectory('temp')` (його можна викликати кілька разів або передати кілька каталогів). +Якщо ви хочете, щоб RobotLoader пропустив певні каталоги, використовуйте `$loader->excludeDirectory('temp')` (можна викликати кілька разів або передати кілька каталогів). -За замовчуванням RobotLoader повідомляє про помилки в PHP-файлах, кидаючи виняток `ParseError`. Його можна відключити за допомогою `$loader->reportParseErrors(false)`. +За замовчуванням RobotLoader повідомляє про помилки в PHP-файлах, генеруючи виключення `ParseError`. Це можна придушити за допомогою `$loader->reportParseErrors(false)`. Додаток Nette .[#toc-nette-application] --------------------------------------- -Усередині програми Nette, де `$configurator` використовується в `Bootstrap.php`, ви можете налаштувати RobotLoader таким чином: +Усередині Nette Application, де `$configurator` використовується в `Bootstrap.php`, ви можете налаштувати RobotLoader таким чином: ```php $configurator = new Nette\Bootstrap\Configurator; -// ... +//... $configurator->setTempDirectory(__DIR__ . '/../temp'); $configurator->createRobotLoader() ->addDirectory(__DIR__) @@ -82,30 +85,32 @@ $configurator->createRobotLoader() ``` -Аналізатор файлів PHP .[#toc-php-files-analyzer] +Аналізатор PHP файлів .[#toc-php-files-analyzer] ------------------------------------------------ -RobotLoader також можна використовувати суто для пошуку класів, інтерфейсів і трейтів у PHP-файлах **без** використання функції автозавантаження: +RobotLoader також можна використовувати суто для пошуку класів, інтерфейсів, трейтів та зчислень у PHP-файлах **без** використання функції автозавантаження: ```php $loader = new Nette\Loaders\RobotLoader; $loader->addDirectory(__DIR__ . '/app'); -// Сканує каталоги на наявність класів / інтерфейсів / трейтів +// Сканує каталоги на наявність класів/інтерфейсів/ознак/зчислень $loader->rebuild(); // Повертає масив пар клас => ім'я файлу $res = $loader->getIndexedClasses(); ``` -Навіть при такому використанні ви можете використовувати кеш. У результаті немодифіковані файли не будуть повторно аналізуватися при повторному скануванні: +Навіть при такому використанні ви можете використовувати кешування. Це гарантує, що незмінні файли не будуть скановані повторно: ```php $loader = new Nette\Loaders\RobotLoader; $loader->addDirectory(__DIR__ . '/app'); + +// Встановити кешування для каталогу 'temp' $loader->setTempDirectory(__DIR__ . '/temp'); -// Сканування каталогів із використанням кешу +// Сканує каталоги з використанням кешу $loader->refresh(); // Повертає масив пар клас => ім'я файлу @@ -116,23 +121,23 @@ $res = $loader->getIndexedClasses(); Кешування .[#toc-caching] ------------------------- -RobotLoader працює дуже швидко, тому що він розумно використовує кеш. +RobotLoader працює дуже швидко, тому що він розумно використовує кешування. -Розробляючи з ним, ви майже не помічаєте, що він працює у фоновому режимі. Він постійно оновлює кеш, оскільки знає, що класи та файли можуть бути створені, видалені, перейменовані тощо. І він не сканує повторно немодифіковані файли. +Під час розробки ви навряд чи помітите, що він працює у фоновому режимі. Він постійно оновлює свій кеш, враховуючи, що класи і файли можуть створюватися, видалятися, перейменовуватися тощо. І він не сканує незмінні файли. -При використанні на робочому сервері, з іншого боку, ми рекомендуємо відключити оновлення кешу за допомогою `$loader->setAutoRefresh(false)` (це робиться автоматично в додатку Nette), оскільки файли не змінюються. Водночас, необхідно **очистити кеш** під час завантаження нової версії на хостинг. +З іншого боку, на продуктивному сервері ми рекомендуємо вимкнути оновлення кешу за допомогою `$loader->setAutoRefresh(false)` (в Nette Application це відбувається автоматично), оскільки файли не змінюються. У той же час, необхідно **очищати кеш** при завантаженні нової версії на хостинг. -Звичайно, початкове сканування файлів, коли кеш ще не існує, може зайняти кілька секунд для великих додатків. RobotLoader має вбудований захист від "cache stampede":https://en.wikipedia.org/wiki/Cache_stampede. -Це ситуація, коли виробничий сервер отримує велику кількість одночасних запитів, і оскільки кеш RobotLoader ще не існує, всі вони почнуть сканувати файли. Це збільшує навантаження на процесор і файлову систему. -На щастя, RobotLoader працює таким чином, що за кількох одночасних запитів тільки перший потік індексує файли, створює кеш, решта чекають, а потім використовують кеш. +Початкове сканування файлів, коли кеш ще не існує, може зайняти деякий час для великих додатків. RobotLoader має вбудований захист від "переповнення кешу":https://en.wikipedia.org/wiki/Cache_stampede. +Це ситуація, коли велика кількість одночасних запитів на робочому сервері запускає RobotLoader, і оскільки кеш ще не існує, всі вони починають сканувати файли, що призводить до перевантаження сервера. +На щастя, RobotLoader працює таким чином, що тільки перший потік індексує файли, створює кеш, а решта чекають і потім використовують кеш. PSR-4 .[#toc-psr-4] ------------------- -Сьогодні Composer можна використовувати для [автозавантаження |best-practices:composer#Autoloading] відповідно до PSR-4. Простіше кажучи, це система, у якій простори імен та імена класів відповідають структурі каталогів та іменам файлів, тобто `App\Router\RouterFactory` знаходиться у файлі `/path/to/App/Router/RouterFactory.php`. +Сьогодні ви можете використовувати [Composer для автозавантаження |best-practices:composer#autoloading], дотримуючись PSR-4. Простіше кажучи, це система, де простори імен та імена класів відповідають структурі каталогів та іменам файлів, наприклад, `App\Router\RouterFactory` буде у файлі `/path/to/App/Router/RouterFactory.php`. -RobotLoader не прив'язаний до будь-якої фіксованої структури, тому він корисний у ситуаціях, коли вам не підходить структура каталогів, оформлена у вигляді просторів імен у PHP, або коли ви розробляєте застосунок, у якому історично не використовуються такі угоди. Також можна використовувати обидва завантажувачі разом. +RobotLoader не прив'язаний до будь-якої фіксованої структури, тому він корисний у ситуаціях, коли ви не хочете, щоб структура каталогів була розроблена точно так само, як простори імен PHP, або коли ви розробляєте програму, яка історично не використовує такі домовленості. Також можна використовувати обидва завантажувачі разом. {{leftbar: nette:@menu-topics}} From a5a95838522cae9aba0a3ca3633631af010f8013 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 1 Nov 2023 14:43:45 +0100 Subject: [PATCH 035/137] php-generator: improved EN translation --- php-generator/en/@home.texy | 238 ++++++++++++++++++------------------ 1 file changed, 119 insertions(+), 119 deletions(-) diff --git a/php-generator/en/@home.texy b/php-generator/en/@home.texy index 44181cbc5b..20de526afb 100644 --- a/php-generator/en/@home.texy +++ b/php-generator/en/@home.texy @@ -14,7 +14,7 @@ Are you looking for a tool to generate PHP code for classes, functions, or compl Installation ------------ -Download and install the package using [Composer|best-practices:composer]: +Download and install the library using the [Composer|best-practices:composer] tool: ```shell composer require nette/php-generator @@ -26,7 +26,7 @@ For PHP compatibility, see the [table |#Compatibility Table]. Classes ------- -Let's start with a straightforward example of generating class using [ClassType |api:Nette\PhpGenerator\ClassType]: +Let's start with an example of creating a class using [ClassType |api:Nette\PhpGenerator\ClassType]: ```php $class = new Nette\PhpGenerator\ClassType('Demo'); @@ -35,18 +35,18 @@ $class ->setFinal() ->setExtends(ParentClass::class) ->addImplement(Countable::class) - ->addComment("Description of class.\nSecond line\n") + ->addComment("Class description.\nSecond line\n") ->addComment('@property-read Nette\Forms\Form $form'); -// to generate PHP code simply cast to string or use echo: +// generate code simply by typecasting to string or using echo: echo $class; ``` -It will render this result: +This will return: ```php /** - * Description of class. + * Class description * Second line * * @property-read Nette\Forms\Form $form @@ -56,18 +56,18 @@ final class Demo extends ParentClass implements Countable } ``` -We can also use a printer to generate the code, which, unlike `echo $class`, we will be able to [further configure |#Printers and PSR compliance]: +To generate the code, you can also use a so-called printer, which, unlike `echo $class`, can be [further configured |#Printer and PSR compliance]: ```php $printer = new Nette\PhpGenerator\Printer; echo $printer->printClass($class); ``` -We can add constants (class [Constant |api:Nette\PhpGenerator\Constant]) and properties (class [Property |api:Nette\PhpGenerator\Property]): +You can add constants (class [Constant |api:Nette\PhpGenerator\Constant]) and properties (class [Property |api:Nette\PhpGenerator\Property]): ```php $class->addConstant('ID', 123) - ->setProtected() // constant visiblity + ->setProtected() // constant visibility ->setType('int') ->setFinal(); @@ -78,10 +78,10 @@ $class->addProperty('items', [1, 2, 3]) $class->addProperty('list') ->setType('?array') - ->setInitialized(); // prints '= null' + ->setInitialized(); // outputs '= null' ``` -It generates: +This will generate: ```php final protected const int ID = 123; @@ -92,14 +92,14 @@ private static $items = [1, 2, 3]; public ?array $list = null; ``` -And we can add [methods|#Method and Function Signature]: +And you can add [methods|#Method and function signatures]: ```php $method = $class->addMethod('count') ->addComment('Count it.') ->setFinal() ->setProtected() - ->setReturnType('?int') // method return type + ->setReturnType('?int') // return types for methods ->setBody('return count($items ?: $this->items);'); $method->addParameter('items', []) // $items = [] @@ -107,7 +107,7 @@ $method->addParameter('items', []) // $items = [] ->setType('array'); // array &$items = [] ``` -It results in: +The result is: ```php /** @@ -119,7 +119,7 @@ final protected function count(array &$items = []): ?int } ``` -Promoted parameters introduced by PHP 8.0 can be passed to the constructor: +Promoted parameters introduced in PHP 8.0 can be passed to the constructor: ```php $method = $class->addMethod('__construct'); @@ -128,7 +128,7 @@ $method->addPromotedParameter('args', []) ->setPrivate(); ``` -It results in: +The result is: ```php public function __construct( @@ -138,15 +138,15 @@ public function __construct( } ``` -Readonly properties and classes can be marked via `setReadOnly()`. +Readonly properties and classes be marked using the `setReadOnly()` function. ------ -If the added property, constant, method or parameter already exist, it throws exception. +If an added property, constant, method, or parameter already exists, an exception is thrown. -Members can be removed using `removeProperty()`, `removeConstant()`, `removeMethod()` or `removeParameter()`. +Class members can be removed using `removeProperty()`, `removeConstant()`, `removeMethod()`, or `removeParameter()`. -You can also add existing `Method`, `Property` or `Constant` objects to the class: +You can also add existing `Method`, `Property`, or `Constant` objects to the class: ```php $method = new Nette\PhpGenerator\Method('getHandle'); @@ -159,7 +159,7 @@ $class = (new Nette\PhpGenerator\ClassType('Demo')) ->addMember($const); ``` -You can clone existing methods, properties and constants with a different name using `cloneWithName()`: +You can also clone existing methods, properties, and constants under a different name using `cloneWithName()`: ```php $methodCount = $class->getMethod('count'); @@ -168,8 +168,8 @@ $class->addMember($methodRecount); ``` -Interface or Trait ------------------- +Interfaces or Traits +-------------------- You can create interfaces and traits (classes [InterfaceType |api:Nette\PhpGenerator\InterfaceType] and [TraitType |api:Nette\PhpGenerator\TraitType]): @@ -178,7 +178,7 @@ $interface = new Nette\PhpGenerator\InterfaceType('MyInterface'); $trait = new Nette\PhpGenerator\TraitType('MyTrait'); ``` -Using traits: +Using a trait: ```php $class = new Nette\PhpGenerator\ClassType('Demo'); @@ -189,7 +189,7 @@ $class->addTrait('MyTrait') echo $class; ``` -Result: +The result is: ```php class Demo @@ -206,7 +206,7 @@ class Demo Enums ----- -You can easily create the enums that PHP 8.1 brings (class [EnumType |api:Nette\PhpGenerator\EnumType]): +You can easily create enums introduced in PHP 8.1 like this (class [EnumType |api:Nette\PhpGenerator\EnumType]): ```php $enum = new Nette\PhpGenerator\EnumType('Suit'); @@ -218,7 +218,7 @@ $enum->addCase('Spades'); echo $enum; ``` -Result: +The result is: ```php enum Suit @@ -230,20 +230,20 @@ enum Suit } ``` -You can also define scalar equivalents for cases to create a backed enum: +You can also define scalar equivalents and create a "backed" enum: ```php $enum->addCase('Clubs', '♣'); $enum->addCase('Diamonds', '♦'); ``` -It is possible to add a comment or [#attributes] to each case using `addComment()` or `addAttribute()`. +For each *case*, you can add a comment or [#attributes] using `addComment()` or `addAttribute()`. -Anonymous Class ---------------- +Anonymous Classes +----------------- -Give `null` as the name and you have an anonymous class: +Pass `null` as the name, and you have an anonymous class: ```php $class = new Nette\PhpGenerator\ClassType(null); @@ -253,7 +253,7 @@ $class->addMethod('__construct') echo '$obj = new class ($val) ' . $class . ';'; ``` -Result: +The result is: ```php $obj = new class ($val) { @@ -265,10 +265,10 @@ $obj = new class ($val) { ``` -Global Function ---------------- +Global Functions +---------------- -Code of functions will generate class [GlobalFunction |api:Nette\PhpGenerator\GlobalFunction]: +The code for functions is generated by the class [GlobalFunction |api:Nette\PhpGenerator\GlobalFunction]: ```php $function = new Nette\PhpGenerator\GlobalFunction('foo'); @@ -277,11 +277,11 @@ $function->addParameter('a'); $function->addParameter('b'); echo $function; -// or use PsrPrinter for output conforming to PSR-2 / PSR-12 / PER +// or use the PsrPrinter for output compliant with PSR-2 / PSR-12 / PER // echo (new Nette\PhpGenerator\PsrPrinter)->printFunction($function); ``` -Result: +The result is: ```php function foo($a, $b) @@ -291,10 +291,10 @@ function foo($a, $b) ``` -Closure -------- +Anonymous Functions +------------------- -Code of closures will generate class [Closure |api:Nette\PhpGenerator\Closure]: +The code for anonymous functions is generated by the class [Closure |api:Nette\PhpGenerator\Closure]: ```php $closure = new Nette\PhpGenerator\Closure; @@ -305,11 +305,11 @@ $closure->addUse('c') ->setReference(); echo $closure; -// or use PsrPrinter for output conforming to PSR-2 / PSR-12 / PER +// or use the PsrPrinter for output compliant with PSR-2 / PSR-12 / PER // echo (new Nette\PhpGenerator\PsrPrinter)->printClosure($closure); ``` -Result: +The result is: ```php function ($a, $b) use (&$c) { @@ -318,10 +318,10 @@ function ($a, $b) use (&$c) { ``` -Arrow Function --------------- +Short Arrow Functions +--------------------- -You can also print closure as arrow function using printer: +You can also output a short anonymous function using the printer: ```php $closure = new Nette\PhpGenerator\Closure; @@ -332,17 +332,17 @@ $closure->addParameter('b'); echo (new Nette\PhpGenerator\Printer)->printArrowFunction($closure); ``` -Result: +The result is: ```php fn($a, $b) => $a + $b ``` -Method and Function Signature ------------------------------ +Method and Function Signatures +------------------------------ -Methods are represented by the class [Method |api:Nette\PhpGenerator\Method]. You can set visibility, return value, add comments, [attributes|#Attributes] etc: +Methods are represented by the class [Method |api:Nette\PhpGenerator\Method]. You can set visibility, return value, add comments, [attributes|#Attributes], etc.: ```php $method = $class->addMethod('count') @@ -352,12 +352,12 @@ $method = $class->addMethod('count') ->setReturnType('?int'); ``` -Each parameter is represented by a class [Parameter |api:Nette\PhpGenerator\Parameter]. Again, you can set every conceivable property: +Individual parameters are represented by the class [Parameter |api:Nette\PhpGenerator\Parameter]. Again, you can set all conceivable properties: ```php $method->addParameter('items', []) // $items = [] - ->setReference() // &$items = [] - ->setType('array'); // array &$items = [] + ->setReference() // &$items = [] + ->setType('array'); // array &$items = [] // function count(&$items = []) ``` @@ -370,7 +370,7 @@ $method->setVariadics(true); $method->addParameter('items'); ``` -Generates: +This generates: ```php function count(...$items) @@ -379,10 +379,10 @@ function count(...$items) ``` -Method and Function Body ------------------------- +Method and Function Bodies +-------------------------- -The body can be passed to the `setBody()` method at once or sequentially (line by line) by repeatedly calling `addBody()`: +The body can be passed all at once to the `setBody()` method or gradually (line by line) by repeatedly calling `addBody()`: ```php $function = new Nette\PhpGenerator\GlobalFunction('foo'); @@ -391,7 +391,7 @@ $function->addBody('return $a;'); echo $function; ``` -Result +The result is: ```php function foo() @@ -401,7 +401,7 @@ function foo() } ``` -You can use special placeholders for handy way to inject variables. +You can use special placeholders for easy variable insertion. Simple placeholders `?` @@ -413,7 +413,7 @@ $function->addBody('return substr(?, ?);', [$str, $num]); echo $function; ``` -Result: +The result is: ```php function foo() @@ -422,7 +422,7 @@ function foo() } ``` -Variadic placeholder `...?` +Placeholder for variadic `...?` ```php $items = [1, 2, 3]; @@ -431,7 +431,7 @@ $function->setBody('myfunc(...?);', [$items]); echo $function; ``` -Result: +The result is: ```php function foo() @@ -440,7 +440,7 @@ function foo() } ``` -You can also use PHP 8 named parameters using placeholder `...?:` +You can also use named parameters for PHP 8 with `...?:` ```php $items = ['foo' => 1, 'bar' => true]; @@ -449,7 +449,7 @@ $function->setBody('myfunc(...?:);', [$items]); // myfunc(foo: 1, bar: true); ``` -Escape placeholder using slash `\?` +The placeholder is escaped with a backslash `\?` ```php $num = 3; @@ -459,7 +459,7 @@ $function->addBody('return $a \? 10 : ?;', [$num]); echo $function; ``` -Result: +The result is: ```php function foo($a) @@ -469,10 +469,10 @@ function foo($a) ``` -Printers and PSR Compliance ---------------------------- +Printer and PSR Compliance +-------------------------- -The [Printer |api:Nette\PhpGenerator\Printer] class is used to generate PHP code: +The [Printer |api:Nette\PhpGenerator\Printer] class is used for generating PHP code: ```php $class = new Nette\PhpGenerator\ClassType('Demo'); @@ -482,16 +482,16 @@ $printer = new Nette\PhpGenerator\Printer; echo $printer->printClass($class); // same as: echo $class ``` -It can generate code for all other elements, offering methods such as `printFunction()`, `printNamespace()`, etc. +It can generate code for all other elements, offering methods like `printFunction()`, `printNamespace()`, etc. -Additionally, the `PsrPrinter` class is available, whose output is in compliance with the PSR-2 / PSR-12 / PER coding style: +There's also the `PsrPrinter` class, which outputs in accordance with PSR-2 / PSR-12 / PER coding style: ```php $printer = new Nette\PhpGenerator\PsrPrinter; echo $printer->printClass($class); ``` -Need to fine-tune behavior to your needs? Create your own printer by inheriting from the `Printer` class. You can reconfigure these variables: +Need custom behavior? Create your own version by inheriting the `Printer` class. You can reconfigure these variables: ```php class MyPrinter extends Nette\PhpGenerator\Printer @@ -504,11 +504,11 @@ class MyPrinter extends Nette\PhpGenerator\Printer public int $linesBetweenProperties = 0; // number of blank lines between methods public int $linesBetweenMethods = 2; - // number of blank lines between groups of use statements for classes, functions, and constants + // number of blank lines between 'use statements' groups for classes, functions, and constants public int $linesBetweenUseTypes = 0; - // position of the opening brace for functions and methods + // position of the opening curly brace for functions and methods public bool $bracesOnNextLine = true; - // place one parameter in one line, even if it has an attribute or is promoted + // place one parameter on one line, even if it has an attribute or is supported public bool $singleParameterOnOneLine = false; // omits namespaces that do not contain any class or function public bool $omitEmptyNamespaces = true; @@ -517,17 +517,17 @@ class MyPrinter extends Nette\PhpGenerator\Printer } ``` -How and why exactly does the standard `Printer` and `PsrPrinter` differ? Why isn't there just one printer, the `PsrPrinter`, in the package? +How and why does the standard `Printer` differ from `PsrPrinter`? Why isn't there just one printer, the `PsrPrinter`, in the package? -The standard `Printer` formats the code as we do it in all of Nette. Since Nette was created much earlier than PSR, and also because PSR for many years did not deliver standards in time, but sometimes even with several years of delay from the introduction of a new feature in PHP, this resulted in a few minor differences in the [coding standard |contributing:coding-standard]. -The bigger difference is just the use of tabs instead of spaces. We know that by using tabs in our projects we allow for width adjustment, which is [essential for people with visual impairments |contributing:coding-standard#Tabs Instead of Spaces]. -An example of a minor difference is the placement of the curly brace on a separate line for functions and methods and always. We see the PSR recommendation as illogical and [leading to a decrease in code clarity |contributing:coding-standard#Wrapping and Braces]. +The standard `Printer` formats the code as we do throughout Nette. Since Nette was established much earlier than PSR, and also because PSR took years to deliver standards on time, sometimes even several years after introducing a new feature in PHP, it resulted in a [coding standard |contributing:coding-standard] that differs in a few minor aspects. +The major difference is the use of tabs instead of spaces. We know that by using tabs in our projects, we allow for width customization, which is essential for [people with visual impairments |contributing:coding-standard#tabs-instead-of-spaces]. +An example of a minor difference is placing the curly brace on a separate line for functions and methods, always. The PSR recommendation seems illogical to us and leads to [reduced code clarity |contributing:coding-standard#Wrapping and Braces]. Types ----- -Each type or union/intersection type can be passed as a string, you can also use predefined constants for native types: +Every type or union/intersection type can be passed as a string; you can also use predefined constants for native types: ```php use Nette\PhpGenerator\Type; @@ -536,16 +536,16 @@ $member->setType('array'); // or Type::Array; $member->setType('?array'); // or Type::nullable(Type::Array); $member->setType('array|string'); // or Type::union(Type::Array, Type::String) $member->setType('Foo&Bar'); // or Type::intersection(Foo::class, Bar::class) -$member->setType(null); // removes type +$member->setType(null); // removes the type ``` -The same applies to the method `setReturnType()`. +The same applies to the `setReturnType()` method. Literals -------- -With `Literal` you can pass arbitrary PHP code to, for example, default property or parameter values etc: +Using `Literal`, you can pass any PHP code, for example, for default property values or parameters, etc: ```php use Nette\PhpGenerator\Literal; @@ -573,25 +573,25 @@ class Demo } ``` -You can also pass parameters to `Literal` and have it formatted into valid PHP code using [special placeholders|#method-and-function-body-generator]: +You can also pass parameters to `Literal` and have them formatted into valid PHP code using [placeholders|#Method and function bodies]: ```php new Literal('substr(?, ?)', [$a, $b]); -// generates, for example: substr('hello', 5); +// generates for example: substr('hello', 5); ``` -The literal representing the creation of a new object is easily generated by the `new` method: +A literal representing the creation of a new object can easily be generated using the `new` method: ```php Literal::new(Demo::class, [$a, 'foo' => $b]); -// generates, for example: new Demo(10, foo: 20) +// generates for example: new Demo(10, foo: 20) ``` Attributes ---------- -You can add PHP 8 attributes to all classes, methods, properties, constants, enum cases, functions, closures and parameters. [#Literals] can also be used as parameter values. +With PHP 8, you can add attributes to all classes, methods, properties, constants, enum cases, functions, closures, and parameters. You can also use [#literals] as parameter values. ```php $class = new Nette\PhpGenerator\ClassType('Demo'); @@ -637,7 +637,7 @@ class Demo Namespace --------- -Classes, traits, interfaces and enums (hereinafter classes) can be grouped into namespaces ([PhpNamespace |api:Nette\PhpGenerator\PhpNamespace]): +Classes, traits, interfaces, and enums (hereafter referred to as classes) can be grouped into namespaces represented by the [PhpNamespace |api:Nette\PhpGenerator\PhpNamespace] class: ```php $namespace = new Nette\PhpGenerator\PhpNamespace('Foo'); @@ -652,9 +652,9 @@ $class = new Nette\PhpGenerator\ClassType('Task'); $namespace->add($class); ``` -If the class already exists, it throws exception. +If the class already exists, an exception is thrown. -You can define use-statements: +You can define use clauses: ```php // use Http\Request; @@ -665,14 +665,14 @@ $namespace->addUse(Http\Request::class, 'HttpReq'); $namespace->addUseFunction('iter\range'); ``` -To simplify a fully qualified class, function or constant name according to the defined aliases, use the `simplifyName` method: +To simplify a fully qualified class, function, or constant name based on defined aliases, use the `simplifyName` method: ```php -echo $namespace->simplifyName('Foo\Bar'); // 'Bar', because 'Foo' is current namespace -echo $namespace->simplifyName('iter\range', $namespace::NameFunction); // 'range', because of the defined use-statement +echo $namespace->simplifyName('Foo\Bar'); // 'Bar', because 'Foo' is the current namespace +echo $namespace->simplifyName('iter\range', $namespace::NameFunction); // 'range', due to the defined use-statement ``` -Conversely, you can convert a simplified class, function or constant name to a fully qualified one using the `resolveName` method: +Conversely, you can convert a simplified class, function, or constant name back to a fully qualified name using the `resolveName` method: ```php echo $namespace->resolveName('Bar'); // 'Foo\Bar' @@ -691,17 +691,17 @@ $namespace = new Nette\PhpGenerator\PhpNamespace('Foo'); $namespace->addUse('Bar\AliasedClass'); $class = $namespace->addClass('Demo'); -$class->addImplement('Foo\A') // it will simplify to A - ->addTrait('Bar\AliasedClass'); // it will simplify to AliasedClass +$class->addImplement('Foo\A') // will be simplified to A + ->addTrait('Bar\AliasedClass'); // will be simplified to AliasedClass $method = $class->addMethod('method'); -$method->addComment('@return ' . $namespace->simplifyType('Foo\D')); // in comments simplify manually +$method->addComment('@return ' . $namespace->simplifyType('Foo\D')); // we manually simplify in comments $method->addParameter('arg') - ->setType('Bar\OtherClass'); // it will resolve to \Bar\OtherClass + ->setType('Bar\OtherClass'); // will be translated to \Bar\OtherClass echo $namespace; -// or use PsrPrinter for output conforming to PSR-2 / PSR-12 / PER +// or use the PsrPrinter for output in accordance with PSR-2 / PSR-12 / PER // echo (new Nette\PhpGenerator\PsrPrinter)->printNamespace($namespace); ``` @@ -737,7 +737,7 @@ echo $printer->printNamespace($namespace); PHP Files --------- -Classes, functions and namespaces can be grouped into PHP files represented by the class [PhpFile|api:Nette\PhpGenerator\PhpFile]: +Classes, functions, and namespaces can be grouped into PHP files represented by the [PhpFile|api:Nette\PhpGenerator\PhpFile] class: ```php $file = new Nette\PhpGenerator\PhpFile; @@ -754,7 +754,7 @@ $function = $file->addFunction('Foo\foo'); echo $file; -// or use PsrPrinter for output conforming to PSR-2 / PSR-12 / PER +// or use the PsrPrinter for output in accordance with PSR-2 / PSR-12 / PER // echo (new Nette\PhpGenerator\PsrPrinter)->printFile($file); ``` @@ -783,8 +783,8 @@ function foo() **Please note:** No additional code can be added to the files outside of functions and classes. -Generating According to Existing Ones -------------------------------------- +Generating from Existing Ones +----------------------------- In addition to being able to model classes and functions using the API described above, you can also have them automatically generated using existing ones: @@ -792,17 +792,17 @@ In addition to being able to model classes and functions using the API described // creates a class identical to the PDO class $class = Nette\PhpGenerator\ClassType::from(PDO::class); -// creates a function identical to trim() +// creates a function identical to the trim() function $function = Nette\PhpGenerator\GlobalFunction::from('trim'); -// creates a closure as specified +// creates a closure based on the provided one $closure = Nette\PhpGenerator\Closure::from( function (stdClass $a, $b = null) {}, ); ``` -Function and method bodies are empty by default. If you want to load them as well, use this way -(it requires `nikic/php-parser` to be installed): +By default, function and method bodies are empty. If you also want to load them, use this method +(requires the `nikic/php-parser` package to be installed): ```php $class = Nette\PhpGenerator\ClassType::from(Foo::class, withBodies: true); @@ -811,10 +811,10 @@ $function = Nette\PhpGenerator\GlobalFunction::from('foo', withBody: true); ``` -Loading from PHP File ---------------------- +Loading from PHP Files +---------------------- -You can also load functions, classes, interfaces and enums directly from a string of PHP code. For example, we create `ClassType` object this way: +You can also load functions, classes, interfaces, and enums directly from a string containing PHP code. For example, to create a `ClassType` object: ```php $class = Nette\PhpGenerator\ClassType::fromCode(<<dump($var); // prints ['a', 'b', 123] +echo $dumper->dump($var); // outputs ['a', 'b', 123] ``` Compatibility Table ------------------- -PhpGenerator 4.0 and 4.1 are compatible with PHP 8.0 to 8.3 +PhpGenerator 4.0 and 4.1 are compatible with PHP 8.0 to 8.3. {{leftbar: nette:@menu-topics}} From fb2b197b510fff4828585144b2a840be6aef34ca Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 9 Nov 2023 13:02:44 +0100 Subject: [PATCH 036/137] latte 3.0.12 --- latte/bg/creating-extension.texy | 22 ++++++++++++++++-- latte/bg/tags.texy | 15 ++++++++++++ latte/cs/cookbook/migration-from-latte2.texy | 20 ++++++++++++++++ latte/cs/creating-extension.texy | 24 +++++++++++++++++--- latte/cs/tags.texy | 17 +++++++++++++- latte/de/creating-extension.texy | 22 ++++++++++++++++-- latte/de/tags.texy | 15 ++++++++++++ latte/el/creating-extension.texy | 22 ++++++++++++++++-- latte/el/tags.texy | 15 ++++++++++++ latte/en/cookbook/migration-from-latte2.texy | 20 ++++++++++++++++ latte/en/creating-extension.texy | 22 ++++++++++++++++-- latte/en/tags.texy | 17 +++++++++++++- latte/es/creating-extension.texy | 22 ++++++++++++++++-- latte/es/tags.texy | 15 ++++++++++++ latte/fr/creating-extension.texy | 22 ++++++++++++++++-- latte/fr/tags.texy | 15 ++++++++++++ latte/hu/creating-extension.texy | 22 ++++++++++++++++-- latte/hu/tags.texy | 15 ++++++++++++ latte/it/creating-extension.texy | 22 ++++++++++++++++-- latte/it/tags.texy | 15 ++++++++++++ latte/ja/creating-extension.texy | 22 ++++++++++++++++-- latte/ja/tags.texy | 15 ++++++++++++ latte/pl/creating-extension.texy | 22 ++++++++++++++++-- latte/pl/tags.texy | 15 ++++++++++++ latte/pt/creating-extension.texy | 22 ++++++++++++++++-- latte/pt/tags.texy | 15 ++++++++++++ latte/ro/creating-extension.texy | 22 ++++++++++++++++-- latte/ro/tags.texy | 15 ++++++++++++ latte/ru/creating-extension.texy | 22 ++++++++++++++++-- latte/ru/tags.texy | 15 ++++++++++++ latte/sl/creating-extension.texy | 22 ++++++++++++++++-- latte/sl/tags.texy | 15 ++++++++++++ latte/tr/creating-extension.texy | 22 ++++++++++++++++-- latte/tr/tags.texy | 15 ++++++++++++ latte/uk/creating-extension.texy | 22 ++++++++++++++++-- latte/uk/tags.texy | 15 ++++++++++++ 36 files changed, 638 insertions(+), 37 deletions(-) diff --git a/latte/bg/creating-extension.texy b/latte/bg/creating-extension.texy index f9cdb80533..3091394103 100644 --- a/latte/bg/creating-extension.texy +++ b/latte/bg/creating-extension.texy @@ -307,7 +307,7 @@ class ForeachNode extends StatementNode // функция за парсиране, която засега просто създава възел public static function create(Latte\Compiler\Tag $tag): self { - $node = new self; + $node = $tag->node = new self; return $node; } @@ -359,7 +359,7 @@ class ForeachNode extends StatementNode public static function create(Latte\Compiler\Tag $tag): self { $tag->expectArguments(); - $node = new self; + $node = $tag->node = new self; $node->expression = $tag->parser->parseExpression(); $tag->parser->stream->consume('as'); $node->value = $parser->parseExpression(); @@ -486,6 +486,24 @@ public function &getIterator(): \Generator ``` +AuxiliaryNode +------------- + +Ако създавате нов таг за Latte, препоръчително е да създадете за него специален клас възел, който ще го представя в дървото AST (вж. класа `ForeachNode` в примера по-горе). В някои случаи може да ви бъде полезен тривиалният помощен клас [AuxiliaryNode |api:Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode], който ви позволява да предадете тялото на метода `print()` и списъка на възлите, направени достъпни от метода `getIterator()`, като параметри на конструктора: + +```php +// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode +// or Latte\Compiler\Nodes\AuxiliaryNode + +$node = new AuxiliaryNode( + // body of the print() method: + fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode), + // nodes accessed via getIterator() and also passed into the print() method: + [$argNode], +); +``` + + Компилаторът предава .[#toc-compiler-passes] ============================================ diff --git a/latte/bg/tags.texy b/latte/bg/tags.texy index 2d53f63639..582f645e22 100644 --- a/latte/bg/tags.texy +++ b/latte/bg/tags.texy @@ -16,6 +16,7 @@ | `{ifset}`... `{elseifset}`... `{/ifset}` | [условие ifset |#ifset-elseifset] | `{ifchanged}`... `{/ifchanged}` | [проверка за промени |#ifchanged] | `{switch}` `{case}` `{default}` `{/switch}` | [състояние на превключване |#switch-case-default] +| `n:else` | [алтернативно съдържание за условията |#n:else] .[table-latte-tags language-latte] |## Цикли @@ -246,6 +247,20 @@ Age: {date('Y') - $birth}
    Страхотно. +`n:else` .{data-version:3.0.11} +------------------------------- + +Ако запишете условието `{if} ... {/if}` под формата на [n:атрибут |syntax#n:attributes], имате възможност да посочите алтернативен клон, като използвате `n:else`: + +```latte +In stock {$count} items + +not available +``` + +Атрибутът `n:else` може да се използва и в комбинация с [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent], и [`n:ifchanged` |#ifchanged]. + + `{/if $cond}` ------------- diff --git a/latte/cs/cookbook/migration-from-latte2.texy b/latte/cs/cookbook/migration-from-latte2.texy index f14c9f90e7..bd8cfc0352 100644 --- a/latte/cs/cookbook/migration-from-latte2.texy +++ b/latte/cs/cookbook/migration-from-latte2.texy @@ -128,6 +128,26 @@ $latte->addExtension(new Nette\Bridges\CacheLatte\CacheExtension($cacheStorage)) ``` +Tracy +----- + +Panel pro Tracy se nyní aktivuje také jako rozšíření. + +Starý kód pro Latte 2: + +```php +$latte = new Latte\Engine; +Latte\Bridges\Tracy\LattePanel::initialize($latte); +``` + +Nový kód pro Latte 3: + +```php +$latte = new Latte\Engine; +$latte->addExtension(new Latte\Bridges\Tracy\TracyExtension); +``` + + Překlady -------- diff --git a/latte/cs/creating-extension.texy b/latte/cs/creating-extension.texy index 26b2b0b3bb..24ff44bc2a 100644 --- a/latte/cs/creating-extension.texy +++ b/latte/cs/creating-extension.texy @@ -307,7 +307,7 @@ class ForeachNode extends StatementNode // parsovací funkce, která zatím pouze vytváří uzel public static function create(Latte\Compiler\Tag $tag): self { - $node = new self; + $node = $tag->node = new self; return $node; } @@ -359,7 +359,7 @@ class ForeachNode extends StatementNode public static function create(Latte\Compiler\Tag $tag): self { $tag->expectArguments(); - $node = new self; + $node = $tag->node = new self; $node->expression = $tag->parser->parseExpression(); $tag->parser->stream->consume('as'); $node->value = $parser->parseExpression(); @@ -406,7 +406,7 @@ public static function create(Latte\Compiler\Tag $tag): \Generator } ``` -Vrácením uzlu je parsování tagu dokončeno. +Vrácením uzlu `$node` je parsování tagu dokončeno. Generování PHP kódu @@ -486,6 +486,24 @@ public function &getIterator(): \Generator ``` +AuxiliaryNode +------------- + +Pokud vytváříte nový tag pro Latte, je žádoucí, abyste pro něj vytvořili vlastní třídu uzlu, která jej bude reprezentovat v AST stromu (viz třída `ForeachNode` v příkladu výše). V některých případech se vám může hodit pomocná triviální třída uzlu [AuxiliaryNode|api:Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode], které tělo metody `print()` a seznam uzlů, které zpřístupňuje metoda `getIterator()`, předáme jako parametry konstruktoru: + +```php +// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode +// or Latte\Compiler\Nodes\AuxiliaryNode + +$node = new AuxiliaryNode( + // tělo metody print(): + fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode), + // uzly zpřístupnění přes getIterator() a také předané do metody print(): + [$argNode], +); +``` + + Průchody kompilátoru ==================== diff --git a/latte/cs/tags.texy b/latte/cs/tags.texy index 1f075e08d8..49b008f6a3 100644 --- a/latte/cs/tags.texy +++ b/latte/cs/tags.texy @@ -16,6 +16,7 @@ Přehled a popis všech tagů (neboli značek či maker) šablonovacího systém | `{ifset}` … `{elseifset}` … `{/ifset}` | [podmínka ifset|#ifset-elseifset] | `{ifchanged}` … `{/ifchanged}` | [test jestli došlo ke změně |#ifchanged] | `{switch}` `{case}` `{default}` `{/switch}` | [podmínka switch|#switch-case-default] +| `n:else` | [alternativní obsah pro podmínky |#n:else] .[table-latte-tags language-latte] |## Cykly @@ -89,7 +90,7 @@ Přehled a popis všech tagů (neboli značek či maker) šablonovacího systém | `n:class` | [dynamický zápis HTML atributu class |#n:class] | `n:attr` | [dynamický zápis jakýchkoliv HTML atributů |#n:attr] | `n:tag` | [dynamický zápis jména HTML elementu |#n:tag] -| `n:ifcontent` | [Vynechá prázdný HTML tag |#n:ifcontent] +| `n:ifcontent` | [vynechá prázdný HTML tag |#n:ifcontent] .[table-latte-tags language-latte] |## Dostupné pouze v Nette Frameworku @@ -246,6 +247,20 @@ Víte, že k n:atributům můžete připojit prefix `tag-`? Pak se bude podmínk Boží. +`n:else` .{data-version:3.0.11} +------------------------------- + +Pokud podmínku `{if} ... {/if}` zapíšete v podobě [n:attributu|syntax#n:atributy], máte možnost uvést i alternativní větev pomocí `n:else`: + +```latte +Skladem {$count} kusů + +není dostupné +``` + +Atribut `n:else` použít také ve dvojici s [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent] a [`n:ifchanged` |#ifchanged]. + + `{/if $cond}` ------------- diff --git a/latte/de/creating-extension.texy b/latte/de/creating-extension.texy index feb6f1c164..a679750994 100644 --- a/latte/de/creating-extension.texy +++ b/latte/de/creating-extension.texy @@ -307,7 +307,7 @@ class ForeachNode extends StatementNode // eine Parsing-Funktion, die vorerst nur einen Knoten erstellt public static function create(Latte\Compiler\Tag $tag): self { - $node = new self; + $node = $tag->node = new self; return $node; } @@ -359,7 +359,7 @@ class ForeachNode extends StatementNode public static function create(Latte\Compiler\Tag $tag): self { $tag->expectArguments(); - $node = new self; + $node = $tag->node = new self; $node->expression = $tag->parser->parseExpression(); $tag->parser->stream->consume('as'); $node->value = $parser->parseExpression(); @@ -486,6 +486,24 @@ public function &getIterator(): \Generator ``` +AuxiliaryNode +------------- + +Wenn Sie ein neues Tag für Latte erstellen, ist es ratsam, eine eigene Knotenklasse dafür zu erstellen, die es im AST-Baum repräsentiert (siehe die Klasse `ForeachNode` im obigen Beispiel). In einigen Fällen kann die triviale Hilfsknotenklasse [AuxiliaryNode |api:Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode] nützlich sein, die es Ihnen ermöglicht, den Körper der Methode `print()` und die Liste der Knoten, die durch die Methode `getIterator()` zugänglich gemacht werden, als Konstruktorparameter zu übergeben: + +```php +// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode +// or Latte\Compiler\Nodes\AuxiliaryNode + +$node = new AuxiliaryNode( + // body of the print() method: + fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode), + // nodes accessed via getIterator() and also passed into the print() method: + [$argNode], +); +``` + + Compiler übergibt .[#toc-compiler-passes] ========================================= diff --git a/latte/de/tags.texy b/latte/de/tags.texy index b816bb1e31..a1073621f7 100644 --- a/latte/de/tags.texy +++ b/latte/de/tags.texy @@ -16,6 +16,7 @@ Zusammenfassung und Beschreibung aller in Latte integrierten Tags. | `{ifset}`... `{elseifset}`... `{/ifset}` | [Bedingung ifset |#ifset-elseifset] | `{ifchanged}`... `{/ifchanged}` | [Test, ob eine Änderung stattgefunden hat |#ifchanged] | `{switch}` `{case}` `{default}` `{/switch}` | [Bedingung switch |#switch-case-default] +| `n:else` | [alternative Inhalte für Bedingungen |#n:else] .[table-latte-tags language-latte] |## Schleifen @@ -246,6 +247,20 @@ Wussten Sie, dass Sie das Präfix `tag-` zu n:Attributen hinzufügen können? Da Schön. +`n:else` .{data-version:3.0.11} +------------------------------- + +Wenn Sie die Bedingung `{if} ... {/if}` in Form eines [n:-Attributs |syntax#n:attributes] schreiben, haben Sie die Möglichkeit, mit `n:else` eine alternative Verzweigung anzugeben: + +```latte +In stock {$count} items + +not available +``` + +Das Attribut `n:else` kann auch in Verbindung mit [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent], und [`n:ifchanged` |#ifchanged]. + + `{/if $cond}` ------------- diff --git a/latte/el/creating-extension.texy b/latte/el/creating-extension.texy index 2c38209526..b26c254ea3 100644 --- a/latte/el/creating-extension.texy +++ b/latte/el/creating-extension.texy @@ -307,7 +307,7 @@ class ForeachNode extends StatementNode // μια συνάρτηση ανάλυσης που απλά δημιουργεί έναν κόμβο προς το παρόν public static function create(Latte\Compiler\Tag $tag): self { - $node = new self; + $node = $tag->node = new self; return $node; } @@ -359,7 +359,7 @@ class ForeachNode extends StatementNode public static function create(Latte\Compiler\Tag $tag): self { $tag->expectArguments(); - $node = new self; + $node = $tag->node = new self; $node->expression = $tag->parser->parseExpression(); $tag->parser->stream->consume('as'); $node->value = $parser->parseExpression(); @@ -486,6 +486,24 @@ public function &getIterator(): \Generator ``` +AuxiliaryNode +------------- + +Εάν δημιουργείτε μια νέα ετικέτα για το Latte, είναι σκόπιμο να δημιουργήσετε μια ειδική κλάση κόμβου για αυτήν, η οποία θα την αντιπροσωπεύει στο δέντρο AST (βλέπε την κλάση `ForeachNode` στο παραπάνω παράδειγμα). Σε ορισμένες περιπτώσεις, μπορεί να βρείτε χρήσιμη την τετριμμένη βοηθητική κλάση κόμβου [AuxiliaryNode |api:Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode], η οποία σας επιτρέπει να περάσετε το σώμα της μεθόδου `print()` και τη λίστα των κόμβων που γίνονται προσβάσιμοι από τη μέθοδο `getIterator()` ως παραμέτρους του κατασκευαστή: + +```php +// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode +// or Latte\Compiler\Nodes\AuxiliaryNode + +$node = new AuxiliaryNode( + // body of the print() method: + fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode), + // nodes accessed via getIterator() and also passed into the print() method: + [$argNode], +); +``` + + Μεταγλωττιστής περνάει .[#toc-compiler-passes] ============================================== diff --git a/latte/el/tags.texy b/latte/el/tags.texy index 3b072d07d0..136ac46e0d 100644 --- a/latte/el/tags.texy +++ b/latte/el/tags.texy @@ -16,6 +16,7 @@ | `{ifset}`... `{elseifset}`... `{/ifset}` | [συνθήκη ifset |#ifset-elseifset] | `{ifchanged}`... `{/ifchanged}` | [test if there has been a change |#ifchanged] | `{switch}` `{case}` `{default}` `{/switch}` | [condition switch |#switch-case-default] +| `n:else` | [εναλλακτικό περιεχόμενο για τους όρους |#n:else] .[table-latte-tags language-latte] |## Βρόχοι @@ -246,6 +247,20 @@ Age: {date('Y') - $birth}
    Ωραία. +`n:else` .{data-version:3.0.11} +------------------------------- + +Αν γράψετε τη συνθήκη `{if} ... {/if}` με τη μορφή ενός [n:attribute |syntax#n:attributes], έχετε τη δυνατότητα να καθορίσετε μια εναλλακτική διακλάδωση χρησιμοποιώντας το `n:else`: + +```latte +In stock {$count} items + +not available +``` + +Το χαρακτηριστικό `n:else` μπορεί επίσης να χρησιμοποιηθεί σε συνδυασμό με το [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent], και [`n:ifchanged` |#ifchanged]. + + `{/if $cond}` ------------- diff --git a/latte/en/cookbook/migration-from-latte2.texy b/latte/en/cookbook/migration-from-latte2.texy index e563704572..825cf2275a 100644 --- a/latte/en/cookbook/migration-from-latte2.texy +++ b/latte/en/cookbook/migration-from-latte2.texy @@ -128,6 +128,26 @@ $latte->addExtension(new Nette\Bridges\CacheLatte\CacheExtension($cacheStorage)) ``` +Tracy +----- + +The panel for Tracy is now also activated as an extension. + +Old code for Latte 2: + +```php +$latte = new Latte\Engine; +Latte\Bridges\Tracy\LattePanel::initialize($latte); +``` + +New code for Latte 3: + +```php +$latte = new Latte\Engine; +$latte->addExtension(new Latte\Bridges\Tracy\TracyExtension); +``` + + Translations ------------ diff --git a/latte/en/creating-extension.texy b/latte/en/creating-extension.texy index 2ab3a6d1d2..60b9bd3b4c 100644 --- a/latte/en/creating-extension.texy +++ b/latte/en/creating-extension.texy @@ -307,7 +307,7 @@ class ForeachNode extends StatementNode // a parsing function that just creates a node for now public static function create(Latte\Compiler\Tag $tag): self { - $node = new self; + $node = $tag->node = new self; return $node; } @@ -359,7 +359,7 @@ class ForeachNode extends StatementNode public static function create(Latte\Compiler\Tag $tag): self { $tag->expectArguments(); - $node = new self; + $node = $tag->node = new self; $node->expression = $tag->parser->parseExpression(); $tag->parser->stream->consume('as'); $node->value = $parser->parseExpression(); @@ -486,6 +486,24 @@ public function &getIterator(): \Generator ``` +AuxiliaryNode +------------- + +If you are creating a new tag for Latte, it is advisable to create a dedicated node class for it, which will represent it in the AST tree (see the `ForeachNode` class in the example above). In some cases, you might find the trivial helper node class [AuxiliaryNode|api:Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode] useful, which allows you to pass the body of the `print()` method and the list of nodes made accessible by the `getIterator()` method as constructor parameters: + +```php +// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode +// or Latte\Compiler\Nodes\AuxiliaryNode + +$node = new AuxiliaryNode( + // body of the print() method: + fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode), + // nodes accessed via getIterator() and also passed into the print() method: + [$argNode], +); +``` + + Compiler Passes =============== diff --git a/latte/en/tags.texy b/latte/en/tags.texy index 40f20ce675..bb1a7d44da 100644 --- a/latte/en/tags.texy +++ b/latte/en/tags.texy @@ -16,6 +16,7 @@ Summary and description of all Latte built-in tags. | `{ifset}` … `{elseifset}` … `{/ifset}` | [condition ifset|#ifset-elseifset] | `{ifchanged}` … `{/ifchanged}` | [test if there has been a change|#ifchanged] | `{switch}` `{case}` `{default}` `{/switch}` | [condition switch|#switch-case-default] +| `n:else` | [alternative content for conditions |#n:else] .[table-latte-tags language-latte] |## Loops @@ -89,7 +90,7 @@ Summary and description of all Latte built-in tags. | `n:class` | [smart class attribute |#n:class] | `n:attr` | [smart HTML attributes |#n:attr] | `n:tag` | [dynamic name of HTML element |#n:tag] -| `n:ifcontent` | [Omit empty HTML tag |#n:ifcontent] +| `n:ifcontent` | [omit empty HTML tag |#n:ifcontent] .[table-latte-tags language-latte] |## Available only in Nette Framework @@ -246,6 +247,20 @@ Do you know that you can add prefix `tag-` to n:attributes? Then the condition w Nice. +`n:else` .{data-version:3.0.11} +------------------------------- + +If you write the `{if} ... {/if}` condition in the form of an [n:attribute|syntax#n:attributes], you have the option to specify an alternative branch using `n:else`: + +```latte +In stock {$count} items + +not available +``` + +The `n:else` attribute can also be used in conjunction with [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent], and [`n:ifchanged` |#ifchanged]. + + `{/if $cond}` ------------- diff --git a/latte/es/creating-extension.texy b/latte/es/creating-extension.texy index 90f18eb08f..80efc46276 100644 --- a/latte/es/creating-extension.texy +++ b/latte/es/creating-extension.texy @@ -307,7 +307,7 @@ class ForeachNode extends StatementNode // a parsing function that just creates a node for now public static function create(Latte\Compiler\Tag $tag): self { - $node = new self; + $node = $tag->node = new self; return $node; } @@ -359,7 +359,7 @@ class ForeachNode extends StatementNode public static function create(Latte\Compiler\Tag $tag): self { $tag->expectArguments(); - $node = new self; + $node = $tag->node = new self; $node->expression = $tag->parser->parseExpression(); $tag->parser->stream->consume('as'); $node->value = $parser->parseExpression(); @@ -486,6 +486,24 @@ public function &getIterator(): \Generator ``` +NodoAuxiliar .[#toc-auxiliarynode] +---------------------------------- + +Si está creando una nueva etiqueta para Latte, es aconsejable crear una clase de nodo dedicada para ella, que la representará en el árbol AST (véase la clase `ForeachNode` en el ejemplo anterior). En algunos casos, puede resultarle útil la clase de nodo auxiliar [AuxiliaryNode |api:Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode], que le permite pasar el cuerpo del método `print()` y la lista de nodos accesibles por el método `getIterator()` como parámetros del constructor: + +```php +// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode +// or Latte\Compiler\Nodes\AuxiliaryNode + +$node = new AuxiliaryNode( + // body of the print() method: + fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode), + // nodes accessed via getIterator() and also passed into the print() method: + [$argNode], +); +``` + + El compilador pasa .[#toc-compiler-passes] ========================================== diff --git a/latte/es/tags.texy b/latte/es/tags.texy index 9a1a83768b..d8ce05adc5 100644 --- a/latte/es/tags.texy +++ b/latte/es/tags.texy @@ -16,6 +16,7 @@ Resumen y descripción de todas las etiquetas Latte incorporadas. | `{ifset}`... `{elseifset}`... `{/ifset}` | [condición ifset |#ifset-elseifset] | `{ifchanged}`... `{/ifchanged}` | [prueba si ha habido un cambio |#ifchanged] | `{switch}` `{case}` `{default}` `{/switch}` | [condition switch |#switch-case-default] +| `n:else` | [contenido alternativo para las condiciones |#n:else] .[table-latte-tags language-latte] |## Bucles @@ -246,6 +247,20 @@ Como cualquier etiqueta de par, un par de `{if} ... {/ if}` puede escribirse com Bien. +`n:else` .{data-version:3.0.11} +------------------------------- + +Si escribe la condición `{if} ... {/if}` en forma de [atributo n: |syntax#n:attributes]tiene la opción de especificar una rama alternativa utilizando `n:else`: + +```latte +In stock {$count} items + +not available +``` + +El atributo `n:else` también puede utilizarse junto con [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent]y [`n:ifchanged` |#ifchanged]. + + `{/if $cond}` ------------- diff --git a/latte/fr/creating-extension.texy b/latte/fr/creating-extension.texy index f5ff5552e8..a700a21cbd 100644 --- a/latte/fr/creating-extension.texy +++ b/latte/fr/creating-extension.texy @@ -307,7 +307,7 @@ class ForeachNode extends StatementNode // une fonction d'analyse syntaxique qui crée simplement un nœud pour l'instant public static function create(Latte\Compiler\Tag $tag): self { - $node = new self; + $node = $tag->node = new self; return $node; } @@ -359,7 +359,7 @@ class ForeachNode extends StatementNode public static function create(Latte\Compiler\Tag $tag): self { $tag->expectArguments(); - $node = new self; + $node = $tag->node = new self; $node->expression = $tag->parser->parseExpression(); $tag->parser->stream->consume('as'); $node->value = $parser->parseExpression(); @@ -486,6 +486,24 @@ public function &getIterator(): \Generator ``` +AuxiliaryNode (nœud auxiliaire) .[#toc-auxiliarynode] +----------------------------------------------------- + +Si vous créez une nouvelle balise pour Latte, il est conseillé de créer une classe de nœuds dédiée, qui la représentera dans l'arbre AST (voir la classe `ForeachNode` dans l'exemple ci-dessus). Dans certains cas, la classe de nœuds auxiliaire triviale [AuxiliaryNode |api:Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode] peut s'avérer utile, car elle permet de passer le corps de la méthode `print()` et la liste des nœuds rendus accessibles par la méthode `getIterator()` en tant que paramètres du constructeur : + +```php +// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode +// or Latte\Compiler\Nodes\AuxiliaryNode + +$node = new AuxiliaryNode( + // body of the print() method: + fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode), + // nodes accessed via getIterator() and also passed into the print() method: + [$argNode], +); +``` + + Le compilateur passe .[#toc-compiler-passes] ============================================ diff --git a/latte/fr/tags.texy b/latte/fr/tags.texy index 6014948985..0d86c53500 100644 --- a/latte/fr/tags.texy +++ b/latte/fr/tags.texy @@ -16,6 +16,7 @@ Résumé et description de toutes les balises intégrées de Latte. | `{ifset}`... `{elseifset}`... `{/ifset}` | [condition ifset |#ifset-elseifset] | `{ifchanged}`... `{/ifchanged}` | [test si un changement est intervenu|#ifchanged] | `{switch}` `{case}` `{default}` `{/switch}` | [condition switch |#switch-case-default] +| `n:else` | [contenu alternatif pour les conditions |#n:else] .[table-latte-tags language-latte] |## Boucles @@ -246,6 +247,20 @@ Savez-vous que vous pouvez ajouter le préfixe `tag-` aux n:attributs ? La condi Bien. +`n:else` .{data-version:3.0.11} +------------------------------- + +Si vous écrivez la condition `{if} ... {/if}` sous la forme d'un [n:attribut |syntax#n:attributes], vous avez la possibilité de spécifier une branche alternative en utilisant `n:else`: + +```latte +In stock {$count} items + +not available +``` + +L'attribut `n:else` peut également être utilisé en conjonction avec [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent], et [`n:ifchanged` |#ifchanged]. + + `{/if $cond}` ------------- diff --git a/latte/hu/creating-extension.texy b/latte/hu/creating-extension.texy index 18afbba7cd..63d4ddc958 100644 --- a/latte/hu/creating-extension.texy +++ b/latte/hu/creating-extension.texy @@ -307,7 +307,7 @@ class ForeachNode extends StatementNode // egy elemző függvény, amely egyelőre csak egy csomópontot hoz létre. public static function create(Latte\Compiler\Tag $tag): self { - $node = new self; + $node = $tag->node = new self; return $node; } @@ -359,7 +359,7 @@ class ForeachNode extends StatementNode public static function create(Latte\Compiler\Tag $tag): self { $tag->expectArguments(); - $node = new self; + $node = $tag->node = new self; $node->expression = $tag->parser->parseExpression(); $tag->parser->stream->consume('as'); $node->value = $parser->parseExpression(); @@ -486,6 +486,24 @@ public function &getIterator(): \Generator ``` +AuxiliaryNode +------------- + +Ha új címkét hozunk létre a Latte számára, célszerű létrehozni egy külön node osztályt, amely az AST fában képviseli majd (lásd a `ForeachNode` osztályt a fenti példában). Bizonyos esetekben hasznos lehet az [AuxiliaryNode |api:Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode] triviális segédcsomópont-osztály, amely lehetővé teszi, hogy a `print()` metódus testét és a `getIterator()` metódus által elérhetővé tett csomópontok listáját konstruktorparaméterként átadjuk: + +```php +// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode +// or Latte\Compiler\Nodes\AuxiliaryNode + +$node = new AuxiliaryNode( + // body of the print() method: + fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode), + // nodes accessed via getIterator() and also passed into the print() method: + [$argNode], +); +``` + + Compiler Passes .[#toc-compiler-passes] ======================================= diff --git a/latte/hu/tags.texy b/latte/hu/tags.texy index 8067ced3a4..72eca3cd27 100644 --- a/latte/hu/tags.texy +++ b/latte/hu/tags.texy @@ -16,6 +16,7 @@ Az összes beépített Latte-címke összefoglalása és leírása. | `{ifset}`... `{elseifset}`... `{/ifset}` | [feltétel ifset |#ifset-elseifset] | `{ifchanged}`... `{/ifchanged}` | [tesztelés, hogy történt-e változás |#ifchanged] | `{switch}` `{case}` `{default}` `{/switch}` | [condition switch |#switch-case-default] +| `n:else` | [alternatív tartalom a feltételekhez |#n:else] .[table-latte-tags language-latte] |## Loops @@ -246,6 +247,20 @@ Tudtad, hogy az n:attribútumokhoz hozzáadhatod a `tag-` előtagot? Ekkor a fel Szép. +`n:else` .{data-version:3.0.11} +------------------------------- + +Ha a `{if} ... {/if}` feltételt [n:attribútum |syntax#n:attributes] formájában írja, akkor lehetősége van a `n:else` segítségével egy alternatív ágat is megadni: + +```latte +In stock {$count} items + +not available +``` + +A `n:else` attribútum a következővel együtt is használható [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent], és [`n:ifchanged` |#ifchanged]. + + `{/if $cond}` ------------- diff --git a/latte/it/creating-extension.texy b/latte/it/creating-extension.texy index a321dfa0a8..1ab63db38d 100644 --- a/latte/it/creating-extension.texy +++ b/latte/it/creating-extension.texy @@ -307,7 +307,7 @@ class ForeachNode extends StatementNode // una funzione di parsing che per ora crea solo un nodo public static function create(Latte\Compiler\Tag $tag): self { - $node = new self; + $node = $tag->node = new self; return $node; } @@ -359,7 +359,7 @@ class ForeachNode extends StatementNode public static function create(Latte\Compiler\Tag $tag): self { $tag->expectArguments(); - $node = new self; + $node = $tag->node = new self; $node->expression = $tag->parser->parseExpression(); $tag->parser->stream->consume('as'); $node->value = $parser->parseExpression(); @@ -486,6 +486,24 @@ public function &getIterator(): \Generator ``` +Nodo ausiliario .[#toc-auxiliarynode] +------------------------------------- + +Se si sta creando un nuovo tag per Latte, è consigliabile creare una classe di nodi dedicata, che lo rappresenti nell'albero AST (si veda la classe `ForeachNode` nell'esempio precedente). In alcuni casi, potrebbe essere utile la classe di nodi ausiliari [AuxiliaryNode |api:Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode], che consente di passare il corpo del metodo `print()` e l'elenco dei nodi resi accessibili dal metodo `getIterator()` come parametri del costruttore: + +```php +// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode +// or Latte\Compiler\Nodes\AuxiliaryNode + +$node = new AuxiliaryNode( + // body of the print() method: + fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode), + // nodes accessed via getIterator() and also passed into the print() method: + [$argNode], +); +``` + + Il compilatore passa .[#toc-compiler-passes] ============================================ diff --git a/latte/it/tags.texy b/latte/it/tags.texy index 8f913e302e..2bb8b2df56 100644 --- a/latte/it/tags.texy +++ b/latte/it/tags.texy @@ -16,6 +16,7 @@ Riepilogo e descrizione di tutti i tag incorporati di Latte. | `{ifset}`... `{elseifset}`... `{/ifset}` | [condizione ifset |#ifset-elseifset] | `{ifchanged}`... `{/ifchanged}` | [verifica se c'è stata una modifica |#ifchanged] | `{switch}` `{case}` `{default}` `{/switch}` | [condizione switch |#switch-case-default] +| `n:else` | [contenuto alternativo per le condizioni |#n:else] .[table-latte-tags language-latte] |## Cicli @@ -246,6 +247,20 @@ Sapete che è possibile aggiungere il prefisso `tag-` a n:attributi? In questo m Bello. +`n:else` .{data-version:3.0.11} +------------------------------- + +Se si scrive la condizione `{if} ... {/if}` sotto forma di un [attributo n: |syntax#n:attributes], si ha la possibilità di specificare un ramo alternativo usando `n:else`: + +```latte +In stock {$count} items + +not available +``` + +L'attributo `n:else` può essere usato anche insieme a [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent], e [`n:ifchanged` |#ifchanged]. + + `{/if $cond}` ------------- diff --git a/latte/ja/creating-extension.texy b/latte/ja/creating-extension.texy index 40c4a14cec..b930a07ec2 100644 --- a/latte/ja/creating-extension.texy +++ b/latte/ja/creating-extension.texy @@ -307,7 +307,7 @@ class ForeachNode extends StatementNode // a parsing function that just creates a node for now public static function create(Latte\Compiler\Tag $tag): self { - $node = new self; + $node = $tag->node = new self; return $node; } @@ -359,7 +359,7 @@ class ForeachNode extends StatementNode public static function create(Latte\Compiler\Tag $tag): self { $tag->expectArguments(); - $node = new self; + $node = $tag->node = new self; $node->expression = $tag->parser->parseExpression(); $tag->parser->stream->consume('as'); $node->value = $parser->parseExpression(); @@ -486,6 +486,24 @@ public function &getIterator(): \Generator ``` +補助ノード.[#toc-auxiliarynode] +-------------------------- + +Latte用の新しいタグを作成する場合は、ASTツリーでそれを表現する専用のノードクラスを作成することをお勧めします(上記の例の`ForeachNode` クラスを参照)。このクラスでは、`print()` メソッドのボディと、`getIterator()` メソッドによってアクセス可能になったノードのリストをコンストラクタのパラメータとして渡すことができます: + +```php +// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode +// or Latte\Compiler\Nodes\AuxiliaryNode + +$node = new AuxiliaryNode( + // body of the print() method: + fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode), + // nodes accessed via getIterator() and also passed into the print() method: + [$argNode], +); +``` + + コンパイラのパス .[#toc-compiler-passes] ================================ diff --git a/latte/ja/tags.texy b/latte/ja/tags.texy index d0ddf3e1d1..f2a8060fa3 100644 --- a/latte/ja/tags.texy +++ b/latte/ja/tags.texy @@ -16,6 +16,7 @@ Latte内蔵の全タグの概要と説明。 |`{ifset}`...`{elseifset}`...`{/ifset}` |[条件 ifset |#ifset-elseifset] |`{ifchanged}`...`{/ifchanged}` |[変化があったかどうかのテスト|#ifchanged] |`{switch}` `{case}` `{default}` `{/switch}` |[条件スイッチ |#switch-case-default] +|`n:else` |[コンディションの代替コンテンツ |#n:else] .[table-latte-tags language-latte] |## ループ @@ -246,6 +247,20 @@ n:attributesに接頭辞`tag-` を付けることができることをご存知 いいですね。 +`n:else` .{data-version:3.0.11} +------------------------------- + + の条件を`{if} ... {/if}` [n:属性の |syntax#n:attributes]形で記述した場合、 を使って別の分岐を指定するオプションがある: + + + + 。`n:else````latte +In stock {$count} items + +not available +``` `n:else` [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent]および [`n:ifchanged` |#ifchanged]. + + `{/if $cond}` ------------- diff --git a/latte/pl/creating-extension.texy b/latte/pl/creating-extension.texy index 16e3fb6bb3..c82776c374 100644 --- a/latte/pl/creating-extension.texy +++ b/latte/pl/creating-extension.texy @@ -307,7 +307,7 @@ class ForeachNode extends StatementNode // funkcja parsowania, która na razie tworzy tylko węzeł public static function create(Latte\Compiler\Tag $tag): self { - $node = new self; + $node = $tag->node = new self; return $node; } @@ -359,7 +359,7 @@ class ForeachNode extends StatementNode public static function create(Latte\Compiler\Tag $tag): self { $tag->expectArguments(); - $node = new self; + $node = $tag->node = new self; $node->expression = $tag->parser->parseExpression(); $tag->parser->stream->consume('as'); $node->value = $parser->parseExpression(); @@ -486,6 +486,24 @@ public function &getIterator(): \Generator ``` +AuxiliaryNode +------------- + +Jeśli tworzysz nowy tag dla Latte, zaleca się utworzenie dla niego dedykowanej klasy węzła, która będzie reprezentować go w drzewie AST (patrz klasa `ForeachNode` w powyższym przykładzie). W niektórych przypadkach przydatna może okazać się trywialna klasa węzła pomocniczego [AuxiliaryNode |api:Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode], która pozwala przekazać ciało metody `print()` i listę węzłów udostępnionych przez metodę `getIterator()` jako parametry konstruktora: + +```php +// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode +// or Latte\Compiler\Nodes\AuxiliaryNode + +$node = new AuxiliaryNode( + // body of the print() method: + fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode), + // nodes accessed via getIterator() and also passed into the print() method: + [$argNode], +); +``` + + Kompilator przechodzi .[#toc-compiler-passes] ============================================= diff --git a/latte/pl/tags.texy b/latte/pl/tags.texy index 01361a52f5..a37900883c 100644 --- a/latte/pl/tags.texy +++ b/latte/pl/tags.texy @@ -16,6 +16,7 @@ Przegląd i opis wszystkich znaczników systemu templatek Latte, które są domy | `{ifset}`... `{elseifset}`... `{/ifset}` | [ifset condition |#ifset-elseifset] | `{ifchanged}`... `{/ifchanged}` | [test, czy nastąpiła zmiana |#ifchanged] | `{switch}` `{case}` `{default}` `{/switch}` | [warunek przełączenia |#switch-case-default] +| `n:else` | [alternatywna zawartość dla warunków |#n:else] .[table-latte-tags language-latte] |## Cykle @@ -246,6 +247,20 @@ Czy wiesz, że możesz przedrostek `tag-` do n:atrybutów ? Wtedy warunek będzi Boże. +`n:else` .{data-version:3.0.11} +------------------------------- + +Jeśli warunek `{if} ... {/if}` zostanie zapisany w postaci [atrybutu n: |syntax#n:attributes], istnieje możliwość określenia alternatywnej gałęzi za pomocą `n:else`: + +```latte +In stock {$count} items + +not available +``` + +Atrybut `n:else` może być również użyty w połączeniu z [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent]oraz [`n:ifchanged` |#ifchanged]. + + `{/if $cond}` ------------- diff --git a/latte/pt/creating-extension.texy b/latte/pt/creating-extension.texy index 327d9059d7..8c31cc2c3f 100644 --- a/latte/pt/creating-extension.texy +++ b/latte/pt/creating-extension.texy @@ -307,7 +307,7 @@ class ForeachNode extends StatementNode // a parsing function that just creates a node for now public static function create(Latte\Compiler\Tag $tag): self { - $node = new self; + $node = $tag->node = new self; return $node; } @@ -359,7 +359,7 @@ class ForeachNode extends StatementNode public static function create(Latte\Compiler\Tag $tag): self { $tag->expectArguments(); - $node = new self; + $node = $tag->node = new self; $node->expression = $tag->parser->parseExpression(); $tag->parser->stream->consume('as'); $node->value = $parser->parseExpression(); @@ -486,6 +486,24 @@ public function &getIterator(): \Generator ``` +AuxiliaryNode +------------- + +Se estiver criando uma nova tag para o Latte, é aconselhável criar uma classe de nó dedicada a ela, que a representará na árvore AST (veja a classe `ForeachNode` no exemplo acima). Em alguns casos, você pode achar útil a classe de nó auxiliar trivial [AuxiliaryNode |api:Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode], que permite que você passe o corpo do método `print()` e a lista de nós tornados acessíveis pelo método `getIterator()` como parâmetros do construtor: + +```php +// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode +// or Latte\Compiler\Nodes\AuxiliaryNode + +$node = new AuxiliaryNode( + // body of the print() method: + fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode), + // nodes accessed via getIterator() and also passed into the print() method: + [$argNode], +); +``` + + Passes de Compilador .[#toc-compiler-passes] ============================================ diff --git a/latte/pt/tags.texy b/latte/pt/tags.texy index 49c3599b74..d1181600f8 100644 --- a/latte/pt/tags.texy +++ b/latte/pt/tags.texy @@ -16,6 +16,7 @@ Resumo e descrição de todas as etiquetas incorporadas no Latte. | `{ifset}`... `{elseifset}`... `{/ifset}`... | [condição se começar |#ifset-elseifset] | `{ifchanged}`... `{/ifchanged}` | [testar se houve uma mudança |#ifchanged] | `{switch}` `{case}` `{default}` `{/switch}` | [interruptor de condição |#switch-case-default] +| `n:else` | [conteúdo alternativo para condições |#n:else] .[table-latte-tags language-latte] |## Loops @@ -246,6 +247,20 @@ Você sabe que pode adicionar o prefixo `tag-` aos n:attributes? Então a condi Legal. +`n:else` .{data-version:3.0.11} +------------------------------- + +Se você escrever a condição `{if} ... {/if}` na forma de um [atributo n:attribute |syntax#n:attributes], terá a opção de especificar um ramo alternativo usando `n:else`: + +```latte +In stock {$count} items + +not available +``` + +O atributo `n:else` também pode ser usado em conjunto com [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent], e [`n:ifchanged` |#ifchanged]. + + `{/if $cond}` ------------- diff --git a/latte/ro/creating-extension.texy b/latte/ro/creating-extension.texy index 51bf98fc2d..7b0f52342c 100644 --- a/latte/ro/creating-extension.texy +++ b/latte/ro/creating-extension.texy @@ -307,7 +307,7 @@ class ForeachNode extends StatementNode // o funcție de parsare care creează doar un nod pentru moment public static function create(Latte\Compiler\Tag $tag): self { - $node = new self; + $node = $tag->node = new self; return $node; } @@ -359,7 +359,7 @@ class ForeachNode extends StatementNode public static function create(Latte\Compiler\Tag $tag): self { $tag->expectArguments(); - $node = new self; + $node = $tag->node = new self; $node->expression = $tag->parser->parseExpression(); $tag->parser->stream->consume('as'); $node->value = $parser->parseExpression(); @@ -486,6 +486,24 @@ public function &getIterator(): \Generator ``` +AuxiliaryNode +------------- + +Dacă creați o nouă etichetă pentru Latte, este recomandabil să creați o clasă de nod dedicată pentru aceasta, care o va reprezenta în arborele AST (a se vedea clasa `ForeachNode` din exemplul de mai sus). În unele cazuri, s-ar putea să vi se pară utilă clasa de noduri auxiliare triviale [AuxiliaryNode |api:Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode], care vă permite să treceți ca parametri de constructor corpul metodei `print()` și lista de noduri accesibile prin metoda `getIterator()`: + +```php +// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode +// or Latte\Compiler\Nodes\AuxiliaryNode + +$node = new AuxiliaryNode( + // body of the print() method: + fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode), + // nodes accessed via getIterator() and also passed into the print() method: + [$argNode], +); +``` + + Compilatorul trece .[#toc-compiler-passes] ========================================== diff --git a/latte/ro/tags.texy b/latte/ro/tags.texy index c2950bc2ad..d60386cc8f 100644 --- a/latte/ro/tags.texy +++ b/latte/ro/tags.texy @@ -16,6 +16,7 @@ Rezumat și descriere a tuturor etichetelor Latte încorporate. | `{ifset}`... `{elseifset}`... `{/ifset}` | [condiție ifset |#ifset-elseifset] | `{ifchanged}`... `{/ifchanged}` | [testează dacă a avut loc o schimbare |#ifchanged] | `{switch}` `{case}` `{default}` `{/switch}` | [condition switch |#switch-case-default] +| `n:else` | [conținut alternativ pentru condiții |#n:else] .[table-latte-tags language-latte] |## Bucle @@ -246,6 +247,20 @@ La fel ca orice tag pair, o pereche de `{if} ... {/ if}` poate fi scrisă ca [n: Frumos. +`n:else` .{data-version:3.0.11} +------------------------------- + +Dacă scrieți condiția `{if} ... {/if}` sub forma unui [n:atribut |syntax#n:attributes], aveți opțiunea de a specifica o ramură alternativă folosind `n:else`: + +```latte +In stock {$count} items + +not available +``` + +Atributul `n:else` poate fi, de asemenea, utilizat împreună cu [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent], și [`n:ifchanged` |#ifchanged]. + + `{/if $cond}` ------------- diff --git a/latte/ru/creating-extension.texy b/latte/ru/creating-extension.texy index 23fd8a9051..e9722842db 100644 --- a/latte/ru/creating-extension.texy +++ b/latte/ru/creating-extension.texy @@ -307,7 +307,7 @@ class ForeachNode extends StatementNode // a parsing function that just creates a node for now public static function create(Latte\Compiler\Tag $tag): self { - $node = new self; + $node = $tag->node = new self; return $node; } @@ -359,7 +359,7 @@ class ForeachNode extends StatementNode public static function create(Latte\Compiler\Tag $tag): self { $tag->expectArguments(); - $node = new self; + $node = $tag->node = new self; $node->expression = $tag->parser->parseExpression(); $tag->parser->stream->consume('as'); $node->value = $parser->parseExpression(); @@ -486,6 +486,24 @@ public function &getIterator(): \Generator ``` +AuxiliaryNode +------------- + +Если вы создаете новый тег для Latte, то целесообразно создать для него специальный класс узла, который будет представлять его в дереве AST (см. класс `ForeachNode` в примере выше). В некоторых случаях может оказаться полезным тривиальный вспомогательный класс узла [AuxiliaryNode |api:Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode], который позволяет передать в качестве параметров конструктора тело метода `print()` и список узлов, доступных методом `getIterator()`: + +```php +// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode +// or Latte\Compiler\Nodes\AuxiliaryNode + +$node = new AuxiliaryNode( + // body of the print() method: + fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode), + // nodes accessed via getIterator() and also passed into the print() method: + [$argNode], +); +``` + + Компилятор передает .[#toc-compiler-passes] =========================================== diff --git a/latte/ru/tags.texy b/latte/ru/tags.texy index d47d8f30cc..3bae39e4dd 100644 --- a/latte/ru/tags.texy +++ b/latte/ru/tags.texy @@ -16,6 +16,7 @@ | `{ifset}`... `{elseifset}`... `{/ifset}` | [условие ifset |#ifset-elseifset] | `{ifchanged}`... `{/ifchanged}` | [проверка наличия изменений |#ifchanged] | `{switch}` `{case}` `{default}` `{/switch}` | [условие switch |#switch-case-default] +| `n:else` | [альтернативное содержание условий |#n:else] .[table-latte-tags language-latte] |## Loops @@ -246,6 +247,20 @@ Age: {date('Y') - $birth}
    Отлично. +`n:else` .{data-version:3.0.11} +------------------------------- + +Если условие `{if} ... {/if}` записано в виде [атрибута n:attribute |syntax#n:attributes], то у вас есть возможность указать альтернативную ветвь с помощью `n:else`: + +```latte +In stock {$count} items + +not available +``` + +Атрибут `n:else` также может использоваться в сочетании с. [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent], и [`n:ifchanged` |#ifchanged]. + + `{/if $cond}` ------------- diff --git a/latte/sl/creating-extension.texy b/latte/sl/creating-extension.texy index dcf41f3758..cfa9fb6bf3 100644 --- a/latte/sl/creating-extension.texy +++ b/latte/sl/creating-extension.texy @@ -307,7 +307,7 @@ class ForeachNode extends StatementNode // funkcija razčlenjevanja, ki za zdaj samo ustvari vozlišče public static function create(Latte\Compiler\Tag $tag): self { - $node = new self; + $node = $tag->node = new self; return $node; } @@ -359,7 +359,7 @@ class ForeachNode extends StatementNode public static function create(Latte\Compiler\Tag $tag): self { $tag->expectArguments(); - $node = new self; + $node = $tag->node = new self; $node->expression = $tag->parser->parseExpression(); $tag->parser->stream->consume('as'); $node->value = $parser->parseExpression(); @@ -486,6 +486,24 @@ public function &getIterator(): \Generator ``` +AuxiliaryNode +------------- + +Če ustvarjate novo oznako za Latte, je zanjo priporočljivo ustvariti poseben razred vozlišča, ki jo bo predstavljal v drevesu AST (glej razred `ForeachNode` v zgornjem primeru). V nekaterih primerih se vam bo morda zdel uporaben trivialni pomožni razred vozlišč [AuxiliaryNode |api:Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode], ki vam omogoča, da kot parametre konstruktorja posredujete telo metode `print()` in seznam vozlišč, do katerih je dostopna metoda `getIterator()`: + +```php +// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode +// or Latte\Compiler\Nodes\AuxiliaryNode + +$node = new AuxiliaryNode( + // body of the print() method: + fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode), + // nodes accessed via getIterator() and also passed into the print() method: + [$argNode], +); +``` + + Prevajalnik prenese .[#toc-compiler-passes] =========================================== diff --git a/latte/sl/tags.texy b/latte/sl/tags.texy index b218a53ccc..958c0bff4f 100644 --- a/latte/sl/tags.texy +++ b/latte/sl/tags.texy @@ -16,6 +16,7 @@ Povzetek in opis vseh vgrajenih oznak Latte. | `{ifset}`... `{elseifset}`... `{/ifset}` | [pogoj ifset |#ifset-elseifset] | `{ifchanged}`... `{/ifchanged}` | [testiranje, ali je prišlo do spremembe |#ifchanged] | `{switch}` `{case}` `{default}` `{/switch}` | [pogoj switch |#switch-case-default] +| `n:else` | [alternativna vsebina za pogoje |#n:else] .[table-latte-tags language-latte] |### zanke @@ -246,6 +247,20 @@ Ali veste, da lahko n:atributom dodate predpono `tag-`? Potem bo pogoj vplival s Lepo. +`n:else` .{data-version:3.0.11} +------------------------------- + +Če pogoj `{if} ... {/if}` zapišete v obliki [n:atributa |syntax#n:attributes], imate možnost določiti alternativno vejo z uporabo `n:else`: + +```latte +In stock {$count} items + +not available +``` + +Atribut `n:else` lahko uporabite tudi v povezavi z [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent], in [`n:ifchanged` |#ifchanged]. + + `{/if $cond}` ------------- diff --git a/latte/tr/creating-extension.texy b/latte/tr/creating-extension.texy index db2b4410f8..72e4325109 100644 --- a/latte/tr/creating-extension.texy +++ b/latte/tr/creating-extension.texy @@ -307,7 +307,7 @@ class ForeachNode extends StatementNode // a parsing function that just creates a node for now public static function create(Latte\Compiler\Tag $tag): self { - $node = new self; + $node = $tag->node = new self; return $node; } @@ -359,7 +359,7 @@ class ForeachNode extends StatementNode public static function create(Latte\Compiler\Tag $tag): self { $tag->expectArguments(); - $node = new self; + $node = $tag->node = new self; $node->expression = $tag->parser->parseExpression(); $tag->parser->stream->consume('as'); $node->value = $parser->parseExpression(); @@ -486,6 +486,24 @@ public function &getIterator(): \Generator ``` +AuxiliaryNode +------------- + +Latte için yeni bir etiket oluşturuyorsanız, bunun için AST ağacında temsil edecek özel bir düğüm sınıfı oluşturmanız tavsiye edilir (yukarıdaki örnekte `ForeachNode` sınıfına bakın). Bazı durumlarda, `print()` yönteminin gövdesini ve `getIterator()` yöntemi tarafından erişilebilir kılınan düğümlerin listesini yapıcı parametreleri olarak geçirmenize olanak tanıyan önemsiz yardımcı düğüm sınıfı [AuxiliaryNode |api:Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode] 'u yararlı bulabilirsiniz: + +```php +// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode +// or Latte\Compiler\Nodes\AuxiliaryNode + +$node = new AuxiliaryNode( + // body of the print() method: + fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode), + // nodes accessed via getIterator() and also passed into the print() method: + [$argNode], +); +``` + + Derleyici Geçişleri .[#toc-compiler-passes] =========================================== diff --git a/latte/tr/tags.texy b/latte/tr/tags.texy index 889b0d3aba..535b2f018d 100644 --- a/latte/tr/tags.texy +++ b/latte/tr/tags.texy @@ -16,6 +16,7 @@ Tüm Latte yerleşik etiketlerinin özeti ve açıklaması. | `{ifset}`... `{elseifset}`... `{/ifset}` | [koşul ifset |#ifset-elseifset] | `{ifchanged}`... `{/ifchanged}` | [bir değişiklik olup olmadığını test edin|#ifchanged] | `{switch}` `{case}` `{default}` `{/switch}` | [koşul anahtarı |#switch-case-default] +| `n:else` | [koşullar için alternatif içerik |#n:else] .[table-latte-tags language-latte] |## Döngüler @@ -246,6 +247,20 @@ n:attributes öğesine `tag-` önekini ekleyebileceğinizi biliyor musunuz? Bu d Güzel. +`n:else` .{data-version:3.0.11} +------------------------------- + + `{if} ... {/if}` koşulunu bir [n:niteliği |syntax#n:attributes] biçiminde yazarsanız, `n:else` adresini kullanarak alternatif bir dal belirtme seçeneğiniz vardır: + +```latte +In stock {$count} items + +not available +``` + + `n:else` özniteliği aşağıdakilerle birlikte de kullanılabilir [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent]ve [`n:ifchanged` |#ifchanged]. + + `{/if $cond}` ------------- diff --git a/latte/uk/creating-extension.texy b/latte/uk/creating-extension.texy index 8ddb1f21d1..9a75553be9 100644 --- a/latte/uk/creating-extension.texy +++ b/latte/uk/creating-extension.texy @@ -307,7 +307,7 @@ class ForeachNode extends StatementNode // функція розбору, яка поки що просто створює вузол public static function create(Latte\Compiler\Tag $tag): self { - $node = new self; + $node = $tag->node = new self; return $node; } @@ -359,7 +359,7 @@ class ForeachNode extends StatementNode public static function create(Latte\Compiler\Tag $tag): self { $tag->expectArguments(); - $node = new self; + $node = $tag->node = new self; $node->expression = $tag->parser->parseExpression(); $tag->parser->stream->consume('as'); $node->value = $parser->parseExpression(); @@ -486,6 +486,24 @@ public function &getIterator(): \Generator ``` +AuxiliaryNode +------------- + +Якщо ви створюєте новий тег для Latte, бажано створити для нього спеціальний клас вузла, який буде представляти його в дереві AST (див. клас `ForeachNode` у прикладі вище). У деяких випадках вам може стати в нагоді тривіальний допоміжний клас вузлів [AuxiliaryNode |api:Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode], який дозволяє передавати тіло методу `print()` і список вузлів, доступних за допомогою методу `getIterator()`, як параметри конструктора: + +```php +// Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode +// or Latte\Compiler\Nodes\AuxiliaryNode + +$node = new AuxiliaryNode( + // body of the print() method: + fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode), + // nodes accessed via getIterator() and also passed into the print() method: + [$argNode], +); +``` + + Компілятор передає .[#toc-compiler-passes] ========================================== diff --git a/latte/uk/tags.texy b/latte/uk/tags.texy index 40bc5c4964..03d1dbcbd2 100644 --- a/latte/uk/tags.texy +++ b/latte/uk/tags.texy @@ -16,6 +16,7 @@ | `{ifset}`... `{elseifset}`... `{/ifset}` | [умова ifset |#ifset-elseifset] | `{ifchanged}`... `{/ifchanged}` | [перевірка наявності змін |#ifchanged] | `{switch}` `{case}` `{default}` `{/switch}` | [умова switch |#switch-case-default] +| `n:else` | [альтернативний контент для умов |#n:else] .[table-latte-tags language-latte] |## Loops @@ -246,6 +247,20 @@ Age: {date('Y') - $birth}
    Чудово. +`n:else` .{data-version:3.0.11} +------------------------------- + +Якщо ви запишете умову `{if} ... {/if}` у вигляді [n:атрибута |syntax#n:attributes], у вас буде можливість вказати альтернативну гілку за допомогою `n:else`: + +```latte +In stock {$count} items + +not available +``` + +Атрибут `n:else` також можна використовувати у поєднанні з [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent]та [`n:ifchanged` |#ifchanged]. + + `{/if $cond}` ------------- From d18a54b98940ad89d5bb960568b663df2a70c036 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 13 Nov 2023 13:42:21 +0100 Subject: [PATCH 037/137] updated PHP requirements --- application/bg/@home.texy | 4 ++-- application/cs/@home.texy | 4 ++-- application/de/@home.texy | 4 ++-- application/el/@home.texy | 4 ++-- application/en/@home.texy | 4 ++-- application/es/@home.texy | 4 ++-- application/fr/@home.texy | 4 ++-- application/hu/@home.texy | 4 ++-- application/it/@home.texy | 4 ++-- application/pl/@home.texy | 4 ++-- application/pt/@home.texy | 4 ++-- application/ro/@home.texy | 4 ++-- application/ru/@home.texy | 4 ++-- application/sl/@home.texy | 4 ++-- application/tr/@home.texy | 4 ++-- application/uk/@home.texy | 4 ++-- tester/bg/guide.texy | 2 +- tester/cs/guide.texy | 2 +- tester/de/guide.texy | 2 +- tester/el/guide.texy | 2 +- tester/en/guide.texy | 2 +- tester/es/guide.texy | 2 +- tester/fr/guide.texy | 2 +- tester/hu/guide.texy | 2 +- tester/it/guide.texy | 2 +- tester/pl/guide.texy | 2 +- tester/pt/guide.texy | 2 +- tester/ro/guide.texy | 2 +- tester/ru/guide.texy | 2 +- tester/sl/guide.texy | 2 +- tester/tr/guide.texy | 2 +- tester/uk/guide.texy | 2 +- tracy/bg/guide.texy | 2 +- tracy/cs/guide.texy | 2 +- tracy/de/guide.texy | 2 +- tracy/el/guide.texy | 2 +- tracy/en/guide.texy | 2 +- tracy/es/guide.texy | 2 +- tracy/fr/guide.texy | 2 +- tracy/hu/guide.texy | 2 +- tracy/it/guide.texy | 2 +- tracy/pl/guide.texy | 2 +- tracy/pt/guide.texy | 2 +- tracy/ro/guide.texy | 2 +- tracy/ru/guide.texy | 2 +- tracy/sl/guide.texy | 2 +- tracy/tr/guide.texy | 2 +- tracy/uk/guide.texy | 2 +- utils/bg/@home.texy | 4 ++-- utils/cs/@home.texy | 4 ++-- utils/de/@home.texy | 4 ++-- utils/el/@home.texy | 4 ++-- utils/en/@home.texy | 4 ++-- utils/es/@home.texy | 4 ++-- utils/fr/@home.texy | 4 ++-- utils/hu/@home.texy | 4 ++-- utils/it/@home.texy | 4 ++-- utils/pl/@home.texy | 4 ++-- utils/pt/@home.texy | 4 ++-- utils/ro/@home.texy | 4 ++-- utils/ru/@home.texy | 4 ++-- utils/sl/@home.texy | 4 ++-- utils/tr/@home.texy | 4 ++-- utils/uk/@home.texy | 4 ++-- 64 files changed, 96 insertions(+), 96 deletions(-) diff --git a/application/bg/@home.texy b/application/bg/@home.texy index e01b54f4ee..64999ca151 100644 --- a/application/bg/@home.texy +++ b/application/bg/@home.texy @@ -28,8 +28,8 @@ composer require nette/application | версия на пакета | съвместима версия на PHP |-----------------------|----------------------- -| Nette Application 4.0 | PHP 8.0 - 8.1 -| Nette Application 3.1 | PHP 7.2 - 8.1 +| Nette Application 4.0 | PHP 8.1 – 8.3 +| 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 diff --git a/application/cs/@home.texy b/application/cs/@home.texy index 833406fcbd..7ff66ca955 100644 --- a/application/cs/@home.texy +++ b/application/cs/@home.texy @@ -28,8 +28,8 @@ composer require nette/application | verze | kompatibilní s PHP |-----------|------------------- -| Nette Application 4.0 | PHP 8.0 – 8.2 -| Nette Application 3.1 | PHP 7.2 – 8.2 +| Nette Application 4.0 | PHP 8.1 – 8.3 +| 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 diff --git a/application/de/@home.texy b/application/de/@home.texy index 91906d2888..de23a839b0 100644 --- a/application/de/@home.texy +++ b/application/de/@home.texy @@ -28,8 +28,8 @@ 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 Application 4.0 | PHP 8.1 – 8.3 +| Nette Application 3.1 | PHP 7.2 – 8.3 | Nette Anwendung 3.0 | PHP 7.1 - 8.0 | Nette-Anwendung 2.4 | PHP 5.6 - 8.0 diff --git a/application/el/@home.texy b/application/el/@home.texy index 8020e59b5f..1c9fac4c70 100644 --- a/application/el/@home.texy +++ b/application/el/@home.texy @@ -28,8 +28,8 @@ composer require nette/application | έκδοση | συμβατό με PHP |-----------|------------------- -| Εφαρμογή Nette 4.0 | PHP 8.0 - 8.2 -| Nette Application 3.1 | PHP 7.2 - 8.2 +| Nette Application 4.0 | PHP 8.1 – 8.3 +| 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 diff --git a/application/en/@home.texy b/application/en/@home.texy index fac8c0d767..c1e758424a 100644 --- a/application/en/@home.texy +++ b/application/en/@home.texy @@ -28,8 +28,8 @@ composer require nette/application | version | compatible with PHP |-----------|------------------- -| Nette Application 4.0 | PHP 8.0 – 8.2 -| Nette Application 3.1 | PHP 7.2 – 8.2 +| Nette Application 4.0 | PHP 8.1 – 8.3 +| 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 diff --git a/application/es/@home.texy b/application/es/@home.texy index b2966f5062..13adb46b5c 100644 --- a/application/es/@home.texy +++ b/application/es/@home.texy @@ -28,8 +28,8 @@ composer require nette/application | versión | compatible con PHP |-----------|------------------- -| Aplicación Nette 4.0 | PHP 8.0 - 8.2 -| Aplicación Nette 3.1 | PHP 7.2 - 8.2 +| Nette Application 4.0 | PHP 8.1 – 8.3 +| Nette Application 3.1 | PHP 7.2 – 8.3 | Aplicación Nette 3.0 | PHP 7.1 - 8.0 | Aplicación Nette 2.4 | PHP 5.6 - 8.0 diff --git a/application/fr/@home.texy b/application/fr/@home.texy index f0388b9636..8afc742343 100644 --- a/application/fr/@home.texy +++ b/application/fr/@home.texy @@ -28,8 +28,8 @@ composer require nette/application | version | compatible avec PHP |-----------|------------------- -| Nette Application 4.0 | PHP 8.0 - 8.2 -| Nette Application 3.1 | PHP 7.2 - 8.2 +| Nette Application 4.0 | PHP 8.1 – 8.3 +| 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 diff --git a/application/hu/@home.texy b/application/hu/@home.texy index 49f809ce72..53ef396602 100644 --- a/application/hu/@home.texy +++ b/application/hu/@home.texy @@ -28,8 +28,8 @@ composer require nette/application | verzió | kompatibilis a PHP-vel |-----------|------------------- -| Nette alkalmazás 4.0 | PHP 8.0 - 8.2 -| Nette alkalmazás 3.1 | PHP 7.2 - 8.2 +| Nette Application 4.0 | PHP 8.1 – 8.3 +| Nette Application 3.1 | PHP 7.2 – 8.3 | Nette alkalmazás 3.0 | PHP 7.1 - 8.0 | Nette Application 2.4 | PHP 5.6 - 8.0 diff --git a/application/it/@home.texy b/application/it/@home.texy index 6c54a56fdd..038c8e4f9f 100644 --- a/application/it/@home.texy +++ b/application/it/@home.texy @@ -28,8 +28,8 @@ composer require nette/application | versione | compatibile con PHP |-----------|------------------- -| Applicazione Nette 4.0 | PHP 8.0 - 8.2 -| Applicazione Nette 3.1 | PHP 7.2 - 8.2 +| Nette Application 4.0 | PHP 8.1 – 8.3 +| Nette Application 3.1 | PHP 7.2 – 8.3 | Applicazione Nette 3.0 | PHP 7.1 - 8.0 | Applicazione Nette 2.4 | PHP 5.6 - 8.0 diff --git a/application/pl/@home.texy b/application/pl/@home.texy index 138c335e70..34e9b68599 100644 --- a/application/pl/@home.texy +++ b/application/pl/@home.texy @@ -28,8 +28,8 @@ composer require nette/application | wersja zgodna z PHP |-----------|------------------- -| Nette Application 4.0 | PHP 8.0 - 8.2 -| Nette Application 3.1 | PHP 7.2 - 8.2 +| Nette Application 4.0 | PHP 8.1 – 8.3 +| 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 diff --git a/application/pt/@home.texy b/application/pt/@home.texy index 68976dc90d..e343ac2d4c 100644 --- a/application/pt/@home.texy +++ b/application/pt/@home.texy @@ -28,8 +28,8 @@ composer require nette/application | versão | compatível com PHP |-----------|------------------- -| Nette Application 4.0 | PHP 8.0 - 8.2 -| Aplicação Nette 3.1 | PHP 7.2 - 8.2 +| Nette Application 4.0 | PHP 8.1 – 8.3 +| Nette Application 3.1 | PHP 7.2 – 8.3 | Aplicativo Nette 3.0 | PHP 7.1 - 8.0 | Aplicação Nette 2.4 | PHP 5.6 - 8.0 diff --git a/application/ro/@home.texy b/application/ro/@home.texy index 8a8c11fbf4..09746df1db 100644 --- a/application/ro/@home.texy +++ b/application/ro/@home.texy @@ -28,8 +28,8 @@ composer require nette/application | versiune | compatibil cu PHP |-----------|------------------- -| Nette Application 4.0 | PHP 8.0 - 8.2 -| Nette Application 3.1 | PHP 7.2 - 8.2 +| Nette Application 4.0 | PHP 8.1 – 8.3 +| 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 diff --git a/application/ru/@home.texy b/application/ru/@home.texy index 6ba4943c53..82c69a7d04 100644 --- a/application/ru/@home.texy +++ b/application/ru/@home.texy @@ -28,8 +28,8 @@ composer require nette/application | версия пакета | совместимая версия PHP |-----------------------|----------------------- -| Nette Application 4.0 | PHP 8.0 – 8.1 -| Nette Application 3.1 | PHP 7.2 – 8.1 +| Nette Application 4.0 | PHP 8.1 – 8.3 +| 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 diff --git a/application/sl/@home.texy b/application/sl/@home.texy index e78407b83e..0d7d2f3cf2 100644 --- a/application/sl/@home.texy +++ b/application/sl/@home.texy @@ -28,8 +28,8 @@ composer require nette/application | različica | združljivo s PHP |-----------|------------------- -| Nette Application 4.0 | PHP 8.0 - 8.2 -| Nette Application 3.1 | PHP 7.2 - 8.2 +| Nette Application 4.0 | PHP 8.1 – 8.3 +| 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 diff --git a/application/tr/@home.texy b/application/tr/@home.texy index bb31500e7c..dbf1d64801 100644 --- a/application/tr/@home.texy +++ b/application/tr/@home.texy @@ -28,8 +28,8 @@ composer require nette/application | sürüm | PHP ile uyumlu |-----------|------------------- -| Nette Uygulama 4.0 | PHP 8.0 - 8.2 -| Nette Uygulama 3.1 | PHP 7.2 - 8.2 +| Nette Application 4.0 | PHP 8.1 – 8.3 +| Nette Application 3.1 | PHP 7.2 – 8.3 | Nette Uygulama 3.0 | PHP 7.1 - 8.0 | Nette Uygulama 2.4 | PHP 5.6 - 8.0 diff --git a/application/uk/@home.texy b/application/uk/@home.texy index c1bd9272d7..0040712998 100644 --- a/application/uk/@home.texy +++ b/application/uk/@home.texy @@ -28,8 +28,8 @@ composer require nette/application | версія пакета | сумісна версія PHP |-----------------------|----------------------- -| Nette Application 4.0 | PHP 8.0 - 8.1 -| Nette Application 3.1 | PHP 7.2 - 8.1 +| Nette Application 4.0 | PHP 8.1 – 8.3 +| 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 diff --git a/tester/bg/guide.texy b/tester/bg/guide.texy index b5a0d2a4d7..00093815da 100644 --- a/tester/bg/guide.texy +++ b/tester/bg/guide.texy @@ -160,7 +160,7 @@ Tester може да генерира отчети с обща информац | PHP съвместима версия |------------------|------------------- -| Tester 2.5 | PHP 8.0 - 8.2 +| Tester 2.5 | PHP 8.0 – 8.3 | Tester 2.4 | PHP 7.2 - 8.2 | Tester 2.3 | PHP 7.1 - 8.0 | Tester 2.1 - 2.2 | PHP 7.1 - 7.3 diff --git a/tester/cs/guide.texy b/tester/cs/guide.texy index 4b7e290a36..7c30f09214 100644 --- a/tester/cs/guide.texy +++ b/tester/cs/guide.texy @@ -160,7 +160,7 @@ Podporované verze PHP | verze | kompatibilní s PHP |------------------|------------------- -| Tester 2.5 | PHP 8.0 – 8.2 +| Tester 2.5 | PHP 8.0 – 8.3 | Tester 2.4 | PHP 7.2 – 8.2 | Tester 2.3 | PHP 7.1 – 8.0 | Tester 2.1 – 2.2 | PHP 7.1 – 7.3 diff --git a/tester/de/guide.texy b/tester/de/guide.texy index 31b57967bc..a3e2384cd0 100644 --- a/tester/de/guide.texy +++ b/tester/de/guide.texy @@ -160,7 +160,7 @@ Unterstützte PHP-Versionen .[#toc-supported-php-versions] | Version | kompatibel mit PHP |------------------|------------------- -| Tester 2.4 | PHP 7.2 - 8.2 +| Tester 2.5 | PHP 8.0 – 8.3 | Tester 2.3 | PHP 7.1 - 8.0 | Tester 2.1 - 2.2 | PHP 7.1 - 7.3 | Tester 2.0 | PHP 5.6 - 7.3 diff --git a/tester/el/guide.texy b/tester/el/guide.texy index 24bfd0da62..1209212079 100644 --- a/tester/el/guide.texy +++ b/tester/el/guide.texy @@ -160,7 +160,7 @@ PHP 7.4.8 (cli) | php -n | 8 threads | έκδοση | συμβατή με PHP |------------------|------------------- -| Tester 2.5 | PHP 8.0 - 8.2 +| Tester 2.5 | PHP 8.0 – 8.3 | Tester 2.4 | PHP 7.2 - 8.2 | Tester 2.3 | PHP 7.1 - 8.0 | Tester 2.1 - 2.2 | PHP 7.1 - 7.3 diff --git a/tester/en/guide.texy b/tester/en/guide.texy index 6795bc07b4..3e59c0a265 100644 --- a/tester/en/guide.texy +++ b/tester/en/guide.texy @@ -160,7 +160,7 @@ Supported PHP versions | version | compatible with PHP |------------------|------------------- -| Tester 2.5 | PHP 8.0 – 8.2 +| Tester 2.5 | PHP 8.0 – 8.3 | Tester 2.4 | PHP 7.2 – 8.2 | Tester 2.3 | PHP 7.1 – 8.0 | Tester 2.1 – 2.2 | PHP 7.1 – 7.3 diff --git a/tester/es/guide.texy b/tester/es/guide.texy index 03a800b4df..14a90f172e 100644 --- a/tester/es/guide.texy +++ b/tester/es/guide.texy @@ -160,7 +160,7 @@ Versiones de PHP soportadas .[#toc-supported-php-versions] | versión | compatible con PHP |------------------|------------------- -| Tester 2.4 | PHP 7.2 – 8.2 +| Tester 2.5 | PHP 8.0 – 8.3 | Tester 2.3 | PHP 7.1 – 8.0 | Tester 2.1 – 2.2 | PHP 7.1 – 7.3 | Tester 2.0 | PHP 5.6 – 7.3 diff --git a/tester/fr/guide.texy b/tester/fr/guide.texy index 97457945fa..07fde73948 100644 --- a/tester/fr/guide.texy +++ b/tester/fr/guide.texy @@ -160,7 +160,7 @@ Versions PHP prises en charge .[#toc-supported-php-versions] | version | compatible avec PHP |------------------|------------------- -| Tester 2.5 | PHP 8.0 - 8.2 +| Tester 2.5 | PHP 8.0 – 8.3 | Tester 2.4 | PHP 7.2 - 8.2 | Tester 2.3 | PHP 7.1 - 8.0 | Tester 2.1 - 2.2 | PHP 7.1 - 7.3 diff --git a/tester/hu/guide.texy b/tester/hu/guide.texy index d11610bf65..3364f06567 100644 --- a/tester/hu/guide.texy +++ b/tester/hu/guide.texy @@ -160,7 +160,7 @@ Támogatott PHP verziók .[#toc-supported-php-versions] | verzió | kompatibilis a PHP-vel |------------------|------------------- -| Tester 2.5 | PHP 8.0 - 8.2 +| Tester 2.5 | PHP 8.0 – 8.3 | Tester 2.4 | PHP 7.2 - 8.2 | Tester 2.3 | PHP 7.1 - 8.0 | Tester 2.1 - 2.2 | PHP 7.1 - 7.3 diff --git a/tester/it/guide.texy b/tester/it/guide.texy index 33811b8bfb..9055f6dce8 100644 --- a/tester/it/guide.texy +++ b/tester/it/guide.texy @@ -160,7 +160,7 @@ Versioni PHP supportate .[#toc-supported-php-versions] | Versione compatibile con PHP |------------------|------------------- -| Tester 2.5 | PHP 8.0 - 8.2 +| Tester 2.5 | PHP 8.0 – 8.3 | Tester 2.4 | PHP 7.2 - 8.2 | Tester 2.3 | PHP 7.1 - 8.0 | Tester 2.1 - 2.2 | PHP 7.1 - 7.3 diff --git a/tester/pl/guide.texy b/tester/pl/guide.texy index ef741f36ad..6b45f19fad 100644 --- a/tester/pl/guide.texy +++ b/tester/pl/guide.texy @@ -160,7 +160,7 @@ Obsługiwane wersje PHP .[#toc-supported-php-versions] | wersje | kompatybilne z PHP |------------------|------------------- -| Tester 2.5 | PHP 8.0 - 8.2 +| Tester 2.5 | PHP 8.0 – 8.3 | Tester 2.4 | PHP 7.2 - 8.2 | Tester 2.3 | PHP 7.1 - 8.0 | Tester 2.1 - 2.2 | PHP 7.1 - 7.3 diff --git a/tester/pt/guide.texy b/tester/pt/guide.texy index edbe36e3b3..a30c297615 100644 --- a/tester/pt/guide.texy +++ b/tester/pt/guide.texy @@ -160,7 +160,7 @@ Versões PHP suportadas .[#toc-supported-php-versions] | versão | compatível com PHP |------------------|------------------- -| Tester 2.5 | PHP 8.0 - 8.2 +| Tester 2.5 | PHP 8.0 – 8.3 | Tester 2.4 | PHP 7.2 - 8.2 | Tester 2.3 | PHP 7.1 - 8.0 | Tester 2.1 - 2.2 | PHP 7.1 - 7.3 diff --git a/tester/ro/guide.texy b/tester/ro/guide.texy index da369c5d74..ed8c9b083d 100644 --- a/tester/ro/guide.texy +++ b/tester/ro/guide.texy @@ -160,7 +160,7 @@ Versiuni PHP acceptate .[#toc-supported-php-versions] | versiune | compatibil cu PHP |------------------|------------------- -| Tester 2.5 | PHP 8.0 - 8.2 +| Tester 2.5 | PHP 8.0 – 8.3 | Tester 2.4 | PHP 7.2 - 8.2 | Tester 2.3 | PHP 7.1 - 8.0 | Tester 2.1 - 2.2 | PHP 7.1 - 7.3 diff --git a/tester/ru/guide.texy b/tester/ru/guide.texy index fc73305514..789ec0cc63 100644 --- a/tester/ru/guide.texy +++ b/tester/ru/guide.texy @@ -160,7 +160,7 @@ Tester может генерировать отчеты с обзором тог | Версия | совместимая с PHP |------------------|------------------- -| Tester 2.5 | PHP 8.0 - 8.2 +| Tester 2.5 | PHP 8.0 – 8.3 | Tester 2.4 | PHP 7.2 - 8.2 | Tester 2.3 | PHP 7.1 - 8.0 | Tester 2.1 - 2.2 | PHP 7.1 - 7.3 diff --git a/tester/sl/guide.texy b/tester/sl/guide.texy index a7d4c6ead5..75f55d6c7d 100644 --- a/tester/sl/guide.texy +++ b/tester/sl/guide.texy @@ -160,7 +160,7 @@ Podprte različice PHP .[#toc-supported-php-versions] | različica | združljiva s PHP |------------------|------------------- -| Tester 2.5 | PHP 8.0 - 8.2 +| Tester 2.5 | PHP 8.0 – 8.3 | Tester 2.4 | PHP 7.2 - 8.2 | Tester 2.3 | PHP 7.1 - 8.0 | Tester 2.1 - 2.2 | PHP 7.1 - 7.3 diff --git a/tester/tr/guide.texy b/tester/tr/guide.texy index 1dcee56145..faf21f3233 100644 --- a/tester/tr/guide.texy +++ b/tester/tr/guide.texy @@ -160,7 +160,7 @@ Desteklenen PHP sürümleri .[#toc-supported-php-versions] | sürüm | PHP ile uyumlu |------------------|------------------- -| Tester 2.5 | PHP 8.0 - 8.2 +| Tester 2.5 | PHP 8.0 – 8.3 | Tester 2.4 | PHP 7.2 - 8.2 | Tester 2.3 | PHP 7.1 - 8.0 | Tester 2.1 - 2.2 | PHP 7.1 - 7.3 diff --git a/tester/uk/guide.texy b/tester/uk/guide.texy index ca06db82f4..336f833c8b 100644 --- a/tester/uk/guide.texy +++ b/tester/uk/guide.texy @@ -160,7 +160,7 @@ Tester може генерувати звіти з оглядом того, як | Версія | сумісна з PHP |------------------|------------------- -| Tester 2.5 | PHP 8.0 - 8.2 +| Tester 2.5 | PHP 8.0 – 8.3 | Tester 2.4 | PHP 7.2 - 8.2 | Tester 2.3 | PHP 7.1 - 8.0 | Tester 2.1 - 2.2 | PHP 7.1 - 7.3 diff --git a/tracy/bg/guide.texy b/tracy/bg/guide.texy index 4a74e8c5b3..7f02e5194b 100644 --- a/tracy/bg/guide.texy +++ b/tracy/bg/guide.texy @@ -194,7 +194,7 @@ Debugger::$email = 'admin@example.com'; | Tracy | съвместим с PHP |-----------|-------------------- -| Tracy 2.10 – 3.0 | PHP 8.0 - 8.2 +| Tracy 2.10 – 3.0 | PHP 8.0 – 8.3 | Tracy 2.9 | PHP 7.2 - 8.2 | Tracy 2.8 | PHP 7.2 - 8.1 | Tracy 2.6 - 2.7 | PHP 7.1 - 8.0 diff --git a/tracy/cs/guide.texy b/tracy/cs/guide.texy index a64e50a135..4618a97896 100644 --- a/tracy/cs/guide.texy +++ b/tracy/cs/guide.texy @@ -194,7 +194,7 @@ Podporované verze PHP | Tracy | kompatibilní s PHP |-----------|------------------- -| Tracy 2.10 – 3.0 | PHP 8.0 – 8.2 +| Tracy 2.10 – 3.0 | PHP 8.0 – 8.3 | Tracy 2.9 | PHP 7.2 – 8.2 | Tracy 2.8 | PHP 7.2 – 8.1 | Tracy 2.6 – 2.7 | PHP 7.1 – 8.0 diff --git a/tracy/de/guide.texy b/tracy/de/guide.texy index 453e31a580..dca709877b 100644 --- a/tracy/de/guide.texy +++ b/tracy/de/guide.texy @@ -194,7 +194,7 @@ Unterstützte PHP-Versionen .[#toc-supported-php-versions] | Tracy ist kompatibel mit PHP |-----------|-------------------- -| Tracy 2.10 – 3.0 | PHP 8.0 - 8.2 +| Tracy 2.10 – 3.0 | PHP 8.0 – 8.3 | Tracy 2.9 | PHP 7.2 - 8.2 | Tracy 2.8 | PHP 7.2 - 8.1 | Tracy 2.6 - 2.7 | PHP 7.1 - 8.0 diff --git a/tracy/el/guide.texy b/tracy/el/guide.texy index f942fa71e8..a4b3b189da 100644 --- a/tracy/el/guide.texy +++ b/tracy/el/guide.texy @@ -194,7 +194,7 @@ Debugger::$email = 'admin@example.com'; | Tracy | συμβατή με PHP |-----------|-------------------- -| Tracy 2.10 – 3.0 | PHP 8.0 - 8.2 +| Tracy 2.10 – 3.0 | PHP 8.0 – 8.3 | Tracy 2.9 | PHP 7.2 - 8.2 | Tracy 2.8 | PHP 7.2 - 8.1 | Tracy 2.6 - 2.7 | PHP 7.1 - 8.0 diff --git a/tracy/en/guide.texy b/tracy/en/guide.texy index 94b755fbcf..493464b82b 100644 --- a/tracy/en/guide.texy +++ b/tracy/en/guide.texy @@ -194,7 +194,7 @@ Supported PHP Versions | Tracy | compatible with PHP |-----------|-------------------- -| Tracy 2.10 – 3.0 | PHP 8.0 – 8.2 +| Tracy 2.10 – 3.0 | PHP 8.0 – 8.3 | Tracy 2.9 | PHP 7.2 – 8.2 | Tracy 2.8 | PHP 7.2 – 8.1 | Tracy 2.6 – 2.7 | PHP 7.1 – 8.0 diff --git a/tracy/es/guide.texy b/tracy/es/guide.texy index 3538ea6275..3dda7e20c6 100644 --- a/tracy/es/guide.texy +++ b/tracy/es/guide.texy @@ -194,7 +194,7 @@ Versiones de PHP soportadas .[#toc-supported-php-versions] | Tracy | compatible con PHP |-----------|-------------------- -| Tracy 2.10 – 3.0 | PHP 8.0 – 8.2 +| Tracy 2.10 – 3.0 | PHP 8.0 – 8.3 | Tracy 2.9 | PHP 7.2 – 8.2 | Tracy 2.8 | PHP 7.2 – 8.1 | Tracy 2.6 – 2.7 | PHP 7.1 – 8.0 diff --git a/tracy/fr/guide.texy b/tracy/fr/guide.texy index de2abc975f..ef05be251b 100644 --- a/tracy/fr/guide.texy +++ b/tracy/fr/guide.texy @@ -194,7 +194,7 @@ Versions de PHP prises en charge .[#toc-supported-php-versions] | Tracy | compatible avec PHP |-----------|-------------------- -| Tracy 2.10 – 3.0 | PHP 8.0 - 8.2 +| Tracy 2.10 – 3.0 | PHP 8.0 – 8.3 | Tracy 2.9 | PHP 7.2 - 8.2 | Tracy 2.8 | PHP 7.2 - 8.1 | Tracy 2.6 - 2.7 | PHP 7.1 - 8.0 diff --git a/tracy/hu/guide.texy b/tracy/hu/guide.texy index 31dec6942e..f673ea18b4 100644 --- a/tracy/hu/guide.texy +++ b/tracy/hu/guide.texy @@ -194,7 +194,7 @@ Támogatott PHP-verziók .[#toc-supported-php-versions] | Tracy | kompatibilis a PHP-vel |-----------|-------------------- -| Tracy 2.10 – 3.0 | PHP 8.0 - 8.2 +| Tracy 2.10 – 3.0 | PHP 8.0 – 8.3 | Tracy 2.9 | PHP 7.2 - 8.2 | Tracy 2.8 | PHP 7.2 - 8.1 | Tracy 2.6 - 2.7 | PHP 7.1 - 8.0 diff --git a/tracy/it/guide.texy b/tracy/it/guide.texy index 4657d2e8d7..53a6fd9d97 100644 --- a/tracy/it/guide.texy +++ b/tracy/it/guide.texy @@ -194,7 +194,7 @@ Versioni PHP supportate .[#toc-supported-php-versions] | Tracy | compatibile con PHP |-----------|-------------------- -| Tracy 2.10 – 3.0 | PHP 8.0 - 8.2 +| Tracy 2.10 – 3.0 | PHP 8.0 – 8.3 | Tracy 2.9 | PHP 7.2 - 8.2 | Tracy 2.8 | PHP 7.2 - 8.1 | Tracy 2.6 - 2.7 | PHP 7.1 - 8.0 diff --git a/tracy/pl/guide.texy b/tracy/pl/guide.texy index b59b619280..3fee6d403b 100644 --- a/tracy/pl/guide.texy +++ b/tracy/pl/guide.texy @@ -194,7 +194,7 @@ Obsługiwane wersje PHP .[#toc-supported-php-versions] | Tracy | kompatybilny z PHP |-----------|------------------- -| Tracy 2.10 – 3.0 | PHP 8.0 - 8.2 +| Tracy 2.10 – 3.0 | PHP 8.0 – 8.3 | Tracy 2.9 | PHP 7.2 - 8.2 | Tracy 2.8 | PHP 7.2 - 8.1 | Tracy 2.6 - 2.7 | PHP 7.1 - 8.0 diff --git a/tracy/pt/guide.texy b/tracy/pt/guide.texy index 5350ab840e..476aab5229 100644 --- a/tracy/pt/guide.texy +++ b/tracy/pt/guide.texy @@ -194,7 +194,7 @@ Versões PHP suportadas .[#toc-supported-php-versions] | Tracy | compatível com PHP |-----------|-------------------- -| Tracy 2.10 – 3.0 | PHP 8.0 - 8.2 +| Tracy 2.10 – 3.0 | PHP 8.0 – 8.3 | Tracy 2.9 | PHP 7.2 - 8.2 | Tracy 2.8 | PHP 7.2 - 8.1 | Tracy 2.6 - 2.7 | PHP 7.1 - 8.0 diff --git a/tracy/ro/guide.texy b/tracy/ro/guide.texy index d289faf636..3464b344dd 100644 --- a/tracy/ro/guide.texy +++ b/tracy/ro/guide.texy @@ -194,7 +194,7 @@ Versiuni PHP acceptate .[#toc-supported-php-versions] | Tracy | compatibil cu PHP |-----------|-------------------- -| Tracy 2.10 – 3.0 | PHP 8.0 - 8.2 +| Tracy 2.10 – 3.0 | PHP 8.0 – 8.3 | Tracy 2.9 | PHP 7.2 - 8.2 | Tracy 2.8 | PHP 7.2 - 8.1 | Tracy 2.6 - 2.7 | PHP 7.1 - 8.0 diff --git a/tracy/ru/guide.texy b/tracy/ru/guide.texy index 93f029345a..9bb45f5c79 100644 --- a/tracy/ru/guide.texy +++ b/tracy/ru/guide.texy @@ -194,7 +194,7 @@ Debugger::$email = 'admin@example.com'; | Tracy | совместимые с PHP |-----------|-------------------- -| Tracy 2.10 – 3.0 | PHP 8.0 - 8.2 +| Tracy 2.10 – 3.0 | PHP 8.0 – 8.3 | Tracy 2.9 | PHP 7.2 - 8.2 | Tracy 2.8 | PHP 7.2 - 8.1 | Трейси 2.6 - 2.7 | PHP 7.1 - 8.0 diff --git a/tracy/sl/guide.texy b/tracy/sl/guide.texy index 3a411e57c7..c70a9d11c1 100644 --- a/tracy/sl/guide.texy +++ b/tracy/sl/guide.texy @@ -194,7 +194,7 @@ Podprte različice PHP .[#toc-supported-php-versions] | Tracy | združljivo s PHP |-----------|-------------------- -| Tracy 2.10 – 3.0 | PHP 8.0 - 8.2 +| Tracy 2.10 – 3.0 | PHP 8.0 – 8.3 | Tracy 2.9 | PHP 7.2 - 8.2 | Tracy 2.8 | PHP 7.2 - 8.1 | Tracy 2.6 - 2.7 | PHP 7.1 - 8.0 diff --git a/tracy/tr/guide.texy b/tracy/tr/guide.texy index 30b5ded8b0..c8fe4b935f 100644 --- a/tracy/tr/guide.texy +++ b/tracy/tr/guide.texy @@ -194,7 +194,7 @@ Desteklenen PHP Sürümleri .[#toc-supported-php-versions] | Tracy | PHP ile uyumlu |-----------|-------------------- -| Tracy 2.10 – 3.0 | PHP 8.0 - 8.2 +| Tracy 2.10 – 3.0 | PHP 8.0 – 8.3 | Tracy 2.9 | PHP 7.2 - 8.2 | Tracy 2.8 | PHP 7.2 - 8.1 | Tracy 2.6 - 2.7 | PHP 7.1 - 8.0 diff --git a/tracy/uk/guide.texy b/tracy/uk/guide.texy index 6761dcd4bb..33bb2359eb 100644 --- a/tracy/uk/guide.texy +++ b/tracy/uk/guide.texy @@ -194,7 +194,7 @@ Debugger::$email = 'admin@example.com'; | Tracy | сумісні з PHP |-----------|-------------------- -| Tracy 2.10 – 3.0 | PHP 8.0 - 8.2 +| Tracy 2.10 – 3.0 | PHP 8.0 – 8.3 | Tracy 2.9 | PHP 7.2 - 8.2 | Tracy 2.8 | PHP 7.2 - 8.1 | Трейсі 2.6 - 2.7 | PHP 7.1 - 8.0 diff --git a/utils/bg/@home.texy b/utils/bg/@home.texy index 468b428942..21e46d7f6c 100644 --- a/utils/bg/@home.texy +++ b/utils/bg/@home.texy @@ -34,8 +34,8 @@ composer require nette/utils | PHP съвместима версия |-----------|------------------- -| Nette Utils 4.0 | PHP 8.0 - 8.2 -| Nette Utils 3.2 | PHP 7.2 - 8.2 +| Nette Utils 4.0 | PHP 8.0 – 8.3 +| Nette Utils 3.2 | PHP 7.2 – 8.3 | Nette Utils 3.0 - 3.1 | PHP 7.1 - 8.0 | Nette Utils 2.5 | PHP 5.6 - 8.0 diff --git a/utils/cs/@home.texy b/utils/cs/@home.texy index a3b1331096..bd9a730b5f 100644 --- a/utils/cs/@home.texy +++ b/utils/cs/@home.texy @@ -34,8 +34,8 @@ composer require nette/utils | verze | kompatibilní s PHP |-----------|------------------- -| Nette Utils 4.0 | PHP 8.0 – 8.2 -| Nette Utils 3.2 | PHP 7.2 – 8.2 +| Nette Utils 4.0 | PHP 8.0 – 8.3 +| Nette Utils 3.2 | PHP 7.2 – 8.3 | Nette Utils 3.0 – 3.1 | PHP 7.1 – 8.0 | Nette Utils 2.5 | PHP 5.6 – 8.0 diff --git a/utils/de/@home.texy b/utils/de/@home.texy index babf795f17..dd67234580 100644 --- a/utils/de/@home.texy +++ b/utils/de/@home.texy @@ -34,8 +34,8 @@ composer require nette/utils | Version | kompatibel mit PHP |-----------|------------------- -| Nette Utils 4.0 | PHP 8.0 - 8.2 -| Nette Utils 3.2 | PHP 7.2 - 8.2 +| Nette Utils 4.0 | PHP 8.0 – 8.3 +| Nette Utils 3.2 | PHP 7.2 – 8.3 | Nette Utils 3.0 - 3.1 | PHP 7.1 - 8.0 | Nette Utils 2.5 | PHP 5.6 - 8.0 diff --git a/utils/el/@home.texy b/utils/el/@home.texy index 8885bebad0..d9739dc497 100644 --- a/utils/el/@home.texy +++ b/utils/el/@home.texy @@ -34,8 +34,8 @@ composer require nette/utils | έκδοση | συμβατό με PHP |-----------|------------------- -| Nette Utils 4.0 | PHP 8.0 - 8.2 -| Nette Utils 3.2 | PHP 7.2 - 8.2 +| Nette Utils 4.0 | PHP 8.0 – 8.3 +| Nette Utils 3.2 | PHP 7.2 – 8.3 | Nette Utils 3.0 - 3.1 | PHP 7.1 - 8.0 | Nette Utils 2.5 | PHP 5.6 - 8.0 diff --git a/utils/en/@home.texy b/utils/en/@home.texy index 6bddedbcfb..470030790b 100644 --- a/utils/en/@home.texy +++ b/utils/en/@home.texy @@ -34,8 +34,8 @@ composer require nette/utils | version | compatible with PHP |-----------|------------------- -| Nette Utils 4.0 | PHP 8.0 – 8.2 -| Nette Utils 3.2 | PHP 7.2 – 8.2 +| Nette Utils 4.0 | PHP 8.0 – 8.3 +| Nette Utils 3.2 | PHP 7.2 – 8.3 | Nette Utils 3.0 – 3.1 | PHP 7.1 – 8.0 | Nette Utils 2.5 | PHP 5.6 – 8.0 diff --git a/utils/es/@home.texy b/utils/es/@home.texy index ecf223d43d..de0038e21f 100644 --- a/utils/es/@home.texy +++ b/utils/es/@home.texy @@ -34,8 +34,8 @@ composer require nette/utils | versión | compatible con PHP |-----------|------------------- -| Nette Utils 4.0 | PHP 8.0 - 8.2 -| Nette Utils 3.2 | PHP 7.2 - 8.2 +| Nette Utils 4.0 | PHP 8.0 – 8.3 +| Nette Utils 3.2 | PHP 7.2 – 8.3 | Nette Utils 3.0 - 3.1 | PHP 7.1 - 8.0 | Nette Utils 2.5 | PHP 5.6 - 8.0 diff --git a/utils/fr/@home.texy b/utils/fr/@home.texy index c9bf7ce122..c22a155f85 100644 --- a/utils/fr/@home.texy +++ b/utils/fr/@home.texy @@ -34,8 +34,8 @@ composer require nette/utils | version | compatible avec PHP |-----------|------------------- -| Nette Utils 4.0 | PHP 8.0 - 8.2 -| Nette Utils 3.2 | PHP 7.2 - 8.2 +| Nette Utils 4.0 | PHP 8.0 – 8.3 +| Nette Utils 3.2 | PHP 7.2 – 8.3 | Nette Utils 3.0 - 3.1 | PHP 7.1 - 8.0 | Nette Utils 2.5 | PHP 5.6 - 8.0 diff --git a/utils/hu/@home.texy b/utils/hu/@home.texy index 9ddc16be73..3ad3dae544 100644 --- a/utils/hu/@home.texy +++ b/utils/hu/@home.texy @@ -34,8 +34,8 @@ composer require nette/utils | verzió | kompatibilis a PHP-vel |-----------|------------------- -| Nette Utils 4.0 | PHP 8.0 - 8.2 -| Nette Utils 3.2 | PHP 7.2 - 8.2 +| Nette Utils 4.0 | PHP 8.0 – 8.3 +| Nette Utils 3.2 | PHP 7.2 – 8.3 | Nette Utils 3.0 - 3.1 | PHP 7.1 - 8.0 | Nette Utils 2.5 | PHP 5.6 - 8.0 diff --git a/utils/it/@home.texy b/utils/it/@home.texy index 9674b40ae9..a3bf3fc8fe 100644 --- a/utils/it/@home.texy +++ b/utils/it/@home.texy @@ -34,8 +34,8 @@ composer require nette/utils | versione | compatibile con PHP |-----------|------------------- -| Nette Utils 4.0 | PHP 8.0 - 8.2 -| Nette Utils 3.2 | PHP 7.2 - 8.2 +| Nette Utils 4.0 | PHP 8.0 – 8.3 +| Nette Utils 3.2 | PHP 7.2 – 8.3 | Nette Utils 3.0 - 3.1 | PHP 7.1 - 8.0 | Nette Utils 2.5 | PHP 5.6 - 8.0 diff --git a/utils/pl/@home.texy b/utils/pl/@home.texy index f53a3669d8..4ae656e9ad 100644 --- a/utils/pl/@home.texy +++ b/utils/pl/@home.texy @@ -34,8 +34,8 @@ composer require nette/utils | wersja zgodna z PHP |-----------|------------------- -| Nette Utils 4.0 | PHP 8.0 - 8.2 -| Nette Utils 3.2 | PHP 7.2 - 8.2 +| Nette Utils 4.0 | PHP 8.0 – 8.3 +| Nette Utils 3.2 | PHP 7.2 – 8.3 | Nette Utils 3.0 - 3.1 | PHP 7.1 - 8.0 | Nette Utils 2.5 | PHP 5.6 - 8.0 diff --git a/utils/pt/@home.texy b/utils/pt/@home.texy index f02fdd62ed..46bff91082 100644 --- a/utils/pt/@home.texy +++ b/utils/pt/@home.texy @@ -34,8 +34,8 @@ composer require nette/utils | versão | compatível com PHP |-----------|------------------- -| Nette Utils 4.0 | PHP 8.0 - 8.2 -| Nette Utils 3.2 | PHP 7.2 - 8.2 +| Nette Utils 4.0 | PHP 8.0 – 8.3 +| Nette Utils 3.2 | PHP 7.2 – 8.3 | Nette Utils 3.0 - 3.1 | PHP 7.1 - 8.0 | Nette Utils 2.5 | PHP 5.6 - 8.0 diff --git a/utils/ro/@home.texy b/utils/ro/@home.texy index bc68166834..c4beaa362e 100644 --- a/utils/ro/@home.texy +++ b/utils/ro/@home.texy @@ -34,8 +34,8 @@ composer require nette/utils | versiune | compatibil cu PHP |-----------|------------------- -| Nette Utils 4.0 | PHP 8.0 - 8.2 -| Nette Utils 3.2 | PHP 7.2 - 8.2 +| Nette Utils 4.0 | PHP 8.0 – 8.3 +| Nette Utils 3.2 | PHP 7.2 – 8.3 | Nette Utils 3.0 - 3.1 | PHP 7.1 - 8.0 | Nette Utils 2.5 | PHP 5.6 - 8.0 diff --git a/utils/ru/@home.texy b/utils/ru/@home.texy index 363d308da6..9a92b30218 100644 --- a/utils/ru/@home.texy +++ b/utils/ru/@home.texy @@ -34,8 +34,8 @@ composer require nette/utils | Версия, совместимая с PHP |-----------|------------------- -| Nette Utils 4.0 | PHP 8.0 - 8.2 -| Nette Utils 3.2 | PHP 7.2 - 8.2 +| Nette Utils 4.0 | PHP 8.0 – 8.3 +| Nette Utils 3.2 | PHP 7.2 – 8.3 | Nette Utils 3.0 - 3.1 | PHP 7.1 - 8.0 | Nette Utils 2.5 | PHP 5.6 - 8.0 diff --git a/utils/sl/@home.texy b/utils/sl/@home.texy index 1d9cedcb7c..b04f690d17 100644 --- a/utils/sl/@home.texy +++ b/utils/sl/@home.texy @@ -34,8 +34,8 @@ composer require nette/utils | različica | združljivo s PHP |-----------|------------------- -| Nette Utils 4.0 | PHP 8.0 - 8.2 -| Nette Utils 3.2 | PHP 7.2 - 8.2 +| Nette Utils 4.0 | PHP 8.0 – 8.3 +| Nette Utils 3.2 | PHP 7.2 – 8.3 | Nette Utils 3.0 - 3.1 | PHP 7.1 - 8.0 | Nette Utils 2.5 | PHP 5.6 - 8.0 diff --git a/utils/tr/@home.texy b/utils/tr/@home.texy index 54c3533daa..5fb8feb8e2 100644 --- a/utils/tr/@home.texy +++ b/utils/tr/@home.texy @@ -34,8 +34,8 @@ composer require nette/utils | sürüm | PHP ile uyumlu |-----------|------------------- -| Nette Utils 4.0 | PHP 8.0 - 8.2 -| Nette Utils 3.2 | PHP 7.2 - 8.2 +| Nette Utils 4.0 | PHP 8.0 – 8.3 +| Nette Utils 3.2 | PHP 7.2 – 8.3 | Nette Utils 3.0 - 3.1 | PHP 7.1 - 8.0 | Nette Utils 2.5 | PHP 5.6 - 8.0 diff --git a/utils/uk/@home.texy b/utils/uk/@home.texy index 5db9800444..d2e35c55b6 100644 --- a/utils/uk/@home.texy +++ b/utils/uk/@home.texy @@ -34,8 +34,8 @@ composer require nette/utils | Версія, сумісна з PHP |-----------|------------------- -| Nette Utils 4.0 | PHP 8.0 - 8.2 -| Nette Utils 3.2 | PHP 7.2 - 8.2 +| Nette Utils 4.0 | PHP 8.0 – 8.3 +| Nette Utils 3.2 | PHP 7.2 – 8.3 | Nette Utils 3.0 - 3.1 | PHP 7.1 - 8.0 | Nette Utils 2.5 | PHP 5.6 - 8.0 From 97064a46208b9e1d0aade51d34388e70ff574102 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 21 Nov 2023 14:51:32 +0100 Subject: [PATCH 038/137] composer: ignore upper boundary --- best-practices/bg/composer.texy | 6 ++++++ best-practices/cs/composer.texy | 6 ++++++ best-practices/de/composer.texy | 6 ++++++ best-practices/el/composer.texy | 6 ++++++ best-practices/en/composer.texy | 6 ++++++ best-practices/es/composer.texy | 6 ++++++ best-practices/fr/composer.texy | 6 ++++++ best-practices/hu/composer.texy | 6 ++++++ best-practices/it/composer.texy | 6 ++++++ best-practices/pl/composer.texy | 6 ++++++ best-practices/pt/composer.texy | 6 ++++++ best-practices/ro/composer.texy | 6 ++++++ best-practices/ru/composer.texy | 6 ++++++ best-practices/sl/composer.texy | 6 ++++++ best-practices/tr/composer.texy | 6 ++++++ best-practices/uk/composer.texy | 6 ++++++ 16 files changed, 96 insertions(+) diff --git a/best-practices/bg/composer.texy b/best-practices/bg/composer.texy index b8a26ebb20..13bf7df4cc 100644 --- a/best-practices/bg/composer.texy +++ b/best-practices/bg/composer.texy @@ -142,6 +142,12 @@ composer require php 8.2.3 --no-update ``` +Пренебрегване на версията на PHP .[#toc-ignoring-php-version] +============================================================= + +Пакетите обикновено посочват както най-ниската версия на PHP, с която са съвместими, така и най-високата версия, с която са тествани. Ако планирате да използвате още по-нова версия на PHP, може би за целите на тестването, Composer ще откаже да инсталира такъв пакет. Решението е да използвате опцията `--ignore-platform-req=php+`, която кара Composer да игнорира горните граници на изискваната версия на PHP. + + Фалшиви доклади .[#toc-false-reports] ===================================== diff --git a/best-practices/cs/composer.texy b/best-practices/cs/composer.texy index 2f0c503870..9ac10dc558 100644 --- a/best-practices/cs/composer.texy +++ b/best-practices/cs/composer.texy @@ -142,6 +142,12 @@ Nebo přímo v souboru `composer.json`: ``` +Ignorování verze PHP +==================== + +Balíčky zpravidla mívají uvedenou jak nejnižší verzi PHP, se kterou jsou kompatibilní, tak i nejvyšší, se kterou jsou testované. Pokud se chystáte používat verzi PHP ještě novější, třeba z důvodu testování, Composer odmítne takový balíček nainstalovat. Řešením je volba `--ignore-platform-req=php+`, která způsobí, že Composer bude ignorovat horní limity požadované verze PHP. + + Planá hlášení ============= diff --git a/best-practices/de/composer.texy b/best-practices/de/composer.texy index eaaa86a842..8910b9e603 100644 --- a/best-practices/de/composer.texy +++ b/best-practices/de/composer.texy @@ -142,6 +142,12 @@ Oder direkt in der Datei "Composer.json": ``` +PHP-Version ignorieren .[#toc-ignoring-php-version] +=================================================== + +Pakete geben normalerweise sowohl die niedrigste Version von PHP an, mit der sie kompatibel sind, als auch die höchste Version, mit der sie getestet wurden. Wenn Sie vorhaben, eine noch neuere Version von PHP zu verwenden, etwa zu Testzwecken, wird Composer die Installation eines solchen Pakets verweigern. Die Lösung besteht darin, die Option `--ignore-platform-req=php+` zu verwenden, die Composer veranlasst, die Obergrenzen der erforderlichen PHP-Version zu ignorieren. + + False Berichte .[#toc-false-reports] ==================================== diff --git a/best-practices/el/composer.texy b/best-practices/el/composer.texy index 0971df08e3..410b88c45a 100644 --- a/best-practices/el/composer.texy +++ b/best-practices/el/composer.texy @@ -142,6 +142,12 @@ composer require php 8.2.3 --no-update ``` +Αγνοώντας την έκδοση PHP .[#toc-ignoring-php-version] +===================================================== + +Τα πακέτα συνήθως καθορίζουν τόσο τη χαμηλότερη έκδοση της PHP με την οποία είναι συμβατά όσο και την υψηλότερη έκδοση με την οποία έχουν δοκιμαστεί. Αν σκοπεύετε να χρησιμοποιήσετε μια ακόμη νεότερη έκδοση της PHP, ίσως για σκοπούς δοκιμής, το Composer θα αρνηθεί να εγκαταστήσει ένα τέτοιο πακέτο. Η λύση είναι να χρησιμοποιήσετε την επιλογή `--ignore-platform-req=php+`, η οποία αναγκάζει το Composer να αγνοήσει τα ανώτερα όρια της απαιτούμενης έκδοσης PHP. + + Ψευδείς αναφορές .[#toc-false-reports] ====================================== diff --git a/best-practices/en/composer.texy b/best-practices/en/composer.texy index e87a29b0f7..bc65bb1c55 100644 --- a/best-practices/en/composer.texy +++ b/best-practices/en/composer.texy @@ -142,6 +142,12 @@ Or directly in the `composer.json` file: ``` +Ignoring PHP Version +==================== + +Packages typically specify both the lowest version of PHP with which they are compatible and the highest version with which they have been tested. If you plan to use an even newer version of PHP, perhaps for testing purposes, Composer will refuse to install such a package. The solution is to use the `--ignore-platform-req=php+` option, which causes Composer to ignore the upper limits of the required PHP version. + + False Reports ============= diff --git a/best-practices/es/composer.texy b/best-practices/es/composer.texy index c550b6a92f..e9fd4a1bf3 100644 --- a/best-practices/es/composer.texy +++ b/best-practices/es/composer.texy @@ -142,6 +142,12 @@ O directamente en el archivo `composer.json`: ``` +Ignorando la versión de PHP .[#toc-ignoring-php-version] +======================================================== + +Los paquetes suelen especificar tanto la versión más baja de PHP con la que son compatibles como la versión más alta con la que han sido probados. Si planea usar una versión aún más nueva de PHP, quizás para propósitos de prueba, Composer se rehusará a instalar dicho paquete. La solución es utilizar la opción `--ignore-platform-req=php+`, que hace que Composer ignore los límites superiores de la versión PHP requerida. + + Informes falsos .[#toc-false-reports] ===================================== diff --git a/best-practices/fr/composer.texy b/best-practices/fr/composer.texy index 485cd78e67..d934b6499d 100644 --- a/best-practices/fr/composer.texy +++ b/best-practices/fr/composer.texy @@ -142,6 +142,12 @@ Ou directement dans le fichier `composer.json` : ``` +Ignorer la version de PHP .[#toc-ignoring-php-version] +====================================================== + +Les paquets spécifient généralement la version la plus basse de PHP avec laquelle ils sont compatibles et la version la plus haute avec laquelle ils ont été testés. Si vous prévoyez d'utiliser une version plus récente de PHP, peut-être à des fins de test, Composer refusera d'installer un tel paquet. La solution est d'utiliser l'option `--ignore-platform-req=php+`, qui permet à Composer d'ignorer les limites supérieures de la version de PHP requise. + + Faux rapports .[#toc-false-reports] =================================== diff --git a/best-practices/hu/composer.texy b/best-practices/hu/composer.texy index a4159ed069..fee65b20c5 100644 --- a/best-practices/hu/composer.texy +++ b/best-practices/hu/composer.texy @@ -142,6 +142,12 @@ Vagy közvetlenül a `composer.json` fájlban: ``` +PHP verzió figyelmen kívül hagyása .[#toc-ignoring-php-version] +=============================================================== + +A csomagok általában megadják a PHP legalacsonyabb verzióját, amellyel kompatibilisek, és a legmagasabb verzióját, amellyel tesztelték őket. Ha a PHP egy még újabb verzióját tervezi használni, esetleg tesztelési céllal, a Composer elutasítja az ilyen csomag telepítését. A megoldás a `--ignore-platform-req=php+` opció használata, amelynek hatására a Composer figyelmen kívül hagyja a szükséges PHP-verzió felső határértékeit. + + Hamis jelentések .[#toc-false-reports] ====================================== diff --git a/best-practices/it/composer.texy b/best-practices/it/composer.texy index c30fc6d908..93f33e4133 100644 --- a/best-practices/it/composer.texy +++ b/best-practices/it/composer.texy @@ -142,6 +142,12 @@ Oppure direttamente nel file `composer.json`: ``` +Ignorare la versione di PHP .[#toc-ignoring-php-version] +======================================================== + +I pacchetti di solito specificano sia la versione più bassa di PHP con cui sono compatibili sia la versione più alta con cui sono stati testati. Se si prevede di usare una versione di PHP ancora più recente, magari a scopo di test, Composer si rifiuterà di installare tale pacchetto. La soluzione è usare l'opzione `--ignore-platform-req=php+`, che fa sì che Composer ignori i limiti superiori della versione PHP richiesta. + + Rapporti falsi .[#toc-false-reports] ==================================== diff --git a/best-practices/pl/composer.texy b/best-practices/pl/composer.texy index f208932801..125441e90d 100644 --- a/best-practices/pl/composer.texy +++ b/best-practices/pl/composer.texy @@ -142,6 +142,12 @@ Lub bezpośrednio w pliku `composer.json`: ``` +Ignorowanie wersji PHP .[#toc-ignoring-php-version] +=================================================== + +Pakiety zazwyczaj określają zarówno najniższą wersję PHP, z którą są kompatybilne, jak i najwyższą wersję, z którą zostały przetestowane. Jeśli planujesz użyć jeszcze nowszej wersji PHP, być może w celach testowych, Composer odmówi instalacji takiego pakietu. Rozwiązaniem jest użycie opcji `--ignore-platform-req=php+`, która powoduje, że Composer ignoruje górne limity wymaganej wersji PHP. + + Fałszywe raporty .[#toc-false-reports] ====================================== diff --git a/best-practices/pt/composer.texy b/best-practices/pt/composer.texy index d6f7112628..a22608c832 100644 --- a/best-practices/pt/composer.texy +++ b/best-practices/pt/composer.texy @@ -142,6 +142,12 @@ Ou diretamente no arquivo `composer.json': ``` +Ignorando a versão do PHP .[#toc-ignoring-php-version] +====================================================== + +Normalmente, os pacotes especificam a versão mais baixa do PHP com a qual são compatíveis e a versão mais alta com a qual foram testados. Se você planeja usar uma versão ainda mais recente do PHP, talvez para fins de teste, o Composer se recusará a instalar esse pacote. A solução é usar a opção `--ignore-platform-req=php+`, que faz com que o Composer ignore os limites superiores da versão do PHP necessária. + + Falsos relatórios .[#toc-false-reports] ======================================= diff --git a/best-practices/ro/composer.texy b/best-practices/ro/composer.texy index ef98ebdb69..a2c5f12e81 100644 --- a/best-practices/ro/composer.texy +++ b/best-practices/ro/composer.texy @@ -142,6 +142,12 @@ Sau direct în fișierul `composer.json`: ``` +Ignorarea versiunii PHP .[#toc-ignoring-php-version] +==================================================== + +Pachetele specifică de obicei atât cea mai mică versiune de PHP cu care sunt compatibile, cât și cea mai mare versiune cu care au fost testate. Dacă intenționați să utilizați o versiune chiar mai nouă de PHP, poate în scopuri de testare, Composer va refuza să instaleze un astfel de pachet. Soluția este de a utiliza opțiunea `--ignore-platform-req=php+`, care face ca Composer să ignore limitele superioare ale versiunii PHP solicitate. + + Rapoarte false .[#toc-false-reports] ==================================== diff --git a/best-practices/ru/composer.texy b/best-practices/ru/composer.texy index 8b6c3fca4a..276a92c29e 100644 --- a/best-practices/ru/composer.texy +++ b/best-practices/ru/composer.texy @@ -142,6 +142,12 @@ composer require php 8.2.3 --no-update ``` +Игнорирование версии PHP .[#toc-ignoring-php-version] +===================================================== + +В пакетах обычно указывается как самая низкая версия PHP, с которой они совместимы, так и самая высокая версия, с которой они были протестированы. Если вы планируете использовать еще более новую версию PHP, возможно, в целях тестирования, Composer откажется устанавливать такой пакет. Решением является использование опции `--ignore-platform-req=php+`, которая заставляет Composer игнорировать верхние границы требуемой версии PHP. + + Ложные отчеты .[#toc-false-reports] =================================== diff --git a/best-practices/sl/composer.texy b/best-practices/sl/composer.texy index 52eb9cc2da..97a8e4ad75 100644 --- a/best-practices/sl/composer.texy +++ b/best-practices/sl/composer.texy @@ -142,6 +142,12 @@ Ali neposredno v datoteki `composer.json`: ``` +Ignoriranje različice PHP .[#toc-ignoring-php-version] +====================================================== + +V paketih je običajno navedena najnižja različica PHP, s katero so združljivi, in najvišja različica, s katero so bili testirani. Če nameravate uporabiti še novejšo različico PHP, morda za namene testiranja, bo Composer zavrnil namestitev takega paketa. Rešitev je uporaba možnosti `--ignore-platform-req=php+`, ki povzroči, da Composer ne upošteva zgornje meje zahtevane različice PHP. + + Napačna poročila .[#toc-false-reports] ====================================== diff --git a/best-practices/tr/composer.texy b/best-practices/tr/composer.texy index 74d2c032f1..c16a3f0864 100644 --- a/best-practices/tr/composer.texy +++ b/best-practices/tr/composer.texy @@ -142,6 +142,12 @@ Veya doğrudan `composer.json` dosyasında: ``` +PHP Sürümünü Yoksayma .[#toc-ignoring-php-version] +================================================== + +Paketler genellikle hem uyumlu oldukları en düşük PHP sürümünü hem de test edildikleri en yüksek sürümü belirtirler. PHP'nin daha yeni bir sürümünü kullanmayı planlıyorsanız, belki de test amacıyla, Composer böyle bir paketi yüklemeyi reddedecektir. Çözüm, Composer'ın gerekli PHP sürümünün üst sınırlarını göz ardı etmesine neden olan `--ignore-platform-req=php+` seçeneğini kullanmaktır. + + Yanlış Raporlar .[#toc-false-reports] ===================================== diff --git a/best-practices/uk/composer.texy b/best-practices/uk/composer.texy index 2eead46d70..edca818c9a 100644 --- a/best-practices/uk/composer.texy +++ b/best-practices/uk/composer.texy @@ -142,6 +142,12 @@ composer require php 8.2.3 --no-update ``` +Ігнорування версії PHP .[#toc-ignoring-php-version] +=================================================== + +Пакунки зазвичай вказують як найнижчу версію PHP, з якою вони сумісні, так і найвищу версію, з якою вони були протестовані. Якщо ви плануєте використовувати ще новішу версію PHP, можливо, з метою тестування, Composer відмовиться встановлювати такий пакунок. Вирішенням проблеми є використання параметра `--ignore-platform-req=php+`, який змушує Composer ігнорувати верхні межі необхідної версії PHP. + + Неправдиві повідомлення .[#toc-false-reports] ============================================= From c62f1181ee5459e8dc2fd492c11726d563c81b55 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sat, 11 Nov 2023 14:25:19 +0100 Subject: [PATCH 039/137] forms 3.1.15 --- forms/bg/controls.texy | 2 +- forms/bg/in-presenter.texy | 2 ++ forms/bg/rendering.texy | 8 ++------ forms/bg/standalone.texy | 2 ++ forms/cs/controls.texy | 2 +- forms/cs/in-presenter.texy | 2 ++ forms/cs/rendering.texy | 8 ++------ forms/cs/standalone.texy | 2 ++ forms/de/controls.texy | 2 +- forms/de/in-presenter.texy | 2 ++ forms/de/rendering.texy | 8 ++------ forms/de/standalone.texy | 2 ++ forms/el/controls.texy | 2 +- forms/el/in-presenter.texy | 2 ++ forms/el/rendering.texy | 8 ++------ forms/el/standalone.texy | 2 ++ forms/en/controls.texy | 2 +- forms/en/in-presenter.texy | 2 ++ forms/en/rendering.texy | 8 ++------ forms/en/standalone.texy | 2 ++ forms/es/controls.texy | 2 +- forms/es/in-presenter.texy | 2 ++ forms/es/rendering.texy | 8 ++------ forms/es/standalone.texy | 2 ++ forms/fr/controls.texy | 2 +- forms/fr/in-presenter.texy | 2 ++ forms/fr/rendering.texy | 8 ++------ forms/fr/standalone.texy | 2 ++ forms/hu/controls.texy | 2 +- forms/hu/in-presenter.texy | 2 ++ forms/hu/rendering.texy | 8 ++------ forms/hu/standalone.texy | 2 ++ forms/it/controls.texy | 2 +- forms/it/in-presenter.texy | 2 ++ forms/it/rendering.texy | 8 ++------ forms/it/standalone.texy | 2 ++ forms/pl/controls.texy | 2 +- forms/pl/in-presenter.texy | 2 ++ forms/pl/rendering.texy | 8 ++------ forms/pl/standalone.texy | 2 ++ forms/pt/controls.texy | 2 +- forms/pt/in-presenter.texy | 2 ++ forms/pt/rendering.texy | 8 ++------ forms/pt/standalone.texy | 2 ++ forms/ro/controls.texy | 2 +- forms/ro/in-presenter.texy | 2 ++ forms/ro/rendering.texy | 8 ++------ forms/ro/standalone.texy | 2 ++ forms/ru/controls.texy | 2 +- forms/ru/in-presenter.texy | 2 ++ forms/ru/rendering.texy | 8 ++------ forms/ru/standalone.texy | 2 ++ forms/sl/controls.texy | 2 +- forms/sl/in-presenter.texy | 2 ++ forms/sl/rendering.texy | 8 ++------ forms/sl/standalone.texy | 2 ++ forms/tr/controls.texy | 2 +- forms/tr/in-presenter.texy | 2 ++ forms/tr/rendering.texy | 8 ++------ forms/tr/standalone.texy | 2 ++ forms/uk/controls.texy | 2 +- forms/uk/in-presenter.texy | 2 ++ forms/uk/rendering.texy | 8 ++------ forms/uk/standalone.texy | 2 ++ latte/bg/tags.texy | 2 -- latte/cs/tags.texy | 2 -- latte/de/tags.texy | 2 -- latte/el/tags.texy | 2 -- latte/en/tags.texy | 2 -- latte/es/tags.texy | 2 -- latte/fr/tags.texy | 2 -- latte/hu/tags.texy | 2 -- latte/it/tags.texy | 2 -- latte/ja/tags.texy | 2 -- latte/pl/tags.texy | 2 -- latte/pt/tags.texy | 2 -- latte/ro/tags.texy | 2 -- latte/ru/tags.texy | 2 -- latte/sl/tags.texy | 2 -- latte/tr/tags.texy | 2 -- latte/uk/tags.texy | 2 -- 81 files changed, 112 insertions(+), 146 deletions(-) diff --git a/forms/bg/controls.texy b/forms/bg/controls.texy index 9c3b11e008..5244af0ddf 100644 --- a/forms/bg/controls.texy +++ b/forms/bg/controls.texy @@ -288,7 +288,7 @@ $form->addTime('time', 'Time:', withSeconds: true) ->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']); ``` -По подразбиране се връща обект `DateTimeImmutable` (с фиктивна дата 1 януари, година 0). Използвайки метода `setFormat()`, можете да зададете [текстов формат |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: +По подразбиране той връща обект `DateTimeImmutable` (с дата 1 януари, година 1). Чрез метода `setFormat()` можете да зададете [текстов формат |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: ```php $form->addTime('time', 'Time:') diff --git a/forms/bg/in-presenter.texy b/forms/bg/in-presenter.texy index 1c885cb270..6a96b8e901 100644 --- a/forms/bg/in-presenter.texy +++ b/forms/bg/in-presenter.texy @@ -294,6 +294,8 @@ class RegistrationFormData $person->setMappedType(PersonFormData::class); ``` +Можете да генерирате предложение за класа данни на формуляра, като използвате метода `Nette\Forms\Blueprint::dataClass($form)`, който ще го отпечата на страницата на браузъра. След това можете просто да щракнете, за да изберете и копирате кода в проекта си. .{data-version:3.1.15} + Множество бутони за изпращане .[#toc-multiple-submit-buttons] ============================================================= diff --git a/forms/bg/rendering.texy b/forms/bg/rendering.texy index c0c764948a..bec4092c41 100644 --- a/forms/bg/rendering.texy +++ b/forms/bg/rendering.texy @@ -11,6 +11,8 @@ [Системата за шаблони Latte |latte:] улеснява значително изчертаването на форми и техните елементи. Първо ще ви покажем как да визуализирате формулярите ръчно, елемент по елемент, за да получите пълен контрол върху кода. По-късно ще ви покажем как да [автоматизирате |#Automatic-Rendering] такова визуализиране. +Можете да имате предложение за шаблон Latte за формуляра, генериран чрез метода `Nette\Forms\Blueprint::latte($form)`, който ще го изведе на страницата на браузъра. След това просто трябва да изберете кода с едно щракване и да го копирате в проекта си. .{data-version:3.1.15} + `{control}` ----------- @@ -88,12 +90,6 @@ protected function createComponentSignInForm(): Form ``` -Код на офертата `{formPrint}` .[#toc-formprint] ------------------------------------------------ - -Можете да генерирате подобен код Latte за формата, като използвате тага `{formPrint}`. Ако го поставите в шаблон, ще видите черновия код вместо обичайното визуализиране. След това просто го изберете и го копирайте в проекта си. - - `{label}` `{input}` ------------------- diff --git a/forms/bg/standalone.texy b/forms/bg/standalone.texy index 4ce57a672e..e65003ddc6 100644 --- a/forms/bg/standalone.texy +++ b/forms/bg/standalone.texy @@ -258,6 +258,8 @@ class RegistrationFormData $person->setMappedType(PersonFormData::class); ``` +Можете да генерирате предложение за класа данни на формуляра, като използвате метода `Nette\Forms\Blueprint::dataClass($form)`, който ще го отпечата на страницата на браузъра. След това можете просто да щракнете, за да изберете и копирате кода в проекта си. .{data-version:3.1.15} + Множество бутони за изпращане .[#toc-multiple-submit-buttons] ============================================================= diff --git a/forms/cs/controls.texy b/forms/cs/controls.texy index a644c150b1..a2deebc6b2 100644 --- a/forms/cs/controls.texy +++ b/forms/cs/controls.texy @@ -288,7 +288,7 @@ $form->addTime('time', 'Čas:', withSeconds: true) ->addRule($form::Range, 'Čas musí být v rozsahu od %d do %d.', ['12:30', '13:30']); ``` -Standardně vrací objekt `DateTimeImmutable` (s fiktivním datem 1. ledna roku 0), metodou `setFormat()` můžete specifikovat [textový formát|https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: +Standardně vrací objekt `DateTimeImmutable` (s datem 1. ledna roku 1), metodou `setFormat()` můžete specifikovat [textový formát|https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: ```php $form->addTime('time', 'Čas:') diff --git a/forms/cs/in-presenter.texy b/forms/cs/in-presenter.texy index 4368a100dc..e8d3bddccd 100644 --- a/forms/cs/in-presenter.texy +++ b/forms/cs/in-presenter.texy @@ -294,6 +294,8 @@ Mapování pak z typu property `$person` pozná, že má kontejner mapovat na t $person->setMappedType(PersonFormData::class); ``` +Návrh datové třídy formuláře si můžete nechat vygenerovat pomocí metody `Nette\Forms\Blueprint::dataClass($form)`, která ji vypíše do stránky prohlížeče. Kód pak stačí kliknutím označit a zkopírovat do projektu. .{data-version:3.1.15} + Více tlačítek ============= diff --git a/forms/cs/rendering.texy b/forms/cs/rendering.texy index 91217dba87..7251511ac6 100644 --- a/forms/cs/rendering.texy +++ b/forms/cs/rendering.texy @@ -11,6 +11,8 @@ Vykreslení pomocí Latte [Šablonovací sytém Latte|latte:] zásadně usnadňuje vykreslení formulářů a jejich prvků. Nejprve si ukážeme, jak formuláře vykreslovat ručně po jednotlivých prvcích a tím získat plnou kontrolu nad kódem. Později si ukážeme, jak lze takové vykreslování [zautomatizovat |#Automatické vykreslování]. +Návrh Latte šablony formuláře si můžete nechat vygenerovat pomocí metody `Nette\Forms\Blueprint::latte($form)`, která jej vypíše do stránky prohlížeče. Kód pak stačí kliknutím označit a zkopírovat do projektu. .{data-version:3.1.15} + `{control}` ----------- @@ -88,12 +90,6 @@ Složitější formulářové prvky, jako je RadioList nebo CheckboxList, lze ta ``` -Návrh kódu `{formPrint}` .[#toc-formprint] ------------------------------------------- - -Podobný Latte kód pro formulář si můžete nechat vygenerovat pomocí značky `{formPrint}`. Pokud ji umístíte do šablony, místo běžného vykreslení se zobrazí návrh kódu. Ten pak stačí označit a zkopírovat do projektu. - - `{label}` `{input}` ------------------- diff --git a/forms/cs/standalone.texy b/forms/cs/standalone.texy index ce1a572842..9fb0ae7e00 100644 --- a/forms/cs/standalone.texy +++ b/forms/cs/standalone.texy @@ -258,6 +258,8 @@ Mapování pak z typu property `$person` pozná, že má kontejner mapovat na t $person->setMappedType(PersonFormData::class); ``` +Návrh datové třídy formuláře si můžete nechat vygenerovat pomocí metody `Nette\Forms\Blueprint::dataClass($form)`, která ji vypíše do stránky prohlížeče. Kód pak stačí kliknutím označit a zkopírovat do projektu. .{data-version:3.1.15} + Více tlačítek ============= diff --git a/forms/de/controls.texy b/forms/de/controls.texy index 8a93444ebc..2fd101e085 100644 --- a/forms/de/controls.texy +++ b/forms/de/controls.texy @@ -288,7 +288,7 @@ $form->addTime('time', 'Time:', withSeconds: true) ->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']); ``` -Standardmäßig wird ein `DateTimeImmutable` -Objekt (mit dem fiktiven Datum des 1. Januar, Jahr 0) zurückgegeben. Mit der Methode `setFormat()` können Sie ein [Textformat |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] angeben: +Standardmäßig wird ein Objekt `DateTimeImmutable` (mit dem Datum des 1. Januar, Jahr 1) zurückgegeben. Mit der Methode `setFormat()` können Sie ein [Textformat |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] angeben: ```php $form->addTime('time', 'Time:') diff --git a/forms/de/in-presenter.texy b/forms/de/in-presenter.texy index f7f4f18008..5397143c73 100644 --- a/forms/de/in-presenter.texy +++ b/forms/de/in-presenter.texy @@ -294,6 +294,8 @@ Das Mapping weiß dann anhand des Eigenschaftstyps `$person`, dass es den Contai $person->setMappedType(PersonFormData::class); ``` +Mit der Methode `Nette\Forms\Blueprint::dataClass($form)` können Sie einen Vorschlag für die Datenklasse eines Formulars erzeugen, der auf der Browserseite ausgedruckt wird. Sie können dann einfach auf den Code klicken, um ihn auszuwählen und in Ihr Projekt zu kopieren. .{data-version:3.1.15} + Mehrere Submit-Buttons .[#toc-multiple-submit-buttons] ====================================================== diff --git a/forms/de/rendering.texy b/forms/de/rendering.texy index 6e17b34c4b..5ef819abfd 100644 --- a/forms/de/rendering.texy +++ b/forms/de/rendering.texy @@ -11,6 +11,8 @@ Rendering mit Latte .[#toc-rendering-with-latte] Das [Latte-Templating-System |latte:] erleichtert das Rendern von Formularen und ihren Elementen grundlegend. Wir werden zunächst zeigen, wie man Formulare manuell, Element für Element, rendern kann, um die volle Kontrolle über den Code zu erhalten. Später werden wir zeigen, wie man dieses Rendering [automatisieren |#Automatic rendering] kann. +Mit der Methode `Nette\Forms\Blueprint::latte($form)` können Sie sich den Vorschlag einer Lattenvorlage für das Formular generieren lassen, der dann auf der Browser-Seite ausgegeben wird. Dann brauchen Sie den Code nur noch mit einem Klick auszuwählen und in Ihr Projekt zu kopieren. .{data-version:3.1.15} + `{control}` ----------- @@ -88,12 +90,6 @@ Komplexere Formularelemente, wie z. B. RadioList oder CheckboxList, können Elem ``` -Code-Vorschlag `{formPrint}` .[#toc-formprint] ----------------------------------------------- - -Sie können einen ähnlichen Latte-Code für ein Formular mit dem Tag `{formPrint}` erzeugen. Wenn Sie ihn in eine Vorlage einfügen, sehen Sie den Code-Entwurf anstelle des normalen Renderings. Wählen Sie ihn dann einfach aus und kopieren Sie ihn in Ihr Projekt. - - `{label}` `{input}` ------------------- diff --git a/forms/de/standalone.texy b/forms/de/standalone.texy index 039c051a97..1807af5161 100644 --- a/forms/de/standalone.texy +++ b/forms/de/standalone.texy @@ -258,6 +258,8 @@ Das Mapping weiß dann anhand des Eigenschaftstyps `$person`, dass es den Contai $person->setMappedType(PersonFormData::class); ``` +Mit der Methode `Nette\Forms\Blueprint::dataClass($form)` können Sie einen Vorschlag für die Datenklasse eines Formulars erzeugen, der auf der Browserseite ausgedruckt wird. Sie können dann einfach auf den Code klicken, um ihn auszuwählen und in Ihr Projekt zu kopieren. .{data-version:3.1.15} + Mehrere Submit-Buttons .[#toc-multiple-submit-buttons] ====================================================== diff --git a/forms/el/controls.texy b/forms/el/controls.texy index 12f94bb294..de94ce19b1 100644 --- a/forms/el/controls.texy +++ b/forms/el/controls.texy @@ -288,7 +288,7 @@ $form->addTime('time', 'Time:', withSeconds: true) ->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']); ``` -Από προεπιλογή, επιστρέφει ένα αντικείμενο `DateTimeImmutable` (με φανταστική ημερομηνία την 1η Ιανουαρίου του έτους 0). Χρησιμοποιώντας τη μέθοδο `setFormat()`, μπορείτε να καθορίσετε μια [μορφή κειμένου |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: +Από προεπιλογή, επιστρέφει ένα αντικείμενο `DateTimeImmutable` (με ημερομηνία 1 Ιανουαρίου, έτος 1). Χρησιμοποιώντας τη μέθοδο `setFormat()`, μπορείτε να καθορίσετε μια [μορφή κειμένου |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: ```php $form->addTime('time', 'Time:') diff --git a/forms/el/in-presenter.texy b/forms/el/in-presenter.texy index d0ea92b9b2..ee4a9f9280 100644 --- a/forms/el/in-presenter.texy +++ b/forms/el/in-presenter.texy @@ -294,6 +294,8 @@ class RegistrationFormData $person->setMappedType(PersonFormData::class); ``` +Μπορείτε να δημιουργήσετε μια πρόταση για την κλάση δεδομένων μιας φόρμας χρησιμοποιώντας τη μέθοδο `Nette\Forms\Blueprint::dataClass($form)`, η οποία θα την εκτυπώσει στη σελίδα του προγράμματος περιήγησης. Στη συνέχεια, μπορείτε απλά να κάνετε κλικ για να επιλέξετε και να αντιγράψετε τον κώδικα στο έργο σας. .{data-version:3.1.15} + Πολλαπλά κουμπιά υποβολής .[#toc-multiple-submit-buttons] ========================================================= diff --git a/forms/el/rendering.texy b/forms/el/rendering.texy index ada1f1310e..16de764208 100644 --- a/forms/el/rendering.texy +++ b/forms/el/rendering.texy @@ -11,6 +11,8 @@ Το [σύστημα προτύπων Latte |latte:] διευκολύνει ουσιαστικά την απόδοση των μορφών και των στοιχείων τους. Αρχικά, θα δείξουμε πώς να αποδίδουμε τις φόρμες χειροκίνητα, στοιχείο προς στοιχείο, για να αποκτήσουμε πλήρη έλεγχο του κώδικα. Αργότερα θα δείξουμε πώς να [αυτοματοποιήσουμε |#Automatic rendering] την εν λόγω απόδοση. +Μπορείτε να έχετε την πρόταση ενός προτύπου Latte για τη φόρμα που δημιουργείται χρησιμοποιώντας τη μέθοδο `Nette\Forms\Blueprint::latte($form)`, η οποία θα την εξάγει στη σελίδα του προγράμματος περιήγησης. Στη συνέχεια, πρέπει απλώς να επιλέξετε τον κώδικα με ένα κλικ και να τον αντιγράψετε στο έργο σας. .{data-version:3.1.15} + `{control}` ----------- @@ -88,12 +90,6 @@ protected function createComponentSignInForm(): Form ``` -Πρόταση κώδικα `{formPrint}` .[#toc-formprint] ----------------------------------------------- - -Μπορείτε να δημιουργήσετε έναν παρόμοιο κωδικό Latte για μια φόρμα χρησιμοποιώντας την ετικέτα `{formPrint}`. Αν το τοποθετήσετε σε ένα πρότυπο, θα δείτε το σχέδιο κώδικα αντί για την κανονική απόδοση. Στη συνέχεια, απλά επιλέξτε το και αντιγράψτε το στο έργο σας. - - `{label}` `{input}` ------------------- diff --git a/forms/el/standalone.texy b/forms/el/standalone.texy index 220d7a4da5..ab8a2ff836 100644 --- a/forms/el/standalone.texy +++ b/forms/el/standalone.texy @@ -258,6 +258,8 @@ class RegistrationFormData $person->setMappedType(PersonFormData::class); ``` +Μπορείτε να δημιουργήσετε μια πρόταση για την κλάση δεδομένων μιας φόρμας χρησιμοποιώντας τη μέθοδο `Nette\Forms\Blueprint::dataClass($form)`, η οποία θα την εκτυπώσει στη σελίδα του προγράμματος περιήγησης. Στη συνέχεια, μπορείτε απλά να κάνετε κλικ για να επιλέξετε και να αντιγράψετε τον κώδικα στο έργο σας. .{data-version:3.1.15} + Πολλαπλά κουμπιά υποβολής .[#toc-multiple-submit-buttons] ========================================================= diff --git a/forms/en/controls.texy b/forms/en/controls.texy index 0b116fa600..d81a6cda87 100644 --- a/forms/en/controls.texy +++ b/forms/en/controls.texy @@ -288,7 +288,7 @@ $form->addTime('time', 'Time:', withSeconds: true) ->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']); ``` -By default, it returns a `DateTimeImmutable` object (with a fictitious date of January 1, year 0). Using the `setFormat()` method, you can specify a [text format|https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: +By default, it returns a `DateTimeImmutable` object (with date of January 1, year 1). Using the `setFormat()` method, you can specify a [text format|https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: ```php $form->addTime('time', 'Time:') diff --git a/forms/en/in-presenter.texy b/forms/en/in-presenter.texy index 8a1c7cc2cc..5d2fe73214 100644 --- a/forms/en/in-presenter.texy +++ b/forms/en/in-presenter.texy @@ -294,6 +294,8 @@ The mapping then knows from the `$person` property type that it should map the c $person->setMappedType(PersonFormData::class); ``` +You can generate a proposal for the data class of a form using the method `Nette\Forms\Blueprint::dataClass($form)`, which will print it out to the browser page. You can then simply click to select and copy the code into your project. .{data-version:3.1.15} + Multiple Submit Buttons ======================= diff --git a/forms/en/rendering.texy b/forms/en/rendering.texy index f9eb21279b..7c928d3a25 100644 --- a/forms/en/rendering.texy +++ b/forms/en/rendering.texy @@ -11,6 +11,8 @@ Rendering With Latte The [Latte templating system|latte:] fundamentally facilitates the rendering of forms and their elements. First, we'll show how to render forms manually, element by element, to gain full control over the code. Later we will show how to [automate |#Automatic rendering] such rendering. +You can have the proposal of a Latte template for the form generated using the method `Nette\Forms\Blueprint::latte($form)`, which will output it to the browser page. Then, you simply need to select the code with a click and copy it into your project. .{data-version:3.1.15} + `{control}` ----------- @@ -88,12 +90,6 @@ More complex form elements, such as RadioList or CheckboxList, can be rendered i ``` -Code Proposal `{formPrint}` .[#toc-formprint] ---------------------------------------------- - -You can generate a similar Latte code for a form using the `{formPrint}` tag. If you place it in a template, you will see the draft code instead of the normal rendering. Then just select it and copy it into your project. - - `{label}` `{input}` ------------------- diff --git a/forms/en/standalone.texy b/forms/en/standalone.texy index 1351e51aef..efdd592130 100644 --- a/forms/en/standalone.texy +++ b/forms/en/standalone.texy @@ -258,6 +258,8 @@ The mapping then knows from the `$person` property type that it should map the c $person->setMappedType(PersonFormData::class); ``` +You can generate a proposal for the data class of a form using the method `Nette\Forms\Blueprint::dataClass($form)`, which will print it out to the browser page. You can then simply click to select and copy the code into your project. .{data-version:3.1.15} + Multiple Submit Buttons ======================= diff --git a/forms/es/controls.texy b/forms/es/controls.texy index 92501c63f6..ee3fd2d1db 100644 --- a/forms/es/controls.texy +++ b/forms/es/controls.texy @@ -288,7 +288,7 @@ $form->addTime('time', 'Time:', withSeconds: true) ->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']); ``` -Por defecto, devuelve un objeto `DateTimeImmutable` (con una fecha ficticia del 1 de enero del año 0). Mediante el método `setFormat()`, puede especificar un [formato de texto |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: +Por defecto, devuelve un objeto `DateTimeImmutable` (con fecha de 1 de enero del año 1). Mediante el método `setFormat()`, puede especificar un [formato de texto |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: ```php $form->addTime('time', 'Time:') diff --git a/forms/es/in-presenter.texy b/forms/es/in-presenter.texy index e30d0b8c91..a6d66ed0e3 100644 --- a/forms/es/in-presenter.texy +++ b/forms/es/in-presenter.texy @@ -294,6 +294,8 @@ El mapeo entonces sabe por el tipo de propiedad `$person` que debe mapear el con $person->setMappedType(PersonFormData::class); ``` +Puede generar una propuesta para la clase de datos de un formulario utilizando el método `Nette\Forms\Blueprint::dataClass($form)`, que la imprimirá en la página del navegador. A continuación, puede simplemente hacer clic para seleccionar y copiar el código en su proyecto. .{data-version:3.1.15} + Botones de envío múltiples .[#toc-multiple-submit-buttons] ========================================================== diff --git a/forms/es/rendering.texy b/forms/es/rendering.texy index 41e2d20681..80f4f02f86 100644 --- a/forms/es/rendering.texy +++ b/forms/es/rendering.texy @@ -11,6 +11,8 @@ Renderizado con Latte .[#toc-rendering-with-latte] El [sistema de plantillas |latte:] Latte facilita fundamentalmente el renderizado de formularios y sus elementos. En primer lugar, mostraremos cómo renderizar formularios manualmente, elemento por elemento, para obtener un control total sobre el código. Más adelante mostraremos cómo [automatizar |#Automatic rendering] dicho renderizado. +Usted puede tener la propuesta de una plantilla de Latte para el formulario generado utilizando el método `Nette\Forms\Blueprint::latte($form)`, que le dará salida a la página del navegador. A continuación, sólo tiene que seleccionar el código con un clic y copiarlo en su proyecto. .{data-version:3.1.15} + `{control}` ----------- @@ -88,12 +90,6 @@ Los elementos de formulario más complejos, como RadioList o CheckboxList, puede ``` -Propuesta de código `{formPrint}` .[#toc-formprint] ---------------------------------------------------- - -Puede generar un código Latte similar para un formulario utilizando la etiqueta `{formPrint}`. Si lo colocas en una plantilla, verás el borrador del código en lugar de la representación normal. Luego sólo tienes que seleccionarlo y copiarlo en tu proyecto. - - `{label}` `{input}` ------------------- diff --git a/forms/es/standalone.texy b/forms/es/standalone.texy index c34b775396..79e8ebebd4 100644 --- a/forms/es/standalone.texy +++ b/forms/es/standalone.texy @@ -258,6 +258,8 @@ El mapeo entonces sabe por el tipo de propiedad `$person` que debe mapear el con $person->setMappedType(PersonFormData::class); ``` +Puede generar una propuesta para la clase de datos de un formulario utilizando el método `Nette\Forms\Blueprint::dataClass($form)`, que la imprimirá en la página del navegador. A continuación, puede simplemente hacer clic para seleccionar y copiar el código en su proyecto. .{data-version:3.1.15} + Botones de envío múltiples .[#toc-multiple-submit-buttons] ========================================================== diff --git a/forms/fr/controls.texy b/forms/fr/controls.texy index 6699cffb17..0391594e24 100644 --- a/forms/fr/controls.texy +++ b/forms/fr/controls.texy @@ -288,7 +288,7 @@ $form->addTime('time', 'Time:', withSeconds: true) ->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']); ``` -Par défaut, la méthode renvoie un objet `DateTimeImmutable` (avec une date fictive du 1er janvier de l'année 0). La méthode `setFormat()` permet de spécifier un [format de texte |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: +Par défaut, elle renvoie un objet `DateTimeImmutable` (avec la date du 1er janvier de l'année 1). La méthode `setFormat()` permet de spécifier un [format de texte |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: ```php $form->addTime('time', 'Time:') diff --git a/forms/fr/in-presenter.texy b/forms/fr/in-presenter.texy index 48ef548323..8f8bcb4739 100644 --- a/forms/fr/in-presenter.texy +++ b/forms/fr/in-presenter.texy @@ -294,6 +294,8 @@ Le mappage sait alors, à partir du type de propriété `$person`, qu'il doit ma $person->setMappedType(PersonFormData::class); ``` +Vous pouvez générer une proposition pour la classe de données d'un formulaire à l'aide de la méthode `Nette\Forms\Blueprint::dataClass($form)`, qui l'imprimera sur la page du navigateur. Il vous suffit ensuite de cliquer pour sélectionner et copier le code dans votre projet. .{data-version:3.1.15} + Boutons d'envoi multiples .[#toc-multiple-submit-buttons] ========================================================= diff --git a/forms/fr/rendering.texy b/forms/fr/rendering.texy index 63b89b61ec..fad4bb8bc9 100644 --- a/forms/fr/rendering.texy +++ b/forms/fr/rendering.texy @@ -11,6 +11,8 @@ Rendu avec Latte .[#toc-rendering-with-latte] Le [système de templates Latte |latte:] facilite fondamentalement le rendu des formulaires et de leurs éléments. Nous allons d'abord montrer comment rendre les formulaires manuellement, élément par élément, afin d'avoir un contrôle total sur le code. Plus tard, nous montrerons comment [automatiser |#Automatic rendering] ce rendu. +Vous pouvez obtenir la proposition d'un modèle Latte pour le formulaire généré à l'aide de la méthode `Nette\Forms\Blueprint::latte($form)`, qui l'affichera sur la page du navigateur. Il vous suffit ensuite de sélectionner le code d'un clic et de le copier dans votre projet. .{data-version:3.1.15} + `{control}` ----------- @@ -88,12 +90,6 @@ Les éléments de formulaire plus complexes, tels que RadioList ou CheckboxList, ``` -Proposition de code `{formPrint}` .[#toc-formprint] ---------------------------------------------------- - -Vous pouvez générer un code latte similaire pour un formulaire en utilisant la balise `{formPrint}`. Si vous le placez dans un modèle, vous verrez le projet de code au lieu du rendu normal. Il suffit ensuite de le sélectionner et de le copier dans votre projet. - - `{label}` `{input}` ------------------- diff --git a/forms/fr/standalone.texy b/forms/fr/standalone.texy index 1fe41903b0..10d01bacb4 100644 --- a/forms/fr/standalone.texy +++ b/forms/fr/standalone.texy @@ -258,6 +258,8 @@ Le mappage sait alors, à partir du type de propriété `$person`, qu'il doit ma $person->setMappedType(PersonFormData::class); ``` +Vous pouvez générer une proposition pour la classe de données d'un formulaire à l'aide de la méthode `Nette\Forms\Blueprint::dataClass($form)`, qui l'imprimera sur la page du navigateur. Il vous suffit ensuite de cliquer pour sélectionner et copier le code dans votre projet. .{data-version:3.1.15} + Boutons d'envoi multiples .[#toc-multiple-submit-buttons] ========================================================= diff --git a/forms/hu/controls.texy b/forms/hu/controls.texy index bf607218fe..26dca4e013 100644 --- a/forms/hu/controls.texy +++ b/forms/hu/controls.texy @@ -288,7 +288,7 @@ $form->addTime('time', 'Time:', withSeconds: true) ->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']); ``` -Alapértelmezés szerint egy `DateTimeImmutable` objektumot ad vissza (a 0. év január 1-jei fiktív dátummal). A `setFormat()` módszerrel [szöveges formátumot |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] adhat meg: +Alapértelmezés szerint egy `DateTimeImmutable` objektumot ad vissza (január 1-jei dátummal, 1. év). A `setFormat()` módszerrel [szöveges formátumot |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] adhat meg: ```php $form->addTime('time', 'Time:') diff --git a/forms/hu/in-presenter.texy b/forms/hu/in-presenter.texy index 2a02728cca..70f4742247 100644 --- a/forms/hu/in-presenter.texy +++ b/forms/hu/in-presenter.texy @@ -294,6 +294,8 @@ A leképezés ekkor a `$person` tulajdonságtípusból tudja, hogy a konténert $person->setMappedType(PersonFormData::class); ``` +Egy űrlap adatosztályának javaslatát a `Nette\Forms\Blueprint::dataClass($form)` metódussal generálhatja, amely a böngészőoldalra nyomtatja ki. Ezután egyszerűen rákattintva kiválaszthatja és bemásolhatja a kódot a projektjébe. .{data-version:3.1.15} + Többszörös beküldőgombok .[#toc-multiple-submit-buttons] ======================================================== diff --git a/forms/hu/rendering.texy b/forms/hu/rendering.texy index 5b81534c50..67a8fc3018 100644 --- a/forms/hu/rendering.texy +++ b/forms/hu/rendering.texy @@ -11,6 +11,8 @@ Renderelés Latte-val .[#toc-rendering-with-latte] A [Latte templating rendszer |latte:] alapvetően megkönnyíti az űrlapok és elemeik megjelenítését. Először megmutatjuk, hogyan lehet az űrlapokat manuálisan, elemenként renderelni, hogy teljes kontrollt kapjunk a kód felett. Később megmutatjuk, hogyan lehet [automatizálni |#Automatic rendering] ezt a renderelést. +A `Nette\Forms\Blueprint::latte($form)` metódus segítségével létrehozhatja a Latte sablon javaslatát az űrlaphoz, amely a böngészőoldalra kimeneti azt. Ezután csak ki kell választania a kódot egy kattintással, és be kell másolnia a projektjébe. .{data-version:3.1.15} + `{control}` ----------- @@ -88,12 +90,6 @@ Az összetettebb űrlapelemek, mint például a RadioList vagy CheckboxList, ele ``` -Kódjavaslat `{formPrint}` .[#toc-formprint] -------------------------------------------- - -Hasonló Latte kódot generálhat egy űrlaphoz a `{formPrint}` tag használatával. Ha ezt egy sablonba helyezi, a normál megjelenítés helyett a kódtervezetet fogja látni. Ezután csak válassza ki, és másolja be a projektjébe. - - `{label}` `{input}` ------------------- diff --git a/forms/hu/standalone.texy b/forms/hu/standalone.texy index aa0825b549..385e7ed55c 100644 --- a/forms/hu/standalone.texy +++ b/forms/hu/standalone.texy @@ -258,6 +258,8 @@ A leképezés ekkor a `$person` tulajdonságtípusból tudja, hogy a konténert $person->setMappedType(PersonFormData::class); ``` +Egy űrlap adatosztályának javaslatát a `Nette\Forms\Blueprint::dataClass($form)` metódussal generálhatja, amely a böngészőoldalra nyomtatja ki. Ezután egyszerűen rákattintva kiválaszthatja és bemásolhatja a kódot a projektjébe. .{data-version:3.1.15} + Többszörös beküldőgombok .[#toc-multiple-submit-buttons] ======================================================== diff --git a/forms/it/controls.texy b/forms/it/controls.texy index 2666d0bc36..94163fb023 100644 --- a/forms/it/controls.texy +++ b/forms/it/controls.texy @@ -288,7 +288,7 @@ $form->addTime('time', 'Time:', withSeconds: true) ->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']); ``` -Per impostazione predefinita, restituisce un oggetto `DateTimeImmutable` (con una data fittizia del 1° gennaio, anno 0). Utilizzando il metodo `setFormat()`, è possibile specificare un [formato di testo |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: +Per impostazione predefinita, restituisce un oggetto `DateTimeImmutable` (con data 1 gennaio, anno 1). Utilizzando il metodo `setFormat()`, è possibile specificare un [formato di testo |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: ```php $form->addTime('time', 'Time:') diff --git a/forms/it/in-presenter.texy b/forms/it/in-presenter.texy index d4115962c3..bf398c453b 100644 --- a/forms/it/in-presenter.texy +++ b/forms/it/in-presenter.texy @@ -294,6 +294,8 @@ La mappatura sa quindi dal tipo di proprietà `$person` che deve mappare il cont $person->setMappedType(PersonFormData::class); ``` +È possibile generare una proposta per la classe di dati di un modulo utilizzando il metodo `Nette\Forms\Blueprint::dataClass($form)`, che la stamperà nella pagina del browser. È quindi sufficiente fare clic per selezionare e copiare il codice nel progetto. .{data-version:3.1.15} + Pulsanti di invio multipli .[#toc-multiple-submit-buttons] ========================================================== diff --git a/forms/it/rendering.texy b/forms/it/rendering.texy index 4b009461dc..0cd895a505 100644 --- a/forms/it/rendering.texy +++ b/forms/it/rendering.texy @@ -11,6 +11,8 @@ Rendering con Latte .[#toc-rendering-with-latte] Il [sistema di template Latte |latte:] facilita fondamentalmente il rendering dei moduli e dei loro elementi. In primo luogo, mostreremo come rendere i moduli manualmente, elemento per elemento, per ottenere il pieno controllo sul codice. In seguito mostreremo come [automatizzare |#Automatic rendering] tale rendering. +È possibile far generare la proposta di un modello Latte per il modulo utilizzando il metodo `Nette\Forms\Blueprint::latte($form)`, che lo invierà alla pagina del browser. È quindi sufficiente selezionare il codice con un clic e copiarlo nel progetto. .{data-version:3.1.15} + `{control}` ----------- @@ -88,12 +90,6 @@ Elementi di form più complessi, come RadioList o CheckboxList, possono essere r ``` -Proposta di codice `{formPrint}` .[#toc-formprint] --------------------------------------------------- - -È possibile generare un codice Latte simile per un modulo usando il tag `{formPrint}`. Se lo si inserisce in un modello, si vedrà la bozza di codice invece del normale rendering. È sufficiente selezionarlo e copiarlo nel progetto. - - `{label}` `{input}` ------------------- diff --git a/forms/it/standalone.texy b/forms/it/standalone.texy index d4e81bbb43..5c5a4af305 100644 --- a/forms/it/standalone.texy +++ b/forms/it/standalone.texy @@ -258,6 +258,8 @@ La mappatura sa quindi dal tipo di proprietà `$person` che deve mappare il cont $person->setMappedType(PersonFormData::class); ``` +È possibile generare una proposta per la classe di dati di un modulo utilizzando il metodo `Nette\Forms\Blueprint::dataClass($form)`, che la stamperà nella pagina del browser. È quindi sufficiente fare clic per selezionare e copiare il codice nel progetto. .{data-version:3.1.15} + Pulsanti di invio multipli .[#toc-multiple-submit-buttons] ========================================================== diff --git a/forms/pl/controls.texy b/forms/pl/controls.texy index 758987e551..b21d68a774 100644 --- a/forms/pl/controls.texy +++ b/forms/pl/controls.texy @@ -288,7 +288,7 @@ $form->addTime('time', 'Time:', withSeconds: true) ->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']); ``` -Domyślnie zwraca obiekt `DateTimeImmutable` (z fikcyjną datą 1 stycznia, rok 0). Za pomocą metody `setFormat()` można określić [format tekstowy |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: +Domyślnie zwraca obiekt `DateTimeImmutable` (z datą 1 stycznia, rok 1). Za pomocą metody `setFormat()` można określić [format tekstowy |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: ```php $form->addTime('time', 'Time:') diff --git a/forms/pl/in-presenter.texy b/forms/pl/in-presenter.texy index 60bed90d6e..afa333ac67 100644 --- a/forms/pl/in-presenter.texy +++ b/forms/pl/in-presenter.texy @@ -294,6 +294,8 @@ Mapowanie wie wtedy z typu właściwości `$person`, że powinno mapować konten $person->setMappedType(PersonFormData::class); ``` +Propozycję klasy danych formularza można wygenerować za pomocą metody `Nette\Forms\Blueprint::dataClass($form)`, która wydrukuje ją na stronie przeglądarki. Następnie wystarczy kliknąć, aby wybrać i skopiować kod do swojego projektu. .{data-version:3.1.15} + Więcej przycisków .[#toc-multiple-submit-buttons] ================================================= diff --git a/forms/pl/rendering.texy b/forms/pl/rendering.texy index 9d0e2fa99f..f36104c567 100644 --- a/forms/pl/rendering.texy +++ b/forms/pl/rendering.texy @@ -11,6 +11,8 @@ Rendering z Latte .[#toc-rendering-with-latte] [System szablonów Latte |latte:] zasadniczo ułatwia renderowanie formularzy i ich elementów. Najpierw pokażemy, jak ręcznie renderować formularze element po elemencie i dzięki temu zyskać pełną kontrolę nad kodem. Później pokażemy, jak [zautomatyzować |#Automatické vykreslování] takie renderowanie. +Propozycję szablonu Latte dla formularza można wygenerować za pomocą metody `Nette\Forms\Blueprint::latte($form)`, która wyświetli go na stronie przeglądarki. Następnie wystarczy wybrać kod jednym kliknięciem i skopiować go do swojego projektu. .{data-version:3.1.15} + `{control}` ----------- @@ -88,12 +90,6 @@ Bardziej złożone elementy formularza, takie jak RadioList lub CheckboxList, mo ``` -Projektowanie kodu `{formPrint}` .[#toc-formprint] --------------------------------------------------- - -Możesz mieć podobny kod Latte dla swojego formularza wygenerowanego za pomocą tagu `{formPrint}` Jeśli umieścisz go w szablonie, zobaczysz sugestię kodu zamiast normalnego renderowania. Następnie wystarczy go zaznaczyć i skopiować do swojego projektu. - - `{label}` `{input}` ------------------- diff --git a/forms/pl/standalone.texy b/forms/pl/standalone.texy index 0757691ff0..b397d0f7f7 100644 --- a/forms/pl/standalone.texy +++ b/forms/pl/standalone.texy @@ -258,6 +258,8 @@ Mapowanie wie wtedy z typu właściwości `$person`, że powinno mapować konten $person->setMappedType(PersonFormData::class); ``` +Propozycję klasy danych formularza można wygenerować za pomocą metody `Nette\Forms\Blueprint::dataClass($form)`, która wydrukuje ją na stronie przeglądarki. Następnie wystarczy kliknąć, aby wybrać i skopiować kod do swojego projektu. .{data-version:3.1.15} + Więcej przycisków .[#toc-multiple-submit-buttons] ================================================= diff --git a/forms/pt/controls.texy b/forms/pt/controls.texy index be69298606..0262d6ec77 100644 --- a/forms/pt/controls.texy +++ b/forms/pt/controls.texy @@ -288,7 +288,7 @@ $form->addTime('time', 'Time:', withSeconds: true) ->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']); ``` -Por padrão, ele retorna um objeto `DateTimeImmutable` (com uma data fictícia de 1º de janeiro do ano 0). Usando o método `setFormat()`, você pode especificar um [formato de texto |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: +Por padrão, ele retorna um objeto `DateTimeImmutable` (com data de 1º de janeiro, ano 1). Usando o método `setFormat()`, você pode especificar um [formato de texto |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: ```php $form->addTime('time', 'Time:') diff --git a/forms/pt/in-presenter.texy b/forms/pt/in-presenter.texy index 0312dd2546..a21a2650d3 100644 --- a/forms/pt/in-presenter.texy +++ b/forms/pt/in-presenter.texy @@ -294,6 +294,8 @@ O mapeamento então sabe pelo tipo de propriedade `$person` que deve mapear o co $person->setMappedType(PersonFormData::class); ``` +Você pode gerar uma proposta para a classe de dados de um formulário usando o método `Nette\Forms\Blueprint::dataClass($form)`, que a imprimirá na página do navegador. Em seguida, basta clicar para selecionar e copiar o código em seu projeto. .{data-version:3.1.15} + Botões de submissão múltipla .[#toc-multiple-submit-buttons] ============================================================ diff --git a/forms/pt/rendering.texy b/forms/pt/rendering.texy index 6b3ce19566..5c79a4ffa8 100644 --- a/forms/pt/rendering.texy +++ b/forms/pt/rendering.texy @@ -11,6 +11,8 @@ Renderização com Latte .[#toc-rendering-with-latte] O [sistema de modelos Latte |latte:] facilita fundamentalmente a renderização de formulários e seus elementos. Primeiro, mostraremos como renderizar formulários manualmente, elemento por elemento, para obter controle total sobre o código. Mais tarde, mostraremos como [automatizar |#Automatic rendering] tal renderização. +Você pode ter a proposta de um modelo Latte para o formulário gerado usando o método `Nette\Forms\Blueprint::latte($form)`, que o enviará para a página do navegador. Em seguida, basta selecionar o código com um clique e copiá-lo em seu projeto. .{data-version:3.1.15} + `{control}` ----------- @@ -88,12 +90,6 @@ Elementos de formulário mais complexos, tais como RadioList ou CheckboxList, po ``` -Proposta de Código `{formPrint}` .[#toc-formprint] --------------------------------------------------- - -Você pode gerar um código Latte similar para um formulário usando a tag `{formPrint}`. Se você colocá-lo em um modelo, você verá o rascunho do código ao invés da renderização normal. Então basta selecioná-lo e copiá-lo para seu projeto. - - `{label}` `{input}` ------------------- diff --git a/forms/pt/standalone.texy b/forms/pt/standalone.texy index dafdebe9b8..62d68e1dac 100644 --- a/forms/pt/standalone.texy +++ b/forms/pt/standalone.texy @@ -258,6 +258,8 @@ O mapeamento então sabe pelo tipo de propriedade `$person` que deve mapear o co $person->setMappedType(PersonFormData::class); ``` +Você pode gerar uma proposta para a classe de dados de um formulário usando o método `Nette\Forms\Blueprint::dataClass($form)`, que a imprimirá na página do navegador. Em seguida, basta clicar para selecionar e copiar o código em seu projeto. .{data-version:3.1.15} + Botões de submissão múltipla .[#toc-multiple-submit-buttons] ============================================================ diff --git a/forms/ro/controls.texy b/forms/ro/controls.texy index 78f5294644..6a15ba02e2 100644 --- a/forms/ro/controls.texy +++ b/forms/ro/controls.texy @@ -288,7 +288,7 @@ $form->addTime('time', 'Time:', withSeconds: true) ->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']); ``` -În mod implicit, se returnează un obiect `DateTimeImmutable` (cu o dată fictivă de 1 ianuarie, anul 0). Cu ajutorul metodei `setFormat()`, puteți specifica un [format de text |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: +În mod implicit, se returnează un obiect `DateTimeImmutable` (cu data de 1 ianuarie, anul 1). Cu ajutorul metodei `setFormat()`, puteți specifica un [format de text |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: ```php $form->addTime('time', 'Time:') diff --git a/forms/ro/in-presenter.texy b/forms/ro/in-presenter.texy index be3f4d4a06..86b61b0e37 100644 --- a/forms/ro/in-presenter.texy +++ b/forms/ro/in-presenter.texy @@ -294,6 +294,8 @@ class RegistrationFormData $person->setMappedType(PersonFormData::class); ``` +Puteți genera o propunere pentru clasa de date a unui formular utilizând metoda `Nette\Forms\Blueprint::dataClass($form)`, care o va imprima în pagina browserului. Puteți apoi să dați un simplu clic pentru a selecta și a copia codul în proiectul dumneavoastră. .{data-version:3.1.15} + Butoane de trimitere multiple .[#toc-multiple-submit-buttons] ============================================================= diff --git a/forms/ro/rendering.texy b/forms/ro/rendering.texy index 18eac08c3c..165597a5fa 100644 --- a/forms/ro/rendering.texy +++ b/forms/ro/rendering.texy @@ -11,6 +11,8 @@ Renderizare cu Latte .[#toc-rendering-with-latte] [Sistemul de modelare Latte |latte:] facilitează în mod fundamental redarea formularelor și a elementelor acestora. În primul rând, vom arăta cum să redăm formularele manual, element cu element, pentru a obține un control total asupra codului. Ulterior vom arăta cum să [automatizăm |#Automatic rendering] această redare. +Puteți obține propunerea unui șablon Latte pentru formularul generat cu ajutorul metodei `Nette\Forms\Blueprint::latte($form)`, care îl va afișa în pagina de browser. Apoi, trebuie doar să selectați codul cu un clic și să îl copiați în proiectul dvs. .{data-version:3.1.15} + `{control}` ----------- @@ -88,12 +90,6 @@ Elementele de formular mai complexe, cum ar fi RadioList sau CheckboxList, pot f ``` -Propunere de cod `{formPrint}` .[#toc-formprint] ------------------------------------------------- - -Puteți genera un cod Latte similar pentru un formular folosind eticheta `{formPrint}`. Dacă îl plasați într-un șablon, veți vedea proiectul de cod în loc de redarea normală. Apoi, nu trebuie decât să îl selectați și să îl copiați în proiectul dvs. - - `{label}` `{input}` ------------------- diff --git a/forms/ro/standalone.texy b/forms/ro/standalone.texy index 5427f926c7..69022e8b7f 100644 --- a/forms/ro/standalone.texy +++ b/forms/ro/standalone.texy @@ -258,6 +258,8 @@ class RegistrationFormData $person->setMappedType(PersonFormData::class); ``` +Puteți genera o propunere pentru clasa de date a unui formular utilizând metoda `Nette\Forms\Blueprint::dataClass($form)`, care o va imprima în pagina browserului. Puteți apoi să dați un simplu clic pentru a selecta și a copia codul în proiectul dumneavoastră. .{data-version:3.1.15} + Butoane de trimitere multiple .[#toc-multiple-submit-buttons] ============================================================= diff --git a/forms/ru/controls.texy b/forms/ru/controls.texy index 6c5d18b680..776a4545af 100644 --- a/forms/ru/controls.texy +++ b/forms/ru/controls.texy @@ -288,7 +288,7 @@ $form->addTime('time', 'Time:', withSeconds: true) ->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']); ``` -По умолчанию возвращается объект `DateTimeImmutable` (с фиктивной датой 1 января 0-го года). Используя метод `setFormat()`, можно задать [текстовый формат |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: +По умолчанию он возвращает объект `DateTimeImmutable` (с датой 1 января, год 1). С помощью метода `setFormat()` можно задать [текстовый формат |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: ```php $form->addTime('time', 'Time:') diff --git a/forms/ru/in-presenter.texy b/forms/ru/in-presenter.texy index 76fdfb7969..ff2fa742cf 100644 --- a/forms/ru/in-presenter.texy +++ b/forms/ru/in-presenter.texy @@ -294,6 +294,8 @@ class RegistrationFormData $person->setMappedType(PersonFormData::class); ``` +Сгенерировать предложение для класса данных формы можно с помощью метода `Nette\Forms\Blueprint::dataClass($form)`, который выведет его на страницу браузера. Затем можно просто щелчком мыши выделить и скопировать код в свой проект. .{data-version:3.1.15} + Несколько кнопок отправки .[#toc-multiple-submit-buttons] ========================================================= diff --git a/forms/ru/rendering.texy b/forms/ru/rendering.texy index 1d7ae11cc4..47d135bd62 100644 --- a/forms/ru/rendering.texy +++ b/forms/ru/rendering.texy @@ -11,6 +11,8 @@ [Система шаблонов Latte |latte:] в корне облегчает отрисовку форм и их элементов. Сначала мы покажем, как отрисовывать формы вручную, элемент за элементом, чтобы получить полный контроль над кодом. Позже мы покажем, как [автоматизировать |#Automatic-Rendering] такой рендеринг. +Предложение шаблона Latte для формы можно сгенерировать с помощью метода `Nette\Forms\Blueprint::latte($form)`, который выведет его на страницу браузера. Затем достаточно выделить код щелчком мыши и скопировать его в свой проект. .{data-version:3.1.15} + `{control}` ----------- @@ -88,12 +90,6 @@ protected function createComponentSignInForm(): Form ``` -Предложение кода `{formPrint}` .[#toc-formprint] ------------------------------------------------- - -Вы можете сгенерировать подобный код Latte для формы, используя тег `{formPrint}`. Если вы поместите его в шаблон, вы увидите проект кода вместо обычного рендеринга. Затем просто выделите его и скопируйте в свой проект. - - `{label}` `{input}` ------------------- diff --git a/forms/ru/standalone.texy b/forms/ru/standalone.texy index 1c2a1788e4..0282263b1a 100644 --- a/forms/ru/standalone.texy +++ b/forms/ru/standalone.texy @@ -258,6 +258,8 @@ class RegistrationFormData $person->setMappedType(PersonFormData::class); ``` +Сгенерировать предложение для класса данных формы можно с помощью метода `Nette\Forms\Blueprint::dataClass($form)`, который выведет его на страницу браузера. Затем можно просто щелчком мыши выделить и скопировать код в свой проект. .{data-version:3.1.15} + Несколько кнопок отправки .[#toc-multiple-submit-buttons] ========================================================= diff --git a/forms/sl/controls.texy b/forms/sl/controls.texy index 18e5bd6a36..8395072799 100644 --- a/forms/sl/controls.texy +++ b/forms/sl/controls.texy @@ -288,7 +288,7 @@ $form->addTime('time', 'Time:', withSeconds: true) ->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']); ``` -Privzeto vrne predmet `DateTimeImmutable` (s fiktivnim datumom 1. januar, leto 0). Z metodo `setFormat()` lahko določite [besedilno obliko |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: +Privzeto vrne objekt `DateTimeImmutable` (z datumom 1. januar, leto 1). Z metodo `setFormat()` lahko določite [obliko besedila |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: ```php $form->addTime('time', 'Time:') diff --git a/forms/sl/in-presenter.texy b/forms/sl/in-presenter.texy index cbdc74a127..807a389a7a 100644 --- a/forms/sl/in-presenter.texy +++ b/forms/sl/in-presenter.texy @@ -294,6 +294,8 @@ Prikazovanje nato na podlagi vrste lastnosti `$person` ugotovi, da mora vsebnik $person->setMappedType(PersonFormData::class); ``` +Predlog podatkovnega razreda obrazca lahko ustvarite z metodo `Nette\Forms\Blueprint::dataClass($form)`, ki ga izpiše na strani brskalnika. Nato lahko preprosto kliknete, da izberete in kopirate kodo v svoj projekt. .{data-version:3.1.15} + Več gumbov za pošiljanje .[#toc-multiple-submit-buttons] ======================================================== diff --git a/forms/sl/rendering.texy b/forms/sl/rendering.texy index 7fa34a0c4e..58f4c0e114 100644 --- a/forms/sl/rendering.texy +++ b/forms/sl/rendering.texy @@ -11,6 +11,8 @@ Renderiranje z Latte .[#toc-rendering-with-latte] [Sistem predlog Latte |latte:] bistveno olajša upodabljanje obrazcev in njihovih elementov. Najprej bomo pokazali, kako ročno upodabljati obrazce, element za elementom, da bi pridobili popoln nadzor nad kodo. Kasneje bomo pokazali, kako takšno upodabljanje [avtomatizirati |#Automatic rendering]. +Predlog Latte predloge za obrazec lahko generirate z metodo `Nette\Forms\Blueprint::latte($form)`, ki ga bo izpisala na stran brskalnika. Nato morate kodo preprosto izbrati s klikom in jo kopirati v svoj projekt. .{data-version:3.1.15} + `{control}` ----------- @@ -88,12 +90,6 @@ Kompleksnejše elemente obrazca, kot sta RadioList ali CheckboxList, lahko prika ``` -Predlog kode `{formPrint}` .[#toc-formprint] --------------------------------------------- - -Podobno kodo Latte lahko ustvarite za obrazec z uporabo oznake `{formPrint}`. Če jo vstavite v predlogo, se bo namesto običajnega izrisa prikazal predlog kode. Nato jo preprosto izberite in kopirajte v svoj projekt. - - `{label}` `{input}` ------------------- diff --git a/forms/sl/standalone.texy b/forms/sl/standalone.texy index 3a4a65f195..b10a2ab9f4 100644 --- a/forms/sl/standalone.texy +++ b/forms/sl/standalone.texy @@ -258,6 +258,8 @@ Prikazovanje nato na podlagi vrste lastnosti `$person` ugotovi, da mora vsebnik $person->setMappedType(PersonFormData::class); ``` +Predlog podatkovnega razreda obrazca lahko ustvarite z metodo `Nette\Forms\Blueprint::dataClass($form)`, ki ga izpiše na strani brskalnika. Nato lahko preprosto kliknete, da izberete in kopirate kodo v svoj projekt. .{data-version:3.1.15} + Več gumbov za pošiljanje .[#toc-multiple-submit-buttons] ======================================================== diff --git a/forms/tr/controls.texy b/forms/tr/controls.texy index d67456cd32..2b4ae3a179 100644 --- a/forms/tr/controls.texy +++ b/forms/tr/controls.texy @@ -288,7 +288,7 @@ $form->addTime('time', 'Time:', withSeconds: true) ->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']); ``` -Varsayılan olarak, bir `DateTimeImmutable` nesnesi döndürür (1 Ocak, 0 yılı hayali bir tarihle). `setFormat()` yöntemini kullanarak bir [metin biçimi |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] belirtebilirsiniz: +Varsayılan olarak, bir `DateTimeImmutable` nesnesi döndürür (tarih 1 Ocak, yıl 1). `setFormat()` yöntemini kullanarak bir [metin biçimi |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters] belirtebilirsiniz: ```php $form->addTime('time', 'Time:') diff --git a/forms/tr/in-presenter.texy b/forms/tr/in-presenter.texy index abf4476a85..09764a3ad0 100644 --- a/forms/tr/in-presenter.texy +++ b/forms/tr/in-presenter.texy @@ -294,6 +294,8 @@ Eşleme daha sonra `$person` özellik türünden konteyneri `PersonFormData` sı $person->setMappedType(PersonFormData::class); ``` +Tarayıcı sayfasına yazdıracak olan `Nette\Forms\Blueprint::dataClass($form)` yöntemini kullanarak bir formun veri sınıfı için bir öneri oluşturabilirsiniz. Daha sonra kodu seçmek ve projenize kopyalamak için tıklamanız yeterlidir. .{data-version:3.1.15} + Çoklu Gönder Düğmeleri .[#toc-multiple-submit-buttons] ====================================================== diff --git a/forms/tr/rendering.texy b/forms/tr/rendering.texy index 69676eca2f..a937fd0ecc 100644 --- a/forms/tr/rendering.texy +++ b/forms/tr/rendering.texy @@ -11,6 +11,8 @@ Latte ile Rendering .[#toc-rendering-with-latte] [Latte şablonlama sistemi |latte:], formların ve öğelerinin oluşturulmasını temel olarak kolaylaştırır. İlk olarak, kod üzerinde tam kontrol elde etmek için formların öğe öğe manuel olarak nasıl oluşturulacağını göstereceğiz. Daha sonra bu işlemin nasıl [otomatikleştirileceğini |#Automatic rendering] göstereceğiz. +`Nette\Forms\Blueprint::latte($form)` yöntemini kullanarak oluşturulan form için bir Latte şablonu önerisine sahip olabilirsiniz, bu da tarayıcı sayfasına çıktı verecektir. Ardından, kodu bir tıklama ile seçmeniz ve projenize kopyalamanız yeterlidir. .{data-version:3.1.15} + `{control}` ----------- @@ -88,12 +90,6 @@ RadioList veya CheckboxList gibi daha karmaşık form öğeleri öğe öğe işl ``` -Kod Önerisi `{formPrint}` .[#toc-formprint] -------------------------------------------- - -`{formPrint}` etiketini kullanarak bir form için benzer bir Latte kodu oluşturabilirsiniz. Bunu bir şablona yerleştirirseniz, normal oluşturma yerine taslak kodu görürsünüz. Sonra onu seçin ve projenize kopyalayın. - - `{label}` `{input}` ------------------- diff --git a/forms/tr/standalone.texy b/forms/tr/standalone.texy index 88f05b7924..75b0fbd244 100644 --- a/forms/tr/standalone.texy +++ b/forms/tr/standalone.texy @@ -258,6 +258,8 @@ Eşleme daha sonra `$person` özellik türünden konteyneri `PersonFormData` sı $person->setMappedType(PersonFormData::class); ``` +Tarayıcı sayfasına yazdıracak olan `Nette\Forms\Blueprint::dataClass($form)` yöntemini kullanarak bir formun veri sınıfı için bir öneri oluşturabilirsiniz. Daha sonra kodu seçmek ve projenize kopyalamak için tıklamanız yeterlidir. .{data-version:3.1.15} + Çoklu Gönder Düğmeleri .[#toc-multiple-submit-buttons] ====================================================== diff --git a/forms/uk/controls.texy b/forms/uk/controls.texy index 3391832a95..c13bb1df4f 100644 --- a/forms/uk/controls.texy +++ b/forms/uk/controls.texy @@ -288,7 +288,7 @@ $form->addTime('time', 'Time:', withSeconds: true) ->addRule($form::Range, 'Time must be between %d and %d.', ['12:30', '13:30']); ``` -За замовчуванням повертається об'єкт `DateTimeImmutable` (з фіктивною датою 1 січня 0 року). За допомогою методу `setFormat()` ви можете вказати [текстовий формат |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: +За замовчуванням він повертає об'єкт `DateTimeImmutable` (з датою 1 січня, рік 1). За допомогою методу `setFormat()` ви можете вказати [текстовий формат |https://www.php.net/manual/en/datetime.format.php#refsect1-datetime.format-parameters]: ```php $form->addTime('time', 'Time:') diff --git a/forms/uk/in-presenter.texy b/forms/uk/in-presenter.texy index a3efcfabcc..de72fb81d7 100644 --- a/forms/uk/in-presenter.texy +++ b/forms/uk/in-presenter.texy @@ -294,6 +294,8 @@ class RegistrationFormData $person->setMappedType(PersonFormData::class); ``` +Ви можете згенерувати пропозицію для класу даних форми за допомогою методу `Nette\Forms\Blueprint::dataClass($form)`, який роздрукує її на сторінку браузера. Потім ви можете просто натиснути, щоб вибрати і скопіювати код у свій проект. .{data-version:3.1.15} + Кілька кнопок надсилання .[#toc-multiple-submit-buttons] ======================================================== diff --git a/forms/uk/rendering.texy b/forms/uk/rendering.texy index e45ef5d03d..4bd5722492 100644 --- a/forms/uk/rendering.texy +++ b/forms/uk/rendering.texy @@ -11,6 +11,8 @@ [Система шаблонів Latte |latte:] докорінно полегшує відтворення форм та їхніх елементів. Спочатку ми покажемо, як відтворювати форми вручну, елемент за елементом, щоб отримати повний контроль над кодом. Пізніше ми покажемо, як [автоматизувати |#Automatic-Rendering] такий рендеринг. +Ви можете отримати пропозицію шаблону Latte для форми, згенерованої за допомогою методу `Nette\Forms\Blueprint::latte($form)`, який виведе її на сторінку браузера. Потім вам просто потрібно вибрати код одним клацанням миші і скопіювати його в свій проект. .{data-version:3.1.15} + `{control}` ----------- @@ -88,12 +90,6 @@ protected function createComponentSignInForm(): Form ``` -Пропозиція коду `{formPrint}` .[#toc-formprint] ------------------------------------------------ - -Ви можете згенерувати подібний код Latte для форми, використовуючи тег `{formPrint}`. Якщо ви помістите його в шаблон, ви побачите проєкт коду замість звичайного рендерингу. Потім просто виділіть його та скопіюйте у свій проект. - - `{label}` `{input}` ------------------- diff --git a/forms/uk/standalone.texy b/forms/uk/standalone.texy index ac5a0ff3ad..df8d24bb56 100644 --- a/forms/uk/standalone.texy +++ b/forms/uk/standalone.texy @@ -258,6 +258,8 @@ class RegistrationFormData $person->setMappedType(PersonFormData::class); ``` +Ви можете згенерувати пропозицію для класу даних форми за допомогою методу `Nette\Forms\Blueprint::dataClass($form)`, який роздрукує її на сторінку браузера. Потім ви можете просто натиснути, щоб вибрати і скопіювати код у свій проект. .{data-version:3.1.15} + Кілька кнопок надсилання .[#toc-multiple-submit-buttons] ======================================================== diff --git a/latte/bg/tags.texy b/latte/bg/tags.texy index 582f645e22..24e6ad3834 100644 --- a/latte/bg/tags.texy +++ b/latte/bg/tags.texy @@ -109,8 +109,6 @@ | `{input}` | [отпечатва елемента за влизане във формата|forms:rendering#label-input] | `{inputError}` | [отпечатва съобщението за грешка за елемента за въвеждане на форма |forms:rendering#inputError] | `n:name` [активира входния елемент на HTML |forms:rendering#n:name] -| `{formPrint}` [генерира чертеж на формата Latte |forms:rendering#formPrint] -| `{formPrintClass}` [отпечатва PHP клас за данните от формата |forms:in-presenter#Mapping-to-Classes] | `{formContainer}`... `{/formContainer}` | [визуализиране на контейнера за формуляри |forms:rendering#special-cases] diff --git a/latte/cs/tags.texy b/latte/cs/tags.texy index 49b008f6a3..6725270e1d 100644 --- a/latte/cs/tags.texy +++ b/latte/cs/tags.texy @@ -109,8 +109,6 @@ Přehled a popis všech tagů (neboli značek či maker) šablonovacího systém | `{input}` | [vykreslí formulářový prvek |forms:rendering#label-input] | `{inputError}` | [vypíše chybovou hlášku formulářového prvku |forms:rendering#inputError] | `n:name` | [oživí formulářový prvek |forms:rendering#n:name] -| `{formPrint}` | [navrhne Latte kód pro formulář |forms:rendering#formPrint] -| `{formPrintClass}` | [navrhne PHP kód třídy s daty formuláře |forms:in-presenter#mapovani-na-tridy] | `{formContainer}` … `{/formContainer}` | [kreslení formulářového kontejneru |forms:rendering#specialni-pripady] diff --git a/latte/de/tags.texy b/latte/de/tags.texy index a1073621f7..839cdd7f75 100644 --- a/latte/de/tags.texy +++ b/latte/de/tags.texy @@ -109,8 +109,6 @@ Zusammenfassung und Beschreibung aller in Latte integrierten Tags. | `{input}` | [druckt ein Formulareingabeelement |forms:rendering#label-input] | `{inputError}` | [gibt eine Fehlermeldung für ein Formulareingabeelement aus |forms:rendering#inputError] | `n:name` | [aktiviert ein HTML-Eingabeelement |forms:rendering#n:name] -| `{formPrint}` | [erzeugt einen Latte-Formular-Blaupause |forms:rendering#formPrint] -| `{formPrintClass}` | [gibt PHP-Klasse für Formulardaten aus |forms:in-presenter#mapping-to-classes] | `{formContainer}`... `{/formContainer}` | [Darstellung des Formular-Containers |forms:rendering#special-cases] diff --git a/latte/el/tags.texy b/latte/el/tags.texy index 136ac46e0d..068d3cd0cf 100644 --- a/latte/el/tags.texy +++ b/latte/el/tags.texy @@ -109,8 +109,6 @@ | `{input}` | [εκτυπώνει ένα στοιχείο εισόδου φόρμας |forms:rendering#label-input] | `{inputError}` | [εκτυπώνει μήνυμα σφάλματος για το στοιχείο εισόδου φόρμας |forms:rendering#inputError] | `n:name` | [ενεργοποιεί ένα στοιχείο εισόδου HTML |forms:rendering#n:name] -| `{formPrint}` | [δημιουργεί σχέδιο φόρμας Latte |forms:rendering#formPrint] -| `{formPrintClass}` | [εκτυπώνει κλάση PHP για τα δεδομένα της φόρμας |forms:in-presenter#mapping-to-classes] | `{formContainer}`... `{/formContainer}` | [απόδοση του δοχείου της φόρμας |forms:rendering#special-cases] diff --git a/latte/en/tags.texy b/latte/en/tags.texy index bb1a7d44da..a25ecff68e 100644 --- a/latte/en/tags.texy +++ b/latte/en/tags.texy @@ -109,8 +109,6 @@ Summary and description of all Latte built-in tags. | `{input}` | [prints a form input element |forms:rendering#label-input] | `{inputError}` | [prints error message for form input element|forms:rendering#inputError] | `n:name` | [activates an HTML input element |forms:rendering#n:name] -| `{formPrint}` | [generates Latte form blueprint |forms:rendering#formPrint] -| `{formPrintClass}` | [prints PHP class for form data |forms:in-presenter#mapping-to-classes] | `{formContainer}` … `{/formContainer}` | [rendering the form container |forms:rendering#special-cases] diff --git a/latte/es/tags.texy b/latte/es/tags.texy index d8ce05adc5..d529d1c009 100644 --- a/latte/es/tags.texy +++ b/latte/es/tags.texy @@ -109,8 +109,6 @@ Resumen y descripción de todas las etiquetas Latte incorporadas. | `{input}` | [imprime un elemento del formulario|forms:rendering#label-input] | `{inputError}` | [imprime un mensaje de error para el elemento de entrada del formulario|forms:rendering#inputError] | `n:name` | [activa un elemento de entrada HTML |forms:rendering#n:name] -| `{formPrint}` | [genera un modelo de formulario Latte |forms:rendering#formPrint] -| `{formPrintClass}` | [imprime la clase PHP para los datos del formulario |forms:in-presenter#mapping-to-classes] | `{formContainer}`... `{/formContainer}` | [renderización del contenedor de formularios |forms:rendering#special-cases] diff --git a/latte/fr/tags.texy b/latte/fr/tags.texy index 0d86c53500..2899f54d90 100644 --- a/latte/fr/tags.texy +++ b/latte/fr/tags.texy @@ -109,8 +109,6 @@ Résumé et description de toutes les balises intégrées de Latte. | `{input}` | [imprime un élément de saisie de formulaire |forms:rendering#label-input] | `{inputError}` | [imprime un message d'erreur pour l'élément de saisie du formulaire |forms:rendering#inputError] | `n:name` | [active un élément de saisie HTML |forms:rendering#n:name] -| `{formPrint}` | [génère le plan du formulaire Latte |forms:rendering#formPrint] -| `{formPrintClass}` | [imprime la classe PHP pour les données du formulaire |forms:in-presenter#mapping-to-classes] | `{formContainer}`... `{/formContainer}` | [rendre le conteneur de formulaire |forms:rendering#special-cases] diff --git a/latte/hu/tags.texy b/latte/hu/tags.texy index 72eca3cd27..068aae2a75 100644 --- a/latte/hu/tags.texy +++ b/latte/hu/tags.texy @@ -109,8 +109,6 @@ Az összes beépített Latte-címke összefoglalása és leírása. | `{input}` | [nyomtat egy űrlap beviteli elemet |forms:rendering#label-input] | `{inputError}` | [hibaüzenetet nyomtat az űrlap beviteli eleméhez |forms:rendering#inputError] | `n:name` | [HTML beviteli elem aktiválása |forms:rendering#n:name] -| `{formPrint}` | [Latte űrlap tervezetet készít |forms:rendering#formPrint] -| `{formPrintClass}` | [PHP osztály nyomtatása az űrlap adataihoz |forms:in-presenter#mapping-to-classes] | `{formContainer}`... `{/formContainer}` | [az űrlap tárolójának renderelése |forms:rendering#special-cases] diff --git a/latte/it/tags.texy b/latte/it/tags.texy index 2bb8b2df56..5086c7081e 100644 --- a/latte/it/tags.texy +++ b/latte/it/tags.texy @@ -109,8 +109,6 @@ Riepilogo e descrizione di tutti i tag incorporati di Latte. | `{input}` | [stampa un elemento di input del modulo |forms:rendering#label-input] | `{inputError}` | [stampa il messaggio di errore per l'elemento di input del modulo |forms:rendering#inputError] | `n:name` | [attiva un elemento di input HTML |forms:rendering#n:name] -| `{formPrint}` | [genera il blueprint del modulo Latte |forms:rendering#formPrint] -| `{formPrintClass}` | [stampa la classe PHP per i dati del modulo |forms:in-presenter#mapping-to-classes] | `{formContainer}`... `{/formContainer}` | [rendere il contenitore del modulo |forms:rendering#special-cases] diff --git a/latte/ja/tags.texy b/latte/ja/tags.texy index f2a8060fa3..0737ec276c 100644 --- a/latte/ja/tags.texy +++ b/latte/ja/tags.texy @@ -109,8 +109,6 @@ Latte内蔵の全タグの概要と説明。 |`{input}` |[フォーム入力要素を表示します。|forms:en:rendering#label-input] |`{inputError}` | [フォーム入力要素のエラーメッセージを表示します。|forms:en:rendering#inputError] |`n:name` |[HTML入力要素をアクティブにする|forms:en:rendering#n:name] -|`{formPrint}` |[ラテ型フォームの青写真を生成する|forms:en:rendering#formPrint] -|`{formPrintClass}` |[フォームデータのための PHP クラスを表示する|forms:en:in-presenter#mapping-to-classes] |`{formContainer}`...`{/formContainer}` |[フォームコンテナのレンダリング |forms:en:rendering#special-cases] diff --git a/latte/pl/tags.texy b/latte/pl/tags.texy index a37900883c..d0489ba7dd 100644 --- a/latte/pl/tags.texy +++ b/latte/pl/tags.texy @@ -109,8 +109,6 @@ Przegląd i opis wszystkich znaczników systemu templatek Latte, które są domy | `{input}` | [renderuje element formularza |forms:rendering#label-input] | `{inputError}` | [drukuje komunikat o błędzie elementu formularza |forms:rendering#inputError] | `n:name` | [animuje element formularza |forms:rendering#n:name] -| `{formPrint}` | [projekt kod latte dla formularza |forms:rendering#formPrint] -| `{formPrintClass}` | [zaprojektuj kod PHP dla klasy z danymi formularza |forms:in-presenter#Mapping-to-Classes] | `{formContainer}`... `{/formContainer}` | [renderowanie pojemnika na formularze |forms:rendering#special-cases] diff --git a/latte/pt/tags.texy b/latte/pt/tags.texy index d1181600f8..96620fc6f4 100644 --- a/latte/pt/tags.texy +++ b/latte/pt/tags.texy @@ -109,8 +109,6 @@ Resumo e descrição de todas as etiquetas incorporadas no Latte. | `{input}` | [imprime um elemento de entrada do formulário |forms:rendering#label-input] | `{inputError}` | [imprime mensagem de erro para o elemento de entrada do formulário |forms:rendering#inputError] | `n:name` | [ativa um elemento de entrada HTML |forms:rendering#n:name] -| `{formPrint}` | [gera o projeto do formulário Latte |forms:rendering#formPrint] -| `{formPrintClass}` | [imprime a classe PHP para dados de formulário |forms:in-presenter#mapping-to-classes] | `{formContainer}`... `{/formContainer}` | [tornando o recipiente do formulário |forms:rendering#special-cases] diff --git a/latte/ro/tags.texy b/latte/ro/tags.texy index d60386cc8f..0e59e6a9ad 100644 --- a/latte/ro/tags.texy +++ b/latte/ro/tags.texy @@ -109,8 +109,6 @@ Rezumat și descriere a tuturor etichetelor Latte încorporate. | `{input}` | [tipărește un element de intrare în formular |forms:rendering#label-input] | `{inputError}` | [tipărește mesajul de eroare pentru elementul de intrare al formularului |forms:rendering#inputError] | `n:name` | [activează un element de intrare HTML |forms:rendering#n:name] -| `{formPrint}` | [generează schița unui formular Latte |forms:rendering#formPrint] -| `{formPrintClass}` | [tipărește clasa PHP pentru datele formularului |forms:in-presenter#mapping-to-classes] | `{formContainer}`... `{/formContainer}` | [redarea formularului container |forms:rendering#special-cases] diff --git a/latte/ru/tags.texy b/latte/ru/tags.texy index 3bae39e4dd..620280e2d7 100644 --- a/latte/ru/tags.texy +++ b/latte/ru/tags.texy @@ -109,8 +109,6 @@ | `{input}` | [печатает элемент ввода формы |forms:rendering#label-input] | `{inputError}` | [печатает сообщение об ошибке для элемента ввода формы |forms:rendering#inputError] | `n:name` | [активирует элемент ввода HTML |forms:rendering#n:name] -| `{formPrint}` | [генерирует чертеж формы Latte |forms:rendering#formPrint] -| `{formPrintClass}` | [печатает PHP класс для данных формы |forms:in-presenter#Mapping-to-Classes] | `{formContainer}`... `{/formContainer}` | [рендеринг контейнера формы |forms:rendering#special-cases] diff --git a/latte/sl/tags.texy b/latte/sl/tags.texy index 958c0bff4f..7203fb69fd 100644 --- a/latte/sl/tags.texy +++ b/latte/sl/tags.texy @@ -109,8 +109,6 @@ Povzetek in opis vseh vgrajenih oznak Latte. | `{input}` | [natisne vhodni element obrazca |forms:rendering#label-input] | `{inputError}` | [izpiše sporočilo o napaki za vhodni element obrazca |forms:rendering#inputError] | `n:name` | [aktivira vnosni element HTML |forms:rendering#n:name] -| `{formPrint}` | [ustvari načrt obrazca Latte |forms:rendering#formPrint] -| `{formPrintClass}` | [izpiše razred PHP za podatke obrazca |forms:in-presenter#mapping-to-classes] | `{formContainer}`... `{/formContainer}` | [upodabljanje vsebnika obrazca |forms:rendering#special-cases] diff --git a/latte/tr/tags.texy b/latte/tr/tags.texy index 535b2f018d..f0f09fb3e3 100644 --- a/latte/tr/tags.texy +++ b/latte/tr/tags.texy @@ -109,8 +109,6 @@ Tüm Latte yerleşik etiketlerinin özeti ve açıklaması. | `{input}` | [bir form giriş öğesi yazdırır |forms:rendering#label-input] | `{inputError}` | [form giriş öğesi için hata mesajı yazdırır |forms:rendering#inputError] | `n:name` | [bir HTML giriş öğesini etkinleştirir |forms:rendering#n:name] -| `{formPrint}` | [Latte form planını oluşturur |forms:rendering#formPrint] -| `{formPrintClass}` | [form verileri için PHP sınıfını yazdırır |forms:in-presenter#mapping-to-classes] | `{formContainer}`... `{/formContainer}` | [form kapsayıcısını oluşturma |forms:rendering#special-cases] diff --git a/latte/uk/tags.texy b/latte/uk/tags.texy index 03d1dbcbd2..802bbbd888 100644 --- a/latte/uk/tags.texy +++ b/latte/uk/tags.texy @@ -109,8 +109,6 @@ | `{input}` | [друкує елемент введення форми |forms:rendering#label-input] | `{inputError}` | [друкує повідомлення про помилку для елемента введення форми |forms:rendering#inputError] | `n:name` | [активує елемент введення HTML |forms:rendering#n:name] -| `{formPrint}` | [генерує креслення форми Latte |forms:rendering#formPrint] -| `{formPrintClass}` | [друкує PHP клас для даних форми |forms:in-presenter#Mapping-to-Classes] | `{formContainer}`... `{/formContainer}` | [рендеринг контейнера форми |forms:rendering#special-cases] From baebce62caed7d328177552d37408edf5ab696e9 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 14 Dec 2023 20:34:50 +0100 Subject: [PATCH 040/137] nette/database v3.2 --- database/bg/configuration.texy | 3 +++ database/cs/@left-menu.texy | 1 + database/cs/configuration.texy | 3 +++ database/cs/upgrading.texy | 15 +++++++++++++++ database/de/configuration.texy | 3 +++ database/el/configuration.texy | 3 +++ database/en/@left-menu.texy | 1 + database/en/configuration.texy | 7 +++++-- database/en/upgrading.texy | 14 ++++++++++++++ database/es/configuration.texy | 9 ++++++--- database/fr/configuration.texy | 3 +++ database/hu/configuration.texy | 3 +++ database/it/configuration.texy | 3 +++ database/pl/configuration.texy | 3 +++ database/pt/configuration.texy | 3 +++ database/ro/configuration.texy | 3 +++ database/ru/configuration.texy | 3 +++ database/sl/configuration.texy | 3 +++ database/tr/configuration.texy | 3 +++ database/uk/configuration.texy | 3 +++ 20 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 database/cs/upgrading.texy create mode 100644 database/en/upgrading.texy diff --git a/database/bg/configuration.texy b/database/bg/configuration.texy index c52899ea11..7885ebcdbb 100644 --- a/database/bg/configuration.texy +++ b/database/bg/configuration.texy @@ -51,6 +51,9 @@ database: # само за MySQL: set SET NAMES charset: # (string) по подразбиране е 'utf8mb4' ('utf8' преди v5.5.3) + # само за MySQL: преобразува TINYINT(1) в bool + supportBooleans: # (bool) по подразбиране е false + # само за Oracle и SQLite: formatDate formatDateTime: # (string) по подразбиране е 'U' ``` diff --git a/database/cs/@left-menu.texy b/database/cs/@left-menu.texy index 039cedfdf8..56600faa08 100644 --- a/database/cs/@left-menu.texy +++ b/database/cs/@left-menu.texy @@ -3,3 +3,4 @@ Databáze - [Core] - [Explorer] - [Konfigurace |configuration] +- [Upgrade |upgrading] diff --git a/database/cs/configuration.texy b/database/cs/configuration.texy index d412ba565a..4d57a44817 100644 --- a/database/cs/configuration.texy +++ b/database/cs/configuration.texy @@ -51,6 +51,9 @@ database: # pouze MySQL: nastaví SET NAMES charset: # (string) výchozí je 'utf8mb4' ('utf8' před verzí 5.5.3) + # pouze MySQL: převádí TINYINT(1) na bool + supportBooleans: # (bool) výchozí je false + # pouze Oracle a SQLite: formát pro ukládání data formatDateTime: # (string) výchozí je 'U' ``` diff --git a/database/cs/upgrading.texy b/database/cs/upgrading.texy new file mode 100644 index 0000000000..22963a8271 --- /dev/null +++ b/database/cs/upgrading.texy @@ -0,0 +1,15 @@ +Upgrade +******* + + +Přechod z verze 3.1 na 3.2 +========================== + +Minimální požadovaná verze PHP je 8.1. + +Kód byl pečlivě vyladěn pro PHP 8.1. Byly doplněny všechny nové typehinty u metod a properites. Změny jsou jen drobné: + +- MySQL: nulové datum `0000-00-00` vrací jako `null` +- MySQL: decimal bez desetinných míst vrací jako int místo float +- typ `time` vrací jako DateTime s datumem `1. 1. 0001` místo aktuálního data + diff --git a/database/de/configuration.texy b/database/de/configuration.texy index a134448e32..056af317e7 100644 --- a/database/de/configuration.texy +++ b/database/de/configuration.texy @@ -51,6 +51,9 @@ database: # nur MySQL: setzt SET NAMES charset: # (string) Standardwert ist 'utf8mb4' ('utf8' vor v5.5.3) + # nur MySQL: wandelt TINYINT(1) in bool um + supportBooleans: # (bool) standardmäßig false + # nur Oracle und SQLite: Datumsformat formatDateTime: # (string) Standardwert ist 'U' ``` diff --git a/database/el/configuration.texy b/database/el/configuration.texy index e3f7f2992d..0f25b028e2 100644 --- a/database/el/configuration.texy +++ b/database/el/configuration.texy @@ -51,6 +51,9 @@ database: # μόνο MySQL: ορίζει SET NAMES charset: # (string) προεπιλογή 'utf8mb4' ('utf8' πριν την έκδοση v5.5.3) + # μόνο MySQL: μετατρέπει το TINYINT(1) σε bool + supportBooleans: # (bool) προεπιλογή σε false + # μόνο Oracle και SQLite: μορφή ημερομηνίας formatDateTime: # (string) προεπιλογή 'U' ``` diff --git a/database/en/@left-menu.texy b/database/en/@left-menu.texy index 3a2cf9ca88..c019745dd4 100644 --- a/database/en/@left-menu.texy +++ b/database/en/@left-menu.texy @@ -3,3 +3,4 @@ Database - [Core] - [Explorer] - [Configuration] +- [Upgrading] diff --git a/database/en/configuration.texy b/database/en/configuration.texy index 130f91101b..ed79fa01eb 100644 --- a/database/en/configuration.texy +++ b/database/en/configuration.texy @@ -45,12 +45,15 @@ database: # PHP database driver class driverClass: # (string) - # only MySQL: sets sql_mode + # MySQL only: sets sql_mode sqlmode: # (string) - # only MySQL: sets SET NAMES + # MySQL only: sets SET NAMES charset: # (string) defaults to 'utf8mb4' ('utf8' before v5.5.3) + # MySQL only: converts TINYINT(1) to bool + supportBooleans: # (bool) defaults to false + # only Oracle and SQLite: date format formatDateTime: # (string) defaults to 'U' ``` diff --git a/database/en/upgrading.texy b/database/en/upgrading.texy new file mode 100644 index 0000000000..cd6a4776a9 --- /dev/null +++ b/database/en/upgrading.texy @@ -0,0 +1,14 @@ +Upgrading +********* + + +Migrating from 3.1 to 3.2 +========================= + +The minimum required PHP version is 8.1. + +The code has been carefully tuned for PHP 8.1. All new typehints for methods and properties have been added. The changes are minor: + +- MySQL: a zero date `0000-00-00` is returned as `null` +- MySQL: a decimal without decimal places is returned as int instead of float +- The `time` type is returned as DateTime with the date `1. 1. 0001` instead of the current date diff --git a/database/es/configuration.texy b/database/es/configuration.texy index e9f6cc8109..5e4391fa82 100644 --- a/database/es/configuration.texy +++ b/database/es/configuration.texy @@ -45,13 +45,16 @@ database: # PHP database driver class driverClass: # (string) - # only MySQL: sets sql_mode + # sólo MySQL: sets sql_mode sqlmode: # (string) - # only MySQL: sets SET NAMES + # sólo MySQL: sets SET NAMES charset: # (string) defaults to 'utf8mb4' ('utf8' before v5.5.3) - # only Oracle and SQLite: date format + # sólo MySQL: convierte TINYINT(1) a bool + supportBooleans: # (bool) por defecto false + + # sólo Oracle and SQLite: date format formatDateTime: # (string) defaults to 'U' ``` diff --git a/database/fr/configuration.texy b/database/fr/configuration.texy index 8dcaa2bd84..022d9742a9 100644 --- a/database/fr/configuration.texy +++ b/database/fr/configuration.texy @@ -51,6 +51,9 @@ database: # uniquement MySQL: sets SET NAMES charset: # (string) par défaut 'utf8mb4' ('utf8' avant v5.5.3) + # uniquement MySQL : convertit TINYINT(1) en bool + supportBooleans : # (bool) valeur par défaut : false + # uniquement Oracle et SQLite: format de date formatDateTime: # (string) vaut par défaut 'U'. ``` diff --git a/database/hu/configuration.texy b/database/hu/configuration.texy index 6af7c620aa..caedc8887f 100644 --- a/database/hu/configuration.texy +++ b/database/hu/configuration.texy @@ -51,6 +51,9 @@ database: # csak MySQL: sets SET NAMES charset: # (string) alapértelmezés szerint 'utf8mb4' ('utf8' a v5.5.3 előtt) + # csak MySQL: TINYINT(1) bool-ra konvertálja + supportBooleans: # (bool) alapértelmezett értéke false + # csak Oracle és SQLite: dátumformátum formatDateTime: # (string) alapértelmezett értéke 'U' ``` diff --git a/database/it/configuration.texy b/database/it/configuration.texy index 55e0e4ad9c..f19ed00c41 100644 --- a/database/it/configuration.texy +++ b/database/it/configuration.texy @@ -51,6 +51,9 @@ database: # solo MySQL: imposta SET NAMES charset: # (string) predefinito a 'utf8mb4' ('utf8' prima della v5.5.3) + # solo MySQL: converte TINYINT(1) in bool + supportBooleans: # (bool) predefinito a false + # solo Oracle e SQLite: formato data formatDateTime: # (string) predefinito a "U". ``` diff --git a/database/pl/configuration.texy b/database/pl/configuration.texy index 9dfe2cf200..978b334e58 100644 --- a/database/pl/configuration.texy +++ b/database/pl/configuration.texy @@ -51,6 +51,9 @@ database: # Tylko MySQL: ustawia SET NAMES charset: # (string) default is 'utf8mb4' ('utf8' before 5.5.3) + # Tylko MySQL: konwertuje TINYINT(1) na bool + supportBooleans: # (bool) domyślnie false + # Tylko Oracle i SQLite: format przechowywania danych formatDateTime: # (string) domyślnie 'U' ``` diff --git a/database/pt/configuration.texy b/database/pt/configuration.texy index 08bead4f03..c390440308 100644 --- a/database/pt/configuration.texy +++ b/database/pt/configuration.texy @@ -51,6 +51,9 @@ database: # somente MySQL: define o SET NAMES charset: # (string) padrão para 'utf8mb4' ('utf8' antes da v5.5.3) + # somente MySQL: converte TINYINT(1) em bool + supportBooleans: # (bool) tem como padrão false + # somente Oracle e SQLite: formato de data formatDateTime: # (string) padrão para 'U' ``` diff --git a/database/ro/configuration.texy b/database/ro/configuration.texy index 5995843a6e..76787ba8f9 100644 --- a/database/ro/configuration.texy +++ b/database/ro/configuration.texy @@ -51,6 +51,9 @@ database: # numai MySQL: stabilește SET NAMES charset: # (șir de caractere) implicit la "utf8mb4" ("utf8" înainte de v5.5.3) + # numai MySQL: convertește TINYINT(1) în bool + supportBooleans: # (bool) implicit la false + # numai Oracle și SQLite: formatul datei formatDateTime: # (șir de caractere) implicit la "U". ``` diff --git a/database/ru/configuration.texy b/database/ru/configuration.texy index 31740c9a68..88107912ce 100644 --- a/database/ru/configuration.texy +++ b/database/ru/configuration.texy @@ -51,6 +51,9 @@ database: # только для MySQL: устанавливает SET NAMES charset: # (string) по умолчанию 'utf8mb4' ('utf8' до v5.5.3) + # Только для MySQL: преобразует TINYINT(1) в bool + supportBooleans: # (bool) по умолчанию false + # только для Oracle и SQLite: формат даті formatDateTime: # (string) по умолчанию 'U' ``` diff --git a/database/sl/configuration.texy b/database/sl/configuration.texy index e0fa43ed33..89b66c6083 100644 --- a/database/sl/configuration.texy +++ b/database/sl/configuration.texy @@ -51,6 +51,9 @@ database: # samo MySQL: nastavi SET NAMES charset: # (niz) privzeta vrednost je 'utf8mb4' ('utf8' pred v5.5.3) + # samo MySQL: pretvori TINYINT(1) v bool + supportBooleans: # (bool) privzeto false + # samo Oracle in SQLite: format datuma formatDateTime: # (niz) privzeta vrednost je 'U' ``` diff --git a/database/tr/configuration.texy b/database/tr/configuration.texy index c8ca0e54fb..39319acf9b 100644 --- a/database/tr/configuration.texy +++ b/database/tr/configuration.texy @@ -51,6 +51,9 @@ database: # sadece MySQL: SET NAMES setleri charset: # (string) varsayılan olarak 'utf8mb4' ('utf8' v5.5.3'ten önce) + # sadece MySQL: TINYINT(1)'i bool'a dönüştürür + supportBooleans: # (bool) varsayılan değer false + # sadece Oracle ve SQLite: tarih biçimi formatDateTime: # (string) varsayılan değer 'U' ``` diff --git a/database/uk/configuration.texy b/database/uk/configuration.texy index a8be808cc7..075ef58259 100644 --- a/database/uk/configuration.texy +++ b/database/uk/configuration.texy @@ -51,6 +51,9 @@ database: # тільки для MySQL: встановлює SET NAMES charset: # (string) за замовчуванням 'utf8mb4' ('utf8' до v5.5.3) + # тільки MySQL: перетворює TINYINT(1) в bool + supportBooleans: # (bool) за замовчуванням дорівнює false + # тільки для Oracle і SQLite: формат даті formatDateTime: # (string) за замовчуванням 'U' ``` From 1956b1c87e44ace7b955b1fb9331fa8ccb7ec642 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sat, 25 Nov 2023 13:42:25 +0100 Subject: [PATCH 041/137] Arrays::associate --- utils/bg/arrays.texy | 41 +++++++++++++++++++++++++++++++++++++++++ utils/cs/arrays.texy | 41 +++++++++++++++++++++++++++++++++++++++++ utils/de/arrays.texy | 41 +++++++++++++++++++++++++++++++++++++++++ utils/el/arrays.texy | 41 +++++++++++++++++++++++++++++++++++++++++ utils/en/arrays.texy | 41 +++++++++++++++++++++++++++++++++++++++++ utils/es/arrays.texy | 41 +++++++++++++++++++++++++++++++++++++++++ utils/fr/arrays.texy | 41 +++++++++++++++++++++++++++++++++++++++++ utils/hu/arrays.texy | 41 +++++++++++++++++++++++++++++++++++++++++ utils/it/arrays.texy | 41 +++++++++++++++++++++++++++++++++++++++++ utils/pl/arrays.texy | 41 +++++++++++++++++++++++++++++++++++++++++ utils/pt/arrays.texy | 41 +++++++++++++++++++++++++++++++++++++++++ utils/ro/arrays.texy | 41 +++++++++++++++++++++++++++++++++++++++++ utils/ru/arrays.texy | 41 +++++++++++++++++++++++++++++++++++++++++ utils/sl/arrays.texy | 41 +++++++++++++++++++++++++++++++++++++++++ utils/tr/arrays.texy | 41 +++++++++++++++++++++++++++++++++++++++++ utils/uk/arrays.texy | 41 +++++++++++++++++++++++++++++++++++++++++ 16 files changed, 656 insertions(+) diff --git a/utils/bg/arrays.texy b/utils/bg/arrays.texy index 820513e2e8..8335fd2567 100644 --- a/utils/bg/arrays.texy +++ b/utils/bg/arrays.texy @@ -24,6 +24,47 @@ use Nette\Utils\Arrays; ``` +associate(array $array, mixed $path): array|\stdClass .[method] +--------------------------------------------------------------- + +Функцията гъвкаво трансформира `$array` в асоциативен масив или обекти в съответствие със зададения път `$path`. Пътят може да бъде низ или масив. Той се състои от имената на ключовете във входния масив и оператори като "[]", "->", "=" и "|". Изхвърля `Nette\InvalidArgumentException`, ако пътят е невалиден. + +```php +// конвертиране в асоциативен масив с помощта на прост ключ +$arr = [ + ['name' => 'John', 'age' => 11], + ['name' => 'Mary', 'age' => null], + //... +]; +$result = Arrays::associate($arr, 'name'); +// $result = ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]] +``` + +```php +// присвояване на стойности от един ключ към друг с помощта на оператора = +$result = Arrays::associate($arr, 'name=age'); // или ['name', '=', 'age'] +// $result = ['John' => 11, 'Mary' => null, ...] +``` + +```php +// създаване на обект с помощта на оператора -> +$result = Arrays::associate($arr, '->name'); // или ['->', 'name'] +// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]] +``` + +```php +// комбиниране на клавиши с помощта на оператора | +$result = Arrays::associate($arr, 'name|age'); // или ['name', '|', 'age'] +// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]] +``` + +```php +// добавяне към масив с помощта на [] +$result = Arrays::associate($arr, 'name[]'); // или ['name', '[]'] +// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]] +``` + + contains(array $array, $value): bool .[method] ---------------------------------------------- diff --git a/utils/cs/arrays.texy b/utils/cs/arrays.texy index de80e0c0cf..1f4d07cfe7 100644 --- a/utils/cs/arrays.texy +++ b/utils/cs/arrays.texy @@ -24,6 +24,47 @@ use Nette\Utils\Arrays; ``` +associate(array $array, mixed $path): array|\stdClass .[method] +--------------------------------------------------------------- + +Funkce flexibilně transformuje pole `$array` na asociativní pole nebo objekty podle zadané cesty `$path`. Cesta může být řetězec nebo pole. Tvoří ji názvy klíčů vstupního pole a operátory jako '[]', '->', '=', a '|'. Vyhazuje `Nette\InvalidArgumentException` v případě, že cesta je neplatná. + +```php +// převod na asociativní pole podle jednoduchého klíče +$arr = [ + ['name' => 'John', 'age' => 11], + ['name' => 'Mary', 'age' => null], + // ... +]; +$result = Arrays::associate($arr, 'name'); +// $result = ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]] +``` + +```php +// přiřazení hodnot z jednoho klíče k jinému s použitím operátoru = +$result = Arrays::associate($arr, 'name=age'); // nebo ['name', '=', 'age'] +// $result = ['John' => 11, 'Mary' => null, ...] +``` + +```php +// vytvoření objektu s použitím operátoru -> +$result = Arrays::associate($arr, '->name'); // nebo ['->', 'name'] +// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]] +``` + +```php +// kombinace klíčů pomocí operátoru | +$result = Arrays::associate($arr, 'name|age'); // nebo ['name', '|', 'age'] +// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]] +``` + +```php +// přidání do pole s použitím [] +$result = Arrays::associate($arr, 'name[]'); // nebo ['name', '[]'] +// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]] +``` + + contains(array $array, $value): bool .[method] ---------------------------------------------- diff --git a/utils/de/arrays.texy b/utils/de/arrays.texy index 7aea115b2e..0e9af6de6f 100644 --- a/utils/de/arrays.texy +++ b/utils/de/arrays.texy @@ -24,6 +24,47 @@ use Nette\Utils\Arrays; ``` +associate(array $array, mixed $path): array|\stdClass .[method] +--------------------------------------------------------------- + +Die Funktion wandelt die `$array` flexibel in ein assoziatives Array oder Objekte entsprechend dem angegebenen Pfad `$path` um. Der Pfad kann eine Zeichenkette oder ein Array sein. Er besteht aus den Namen der Schlüssel im Eingabe-Array und Operatoren wie '[]', '->', '=' und '|'. Wirft `Nette\InvalidArgumentException`, wenn der Pfad ungültig ist. + +```php +// Umwandlung in ein assoziatives Array unter Verwendung eines einfachen Schlüssels +$arr = [ + ['name' => 'John', 'age' => 11], + ['name' => 'Mary', 'age' => null], + //... +]; +$result = Arrays::associate($arr, 'name'); +// $result = ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]] +``` + +```php +// Zuweisung von Werten von einem Schlüssel zu einem anderen mit dem Operator = +$result = Arrays::associate($arr, 'name=age'); // oder ['name', '=', 'age'] +// $result = ['John' => 11, 'Mary' => null, ...] +``` + +```php +// Erstellen eines Objekts mit dem ->-Operator +$result = Arrays::associate($arr, '->name'); // oder ['->', 'name'] +// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]] +``` + +```php +// Schlüssel mit dem Operator | kombinieren +$result = Arrays::associate($arr, 'name|age'); // oder ['name', '|', 'age'] +// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]] +``` + +```php +// Hinzufügen zu einem Array mit [] +$result = Arrays::associate($arr, 'name[]'); // oder ['name', '[]'] +// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]] +``` + + contains(array $array, $value): bool .[method] ---------------------------------------------- diff --git a/utils/el/arrays.texy b/utils/el/arrays.texy index 29b06248e0..ecc30f96e7 100644 --- a/utils/el/arrays.texy +++ b/utils/el/arrays.texy @@ -24,6 +24,47 @@ use Nette\Utils\Arrays; ``` +associate(array $array, mixed $path): array|\stdClass .[method] +--------------------------------------------------------------- + +Η συνάρτηση μετατρέπει ευέλικτα το `$array` σε συσχετιστικό πίνακα ή αντικείμενα σύμφωνα με την καθορισμένη διαδρομή `$path`. Η διαδρομή μπορεί να είναι μια συμβολοσειρά ή ένας πίνακας. Αποτελείται από τα ονόματα των κλειδιών του πίνακα εισόδου και τελεστές όπως '[]', '->', '=' και '|'. Πετάει το `Nette\InvalidArgumentException` αν η διαδρομή είναι άκυρη. + +```php +// μετατροπή σε συσχετιστικό πίνακα χρησιμοποιώντας ένα απλό κλειδί +$arr = [ + ['name' => 'John', 'age' => 11], + ['name' => 'Mary', 'age' => null], + //... +]; +$result = Arrays::associate($arr, 'name'); +// $result = ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]] +``` + +```php +// ανάθεση τιμών από ένα κλειδί σε ένα άλλο με χρήση του τελεστή = +$result = Arrays::associate($arr, 'name=age'); // ή ['name', '=', 'age'] +// $result = ['John' => 11, 'Mary' => null, ...] +``` + +```php +// δημιουργία ενός αντικειμένου με χρήση του τελεστή -> +$result = Arrays::associate($arr, '->name'); // ή ['->', 'name'] +// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]] +``` + +```php +// συνδυασμός κλειδιών με χρήση του τελεστή | +$result = Arrays::associate($arr, 'name|age'); // ή ['name', '|', 'age'] +// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]] +``` + +```php +// προσθήκη σε έναν πίνακα χρησιμοποιώντας [] +$result = Arrays::associate($arr, 'name[]'); // ή ['name', '[]'] +// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]] +``` + + contains(array $array, $value): bool .[method] ---------------------------------------------- diff --git a/utils/en/arrays.texy b/utils/en/arrays.texy index 5e4e5f9718..1ff2791f1e 100644 --- a/utils/en/arrays.texy +++ b/utils/en/arrays.texy @@ -24,6 +24,47 @@ use Nette\Utils\Arrays; ``` +associate(array $array, mixed $path): array|\stdClass .[method] +--------------------------------------------------------------- + +The function flexibly transforms the `$array` into an associative array or objects according to the specified path `$path`. The path can be a string or an array. It consists of the names of keys in the input array and operators like '[]', '->', '=', and '|'. Throws `Nette\InvalidArgumentException` if the path is invalid. + +```php +// converting to an associative array using a simple key +$arr = [ + ['name' => 'John', 'age' => 11], + ['name' => 'Mary', 'age' => null], + // ... +]; +$result = Arrays::associate($arr, 'name'); +// $result = ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]] +``` + +```php +// assigning values from one key to another using the = operator +$result = Arrays::associate($arr, 'name=age'); // or ['name', '=', 'age'] +// $result = ['John' => 11, 'Mary' => null, ...] +``` + +```php +// creating an object using the -> operator +$result = Arrays::associate($arr, '->name'); // or ['->', 'name'] +// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]] +``` + +```php +// combining keys using the | operator +$result = Arrays::associate($arr, 'name|age'); // or ['name', '|', 'age'] +// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]] +``` + +```php +// adding to an array using [] +$result = Arrays::associate($arr, 'name[]'); // or ['name', '[]'] +// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]] +``` + + contains(array $array, $value): bool .[method] ---------------------------------------------- diff --git a/utils/es/arrays.texy b/utils/es/arrays.texy index a393e4b351..16f64b28d8 100644 --- a/utils/es/arrays.texy +++ b/utils/es/arrays.texy @@ -24,6 +24,47 @@ use Nette\Utils\Arrays; ``` +associate(array $array, mixed $path): array|\stdClass .[method] +--------------------------------------------------------------- + +La función transforma de forma flexible la `$array` en una matriz asociativa u objetos según la ruta especificada `$path`. La ruta puede ser una cadena o una matriz. Consiste en los nombres de las claves de la matriz de entrada y operadores como '[]', '->', '=' y '|'. Lanza `Nette\InvalidArgumentException` si la ruta no es válida. + +```php +// conversión a array asociativo utilizando una clave simple +$arr = [ + ['name' => 'John', 'age' => 11], + ['name' => 'Mary', 'age' => null], + //... +]; +$result = Arrays::associate($arr, 'name'); +// $result = ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]] +``` + +```php +// asignar valores de una clave a otra mediante el operador = +$result = Arrays::associate($arr, 'name=age'); // o ['name', '=', 'age'] +// $result = ['John' => 11, 'Mary' => null, ...] +``` + +```php +// crear un objeto utilizando el operador -> +$result = Arrays::associate($arr, '->name'); // o ['->', 'name'] +// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]] +``` + +```php +// combinación de claves mediante el operador | +$result = Arrays::associate($arr, 'name|age'); // o ['name', '|', 'age'] +// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]] +``` + +```php +// añadir a un array usando [] +$result = Arrays::associate($arr, 'name[]'); // o ['name', '[]'] +// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]] +``` + + contains(array $array, $value): bool .[method] ---------------------------------------------- diff --git a/utils/fr/arrays.texy b/utils/fr/arrays.texy index 7d94514953..8ac6ab134c 100644 --- a/utils/fr/arrays.texy +++ b/utils/fr/arrays.texy @@ -24,6 +24,47 @@ use Nette\Utils\Arrays; ``` +associate(array $array, mixed $path): array|\stdClass .[method] +--------------------------------------------------------------- + +La fonction transforme de manière flexible le fichier `$array` en un tableau associatif ou en objets selon le chemin spécifié `$path`. Le chemin peut être une chaîne ou un tableau. Il se compose des noms des clés du tableau d'entrée et d'opérateurs tels que "[]", "->", "=" et "|". Lance `Nette\InvalidArgumentException` si le chemin n'est pas valide. + +```php +// conversion en tableau associatif à l'aide d'une simple clé +$arr = [ + ['name' => 'John', 'age' => 11], + ['name' => 'Mary', 'age' => null], + //... +]; +$result = Arrays::associate($arr, 'name'); +// $result = ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]] +``` + +```php +// l'affectation de valeurs d'une clé à une autre à l'aide de l'opérateur =. +$result = Arrays::associate($arr, 'name=age'); // ou ['name', '=', 'age'] +// $result = ['John' => 11, 'Mary' => null, ...] +``` + +```php +// création d'un objet à l'aide de l'opérateur -> +$result = Arrays::associate($arr, '->name'); // ou ['->', 'name'] +// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]] +``` + +```php +// combiner des clés à l'aide de l'opérateur | +$result = Arrays::associate($arr, 'name|age'); // ou ['name', '|', 'age'] +// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]] +``` + +```php +// ajouter à un tableau en utilisant [] +$result = Arrays::associate($arr, 'name[]'); // ou ['name', '[]'] +// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]] +``` + + contains(array $array, $value): bool .[method] ---------------------------------------------- diff --git a/utils/hu/arrays.texy b/utils/hu/arrays.texy index b2efecd091..b38d952c9d 100644 --- a/utils/hu/arrays.texy +++ b/utils/hu/arrays.texy @@ -24,6 +24,47 @@ use Nette\Utils\Arrays; ``` +associate(array $array, mixed $path): array|\stdClass .[method] +--------------------------------------------------------------- + +A függvény rugalmasan átalakítja a `$array` címet egy asszociatív tömbre vagy objektumokra a megadott útvonalnak megfelelően `$path`. Az útvonal lehet egy karakterlánc vagy egy tömb. A bemeneti tömb kulcsainak nevéből és olyan operátorokból áll, mint a '[]', '->', '=' és '|'. A `Nette\InvalidArgumentException` értéket dobja, ha az elérési útvonal érvénytelen. + +```php +// egyszerű kulcs segítségével asszociatív tömbté alakítás +$arr = [ + ['name' => 'John', 'age' => 11], + ['name' => 'Mary', 'age' => null], + //... +]; +$result = Arrays::associate($arr, 'name'); +// $result = ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]] +``` + +```php +// értékek hozzárendelése egyik kulcsról a másikhoz az = operátorral +$result = Arrays::associate($arr, 'name=age'); // vagy ['name', '=', 'age'] +// $result = ['John' => 11, 'Mary' => null, ...] +``` + +```php +// objektum létrehozása a -> operátor használatával +$result = Arrays::associate($arr, '->name'); // vagy ['->', 'name'] +// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]] +``` + +```php +// kulcsok kombinálása a | operátorral +$result = Arrays::associate($arr, 'name|age'); // vagy ['name', '|', 'age'] +// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]] +``` + +```php +// hozzáadás egy tömbhöz a [] +$result = Arrays::associate($arr, 'name[]'); // vagy ['name', '[]'] +// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]] +``` + + contains(array $array, $value): bool .[method] ---------------------------------------------- diff --git a/utils/it/arrays.texy b/utils/it/arrays.texy index a4394bde90..c9e8f0019b 100644 --- a/utils/it/arrays.texy +++ b/utils/it/arrays.texy @@ -24,6 +24,47 @@ use Nette\Utils\Arrays; ``` +associate(array $array, mixed $path): array|\stdClass .[method] +--------------------------------------------------------------- + +La funzione trasforma in modo flessibile l'oggetto `$array` in un array associativo o in oggetti secondo il percorso specificato `$path`. Il percorso può essere una stringa o un array. È costituito dai nomi delle chiavi dell'array di input e da operatori come '[]', '->', '=' e '|'. Lancia `Nette\InvalidArgumentException` se il percorso non è valido. + +```php +// Conversione in un array associativo con una chiave semplice +$arr = [ + ['name' => 'John', 'age' => 11], + ['name' => 'Mary', 'age' => null], + //... +]; +$result = Arrays::associate($arr, 'name'); +// $result = ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]] +``` + +```php +// assegnare valori da una chiave a un'altra utilizzando l'operatore = +$result = Arrays::associate($arr, 'name=age'); // o ['name', '=', 'age'] +// $result = ['John' => 11, 'Mary' => null, ...] +``` + +```php +// creare un oggetto utilizzando l'operatore -> +$result = Arrays::associate($arr, '->name'); // o ['->', 'name'] +// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]] +``` + +```php +// combinando le chiavi con l'operatore | +$result = Arrays::associate($arr, 'name|age'); // oppure ['name', '|', 'age'] +// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]] +``` + +```php +// aggiungere a un array usando [] +$result = Arrays::associate($arr, 'name[]'); // oppure ['name', '[]'] +// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]] +``` + + contains(array $array, $value): bool .[method] ---------------------------------------------- diff --git a/utils/pl/arrays.texy b/utils/pl/arrays.texy index f53b6e0e62..f605e4e771 100644 --- a/utils/pl/arrays.texy +++ b/utils/pl/arrays.texy @@ -24,6 +24,47 @@ use Nette\Utils\Arrays; ``` +associate(array $array, mixed $path): array|\stdClass .[method] +--------------------------------------------------------------- + +Funkcja elastycznie przekształca `$array` w tablicę asocjacyjną lub obiekty zgodnie z określoną ścieżką `$path`. Ścieżka może być łańcuchem lub tablicą. Składa się z nazw kluczy w tablicy wejściowej i operatorów takich jak "[]", "->", "=" i "|". Rzuca `Nette\InvalidArgumentException` jeśli ścieżka jest nieprawidłowa. + +```php +// Konwersja do tablicy asocjacyjnej przy użyciu klucza prostego +$arr = [ + ['name' => 'John', 'age' => 11], + ['name' => 'Mary', 'age' => null], + //... +]; +$result = Arrays::associate($arr, 'name'); +// $result = ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]] +``` + +```php +// przypisywanie wartości z jednego klucza do drugiego przy użyciu operatora = +$result = Arrays::associate($arr, 'name=age'); // lub ['name', '=', 'age'] +// $result = ['John' => 11, 'Mary' => null, ...] +``` + +```php +// tworzenie obiektu przy użyciu operatora -> +$result = Arrays::associate($arr, '->name'); // lub ['->', 'name'] +// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]] +``` + +```php +// łączenie kluczy za pomocą operatora | +$result = Arrays::associate($arr, 'name|age'); // lub ['name', '|', 'age'] +// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]] +``` + +```php +// dodawanie do tablicy przy użyciu [] +$result = Arrays::associate($arr, 'name[]'); // lub ['name', '[]'] +// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]] +``` + + contains(array $array, $value): bool .[method] ---------------------------------------------- diff --git a/utils/pt/arrays.texy b/utils/pt/arrays.texy index c7b6db12bb..4123f387e7 100644 --- a/utils/pt/arrays.texy +++ b/utils/pt/arrays.texy @@ -24,6 +24,47 @@ use Nette\Utils\Arrays; ``` +associate(array $array, mixed $path): array|\stdClass .[method] +--------------------------------------------------------------- + +A função transforma de forma flexível o `$array` em uma matriz associativa ou objetos de acordo com o caminho especificado `$path`. O caminho pode ser uma string ou uma matriz. Ele consiste nos nomes das chaves na matriz de entrada e em operadores como '[]', '->', '=' e '|'. Lança `Nette\InvalidArgumentException` se o caminho for inválido. + +```php +// conversão em uma matriz associativa usando uma chave simples +$arr = [ + ['name' => 'John', 'age' => 11], + ['name' => 'Mary', 'age' => null], + //... +]; +$result = Arrays::associate($arr, 'name'); +// $result = ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]] +``` + +```php +// atribuir valores de uma chave a outra usando o operador = +$result = Arrays::associate($arr, 'name=age'); // ou ['name', '=', 'age'] +// $result = ['John' => 11, 'Mary' => null, ...] +``` + +```php +// criar um objeto usando o operador -> +$result = Arrays::associate($arr, '->name'); // ou ['->', 'name'] +// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]] +``` + +```php +// combinação de chaves usando o operador | +$result = Arrays::associate($arr, 'name|age'); // ou ['name', '|', 'age'] +// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]] +``` + +```php +// adicionando a uma matriz usando [] +$result = Arrays::associate($arr, 'name[]'); // ou ['name', '[]'] +// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]] +``` + + contains(array $array, $value): bool .[method] ---------------------------------------------- diff --git a/utils/ro/arrays.texy b/utils/ro/arrays.texy index 7c76a41abd..cef51c281a 100644 --- a/utils/ro/arrays.texy +++ b/utils/ro/arrays.texy @@ -24,6 +24,47 @@ use Nette\Utils\Arrays; ``` +associate(array $array, mixed $path): array|\stdClass .[method] +--------------------------------------------------------------- + +Funcția transformă în mod flexibil `$array` într-o matrice asociativă sau obiecte în funcție de calea specificată `$path`. Calea poate fi un șir de caractere sau o matrice. Aceasta constă din numele cheilor din tabloul de intrare și operatori precum "[]", "->", "=" și "|". Se aruncă `Nette\InvalidArgumentException` în cazul în care calea nu este validă. + +```php +// conversia într-un tablou asociativ utilizând o cheie simplă +$arr = [ + ['name' => 'John', 'age' => 11], + ['name' => 'Mary', 'age' => null], + //... +]; +$result = Arrays::associate($arr, 'name'); +// $result = ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]] +``` + +```php +// atribuirea de valori de la o cheie la alta cu ajutorul operatorului =. +$result = Arrays::associate($arr, 'name=age'); // sau ['name', '=', 'age'] +// $result = ['John' => 11, 'Mary' => null, ...] +``` + +```php +// crearea unui obiect cu ajutorul operatorului -> +$result = Arrays::associate($arr, '->name'); // sau ['->', 'name'] +// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]] +``` + +```php +// combinarea cheilor cu ajutorul operatorului | +$result = Arrays::associate($arr, 'name|age'); // sau ['name', '|', 'age'] +// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]] +``` + +```php +// adăugarea la un array folosind [] +$result = Arrays::associate($arr, 'name[]'); // sau ['name', '[]'] +// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]] +``` + + contains(array $array, $value): bool .[method] ---------------------------------------------- diff --git a/utils/ru/arrays.texy b/utils/ru/arrays.texy index 05dca37498..65b8239ac0 100644 --- a/utils/ru/arrays.texy +++ b/utils/ru/arrays.texy @@ -24,6 +24,47 @@ use Nette\Utils\Arrays; ``` +associate(array $array, mixed $path): array|\stdClass .[method] +--------------------------------------------------------------- + +Функция гибко преобразует `$array` в ассоциативный массив или объекты в соответствии с заданным путем `$path`. Путь может быть строкой или массивом. Он состоит из имен ключей входного массива и операторов типа '[]', '->', '=' и '|'. Выбрасывает `Nette\InvalidArgumentException`, если путь недопустим. + +```php +// Преобразование в ассоциативный массив с помощью простого ключа +$arr = [ + ['name' => 'John', 'age' => 11], + ['name' => 'Mary', 'age' => null], + //... +]; +$result = Arrays::associate($arr, 'name'); +// $result = ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]] +``` + +```php +// Присвоение значений от одного ключа к другому с помощью оператора = +$result = Arrays::associate($arr, 'name=age'); // или ['name', '=', 'age'] +// $result = ['John' => 11, 'Mary' => null, ...] +``` + +```php +// создание объекта с помощью оператора -> +$result = Arrays::associate($arr, '->name'); // или ['->', 'name'] +// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]] +``` + +```php +// объединение ключей с помощью оператора | +$result = Arrays::associate($arr, 'name|age'); // или ['name', '|', 'age'] +// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]] +``` + +```php +// добавление в массив с помощью [] +$result = Arrays::associate($arr, 'name[]'); // или ['name', '[]'] +// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]] +``` + + contains(array $array, $value): bool .[method] ---------------------------------------------- diff --git a/utils/sl/arrays.texy b/utils/sl/arrays.texy index ba1f546b28..f22a6455aa 100644 --- a/utils/sl/arrays.texy +++ b/utils/sl/arrays.texy @@ -24,6 +24,47 @@ use Nette\Utils\Arrays; ``` +associate(array $array, mixed $path): array|\stdClass .[method] +--------------------------------------------------------------- + +Funkcija fleksibilno preoblikuje `$array` v asociativno polje ali predmete v skladu z določeno potjo `$path`. Pot je lahko niz ali polje. Sestavljena je iz imen ključev v vhodnem polju in operatorjev, kot so "[]", "->", "=" in "|". Če je pot neveljavna, se vrže `Nette\InvalidArgumentException`. + +```php +// pretvorba v asociativno polje z uporabo preprostega ključa +$arr = [ + ['name' => 'John', 'age' => 11], + ['name' => 'Mary', 'age' => null], + //... +]; +$result = Arrays::associate($arr, 'name'); +// $result = ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]] +``` + +```php +// pripisovanje vrednosti z ene tipke na drugo s pomočjo operatorja = +$result = Arrays::associate($arr, 'name=age'); // ali ['name', '=', 'age'] +// $result = ['John' => 11, 'Mary' => null, ...] +``` + +```php +// ustvarjanje objekta z uporabo operatorja -> +$result = Arrays::associate($arr, '->name'); // ali ['->', 'name'] +// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]] +``` + +```php +// združevanje tipk z uporabo operatorja | +$result = Arrays::associate($arr, 'name|age'); // ali ['name', '|', 'age'] +// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]] +``` + +```php +// dodajanje v polje z uporabo [] +$result = Arrays::associate($arr, 'name[]'); // ali ['name', '[]'] +// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]] +``` + + contains(array $array, $value): bool .[method] ---------------------------------------------- diff --git a/utils/tr/arrays.texy b/utils/tr/arrays.texy index 85e7b2610d..ec00b29131 100644 --- a/utils/tr/arrays.texy +++ b/utils/tr/arrays.texy @@ -24,6 +24,47 @@ use Nette\Utils\Arrays; ``` +associate(array $array, mixed $path): array|\stdClass .[method] +--------------------------------------------------------------- + +İşlev, `$array` adresini belirtilen yola göre esnek bir şekilde ilişkisel bir diziye veya nesnelere dönüştürür `$path`. Yol bir dize veya dizi olabilir. Girdi dizisindeki anahtarların adlarından ve '[]', '->', '=' ve '|' gibi operatörlerden oluşur. Yol geçersizse `Nette\InvalidArgumentException` adresini atar. + +```php +// basit bir anahtar kullanarak ilişkisel bir diziye dönüştürme +$arr = [ + ['name' => 'John', 'age' => 11], + ['name' => 'Mary', 'age' => null], + //... +]; +$result = Arrays::associate($arr, 'name'); +// $result = ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]] +``` + +```php +// = operatörünü kullanarak bir anahtardan diğerine değer atama +$result = Arrays::associate($arr, 'name=age'); // veya ['name', '=', 'age'] +// $result = ['John' => 11, 'Mary' => null, ...] +``` + +```php +// -> operatörünü kullanarak bir nesne oluşturma +$result = Arrays::associate($arr, '->name'); // veya ['->', 'name'] +// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]] +``` + +```php +// | operatörünü kullanarak anahtarları birleştirme +$result = Arrays::associate($arr, 'name|age'); // veya ['name', '|', 'age'] +// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]] +``` + +```php +// [] kullanarak bir diziye ekleme +$result = Arrays::associate($arr, 'name[]'); // veya ['name', '[]'] +// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]] +``` + + contains(array $array, $value): bool .[method] ---------------------------------------------- diff --git a/utils/uk/arrays.texy b/utils/uk/arrays.texy index 52b1e384ab..7dd065d131 100644 --- a/utils/uk/arrays.texy +++ b/utils/uk/arrays.texy @@ -24,6 +24,47 @@ use Nette\Utils\Arrays; ``` +associate(array $array, mixed $path): array|\stdClass .[method] +--------------------------------------------------------------- + +Функція гнучко перетворює `$array` в асоціативний масив або об'єкти за вказаним шляхом `$path`. Шлях може бути рядком або масивом. Він складається з імен ключів у вхідному масиві та операторів '[]', '->', '=' і '|'. Якщо шлях невірний, то генерується `Nette\InvalidArgumentException`. + +```php +// перетворення в асоціативний масив з допомогою простого ключа +$arr = [ + ['name' => 'John', 'age' => 11], + ['name' => 'Mary', 'age' => null], + //... +]; +$result = Arrays::associate($arr, 'name'); +// $result = ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]] +``` + +```php +// присвоювання значень від одного ключа до іншого за допомогою оператора = +$result = Arrays::associate($arr, 'name=age'); // або ['name', '=', 'age'] +// $result = ['John' => 11, 'Mary' => null, ...] +``` + +```php +// створення об'єкту з допомогою оператора -> +$result = Arrays::associate($arr, '->name'); // або ['->', 'name'] +// $result = (object) ['John' => ['name' => 'John', 'age' => 11], 'Mary' => ['name' => 'Mary', 'age' => null]] +``` + +```php +// об'єднання ключів за допомогою оператора | або +$result = Arrays::associate($arr, 'name|age'); // або ['name', '|', 'age'] +// $result: ['John' => ['name' => 'John', 'age' => 11], 'Paul' => ['name' => 'Paul', 'age' => 44]] +``` + +```php +// додавання до масиву з використанням [] або [] +$result = Arrays::associate($arr, 'name[]'); // або ['name', '[]'] +// $result: ['John' => [['name' => 'John', 'age' => 22], ['name' => 'John', 'age' => 11]]] +``` + + contains(array $array, $value): bool .[method] ---------------------------------------------- From 8dc3152661b7935a4091844d301d416830bc1b96 Mon Sep 17 00:00:00 2001 From: Alan Jones Date: Tue, 26 Dec 2023 12:56:02 +0000 Subject: [PATCH 042/137] typo (#1036) Fix typo of `atribut` to `attribute` --- latte/en/syntax.texy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/latte/en/syntax.texy b/latte/en/syntax.texy index 17841ecd58..532a8555a0 100644 --- a/latte/en/syntax.texy +++ b/latte/en/syntax.texy @@ -9,7 +9,7 @@ Below is a minimal template that illustrates a few basics elements: tags, n:attr ```latte {* this is a comment *} -
      {* n:if is n:atribut *} +
        {* n:if is n:attribute *} {foreach $items as $item} {* tag representing foreach loop *}
      • {$item|capitalize}
      • {* tag that prints a variable with a filter *} {/foreach} {* end of cycle *} From 461b6fa280ec882c620d2ee7de52c983dcbbd084 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 26 Dec 2023 13:54:25 +0100 Subject: [PATCH 043/137] troubleshooting: fixed info --- nette/bg/troubleshooting.texy | 2 +- nette/cs/troubleshooting.texy | 2 +- nette/de/troubleshooting.texy | 2 +- nette/el/troubleshooting.texy | 2 +- nette/en/troubleshooting.texy | 2 +- nette/es/troubleshooting.texy | 2 +- nette/fr/troubleshooting.texy | 2 +- nette/hu/troubleshooting.texy | 2 +- nette/it/troubleshooting.texy | 2 +- nette/pl/troubleshooting.texy | 2 +- nette/pt/troubleshooting.texy | 2 +- nette/ro/troubleshooting.texy | 2 +- nette/ru/troubleshooting.texy | 2 +- nette/sl/troubleshooting.texy | 2 +- nette/tr/troubleshooting.texy | 2 +- nette/uk/troubleshooting.texy | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/nette/bg/troubleshooting.texy b/nette/bg/troubleshooting.texy index 3025fb225e..2a1817d7a9 100644 --- a/nette/bg/troubleshooting.texy +++ b/nette/bg/troubleshooting.texy @@ -74,7 +74,7 @@ setsebool -P httpd_can_network_connect_db on За да стартирате приложението в хостинг услуга, трябва да зададете document-root в тази директория в конфигурацията на хостинга. Или ако на хостинга има готова папка за публичната директория с различно име (например `web`, `public_html` и т.н.), просто преименувайте `www/`. -Единственото** решение е да се "отървете" от папката `www/`, като използвате правила във файла `.htaccess` или в маршрутизатора. Ако хостингът ви не позволява да зададете корен на документа в поддиректория (т.е. да създавате директории едно ниво над публичната директория), потърсете друга. В противен случай поемате значителен риск за сигурността. Това е като да живееш в апартамент, в който не можеш да затвориш входната врата и тя винаги е отворена. +Решението не е** да се предотврати достъпът до всички папки с изключение на `www/` чрез правила във файла `.htaccess` или в маршрутизатора. Ако хостингът ви не позволява задаване на коренната директория на документа в поддиректория (т.е. създаване на директории на ниво над публичната директория), трябва да потърсите друга хостинг услуга. В противен случай бихте се изложили на значителни рискове за сигурността. Това е все едно да живеете в апартамент, в който входната врата не може да се затвори и винаги е широко отворена. Как да настроя сървъра за красиви URL адреси? .[#toc-how-to-configure-a-server-for-nice-urls] diff --git a/nette/cs/troubleshooting.texy b/nette/cs/troubleshooting.texy index e18ad30c9e..1b1b88e37a 100644 --- a/nette/cs/troubleshooting.texy +++ b/nette/cs/troubleshooting.texy @@ -74,7 +74,7 @@ Adresář `www/` používaný u ukázkových projektů v Nette představuje tzv. Pro zprovoznění aplikace na hostingu je potřeba, abyste v konfiguraci hostingu nastavili tzv. document-root do tohoto adresáře. Nebo, pokud hosting má pro veřejný adresář předpřipravenou složku s jiným názvem (například `web`, `public_html` atd.), tak `www/` jednoduše přejmenujte. -Řešením **naopak není** „zbavit“ se složky `www/` pomocí pravidel v souboru `.htaccess` nebo v routeru. Pokud by hosting neumožňoval nastavit document-root do podadresáře (tj. vytvářet adresáře o úroveň výš nad veřejným adresářem), poohlédněte se po jiném. Šli byste jinak do značného bezpečnostního rizika. Bylo by to jako bydlet v bytě, kde nejdou zavřít vstupní dveře a jsou stále dokořán. +Řešením **naopak není** zamezit přístupu do všech složek kromě `www/` pomocí pravidel v souboru `.htaccess` nebo v routeru. Pokud by hosting neumožňoval nastavit document-root do podadresáře (tj. vytvářet adresáře o úroveň výš nad veřejným adresářem), poohlédněte se po jiném. Šli byste jinak do značného bezpečnostního rizika. Bylo by to jako bydlet v bytě, kde nejdou zavřít vstupní dveře a jsou stále dokořán. Jak nastavit server pro hezká URL? diff --git a/nette/de/troubleshooting.texy b/nette/de/troubleshooting.texy index d711a893b0..4be5b888a7 100644 --- a/nette/de/troubleshooting.texy +++ b/nette/de/troubleshooting.texy @@ -74,7 +74,7 @@ Das Verzeichnis `www/`, das in den Beispielprojekten in Nette verwendet wird, is Um die Anwendung auf dem Hosting laufen zu lassen, müssen Sie das document-root in der Hosting-Konfiguration auf dieses Verzeichnis setzen. Oder, wenn das Hosting einen vorgefertigten Ordner für das öffentliche Verzeichnis mit einem anderen Namen hat (zum Beispiel `web`, `public_html` usw.), benennen Sie einfach `www/` um. -Die Lösung **ist** nicht, den Ordner `www/` durch Regeln in der Datei `.htaccess` oder im Router "loszuwerden". Wenn das Hosting Ihnen nicht erlaubt, document-root auf ein Unterverzeichnis zu setzen (d.h. Verzeichnisse eine Ebene über dem öffentlichen Verzeichnis zu erstellen), suchen Sie nach einem anderen. Andernfalls würden Sie ein erhebliches Sicherheitsrisiko eingehen. Das wäre so, als würden Sie in einer Wohnung leben, deren Eingangstür Sie nicht schließen können und die immer weit offen steht. +Die Lösung **ist** nicht, den Zugriff auf alle Verzeichnisse außer `www/` durch Regeln in der Datei `.htaccess` oder im Router zu verhindern. Wenn Ihr Hosting nicht erlaubt, das Stammverzeichnis für Dokumente auf ein Unterverzeichnis zu setzen (d. h. Verzeichnisse eine Ebene über dem öffentlichen Verzeichnis anzulegen), sollten Sie sich nach einem anderen Hosting-Dienst umsehen. Andernfalls würden Sie sich einem erheblichen Sicherheitsrisiko aussetzen. Das wäre so, als würden Sie in einer Wohnung leben, deren Eingangstür nicht geschlossen werden kann und immer offen steht. Wie konfiguriert man einen Server für schöne URLs? .[#toc-how-to-configure-a-server-for-nice-urls] diff --git a/nette/el/troubleshooting.texy b/nette/el/troubleshooting.texy index 18f731fbb4..2280a8124c 100644 --- a/nette/el/troubleshooting.texy +++ b/nette/el/troubleshooting.texy @@ -74,7 +74,7 @@ setsebool -P httpd_can_network_connect_db on Για να εκτελέσετε την εφαρμογή στη φιλοξενία, πρέπει να ορίσετε το document-root σε αυτόν τον κατάλογο στη διαμόρφωση της φιλοξενίας. Ή, αν η φιλοξενία έχει έναν προκαθορισμένο φάκελο για τον δημόσιο κατάλογο με διαφορετικό όνομα (για παράδειγμα `web`, `public_html` κ.λπ.), απλά μετονομάστε τον σε `www/`. -Η λύση **δεν** είναι να "ξεφορτωθείτε" το φάκελο `www/` χρησιμοποιώντας κανόνες στο αρχείο `.htaccess` ή στο δρομολογητή. Αν η φιλοξενία δεν σας επιτρέπει να ορίσετε το document-root σε υποκατάλογο (δηλ. να δημιουργήσετε καταλόγους ένα επίπεδο πάνω από τον δημόσιο κατάλογο), αναζητήστε άλλον. Διαφορετικά, θα αναλάβετε ένα σημαντικό ρίσκο ασφάλειας. Θα ήταν σαν να ζείτε σε ένα διαμέρισμα όπου δεν μπορείτε να κλείσετε την εξώπορτα και είναι πάντα ορθάνοιχτη. +Η λύση **δεν** είναι να αποτρέψετε την πρόσβαση σε όλους τους φακέλους εκτός από το `www/` χρησιμοποιώντας κανόνες στο αρχείο `.htaccess` ή στο δρομολογητή. Αν η φιλοξενία σας δεν επιτρέπει τον ορισμό της ρίζας του εγγράφου σε υποκατάλογο (δηλαδή τη δημιουργία καταλόγων ένα επίπεδο πάνω από τον δημόσιο κατάλογο), θα πρέπει να αναζητήσετε μια άλλη υπηρεσία φιλοξενίας. Διαφορετικά, θα εκτεθείτε σε σημαντικούς κινδύνους ασφαλείας. Θα ήταν σαν να ζείτε σε ένα διαμέρισμα όπου η μπροστινή πόρτα δεν μπορεί να κλείσει και είναι πάντα ορθάνοιχτη. Πώς να διαμορφώσετε έναν διακομιστή για ωραίες διευθύνσεις URL; .[#toc-how-to-configure-a-server-for-nice-urls] diff --git a/nette/en/troubleshooting.texy b/nette/en/troubleshooting.texy index b9b44992fa..dfa96741c6 100644 --- a/nette/en/troubleshooting.texy +++ b/nette/en/troubleshooting.texy @@ -74,7 +74,7 @@ The `www/` directory used in the sample projects in Nette is the so-called publi To run the application on the hosting, you need to set the document-root to this directory in the hosting configuration. Or, if the hosting has a pre-made folder for the public directory with a different name (for example `web`, `public_html` etc.), simply rename `www/`. -The solution **isn't** to "get rid" of the `www/` folder using rules in the `.htaccess` file or in the router. If the hosting would not allow you to set document-root to a subdirectory (i.e. create directories one level above the public directory), look for another. You would otherwise be taking a significant security risk. It would be like living in an apartment where you can't close the front door and it's always wide open. +The solution **is not** to prevent access to all folders except `www/` using rules in the `.htaccess` file or in the router. If your hosting does not allow setting the document root to a subdirectory (i.e., creating directories a level above the public directory), you should look for a different hosting service. Otherwise, you would be exposing yourself to significant security risks. It would be like living in an apartment where the front door cannot be closed and is always wide open. How to Configure a Server for Nice URLs? diff --git a/nette/es/troubleshooting.texy b/nette/es/troubleshooting.texy index 59b26e6139..56b489fde8 100644 --- a/nette/es/troubleshooting.texy +++ b/nette/es/troubleshooting.texy @@ -74,7 +74,7 @@ El directorio `www/` utilizado en los proyectos de ejemplo de Nette es el denomi Para ejecutar la aplicación en el hosting, es necesario establecer el document-root a este directorio en la configuración del hosting. O, si el alojamiento tiene una carpeta pre-hecha para el directorio público con un nombre diferente (por ejemplo `web`, `public_html` etc.), simplemente renombre `www/`. -La solución **no** es "deshacerse" de la carpeta `www/` utilizando reglas en el archivo `.htaccess` o en el router. Si el alojamiento no te permite establecer document-root en un subdirectorio (es decir, crear directorios un nivel por encima del directorio público), busca otro. De lo contrario, estarías asumiendo un riesgo de seguridad importante. Sería como vivir en un apartamento en el que no puedes cerrar la puerta principal y siempre está abierta de par en par. +La solución **no es** impedir el acceso a todas las carpetas excepto `www/` mediante reglas en el archivo `.htaccess` o en el router. Si tu alojamiento no permite establecer la raíz del documento en un subdirectorio (es decir, crear directorios un nivel por encima del directorio público), deberías buscar otro servicio de alojamiento. De lo contrario, te estarías exponiendo a importantes riesgos de seguridad. Sería como vivir en un apartamento donde la puerta principal no se puede cerrar y está siempre abierta de par en par. ¿Cómo configurar un servidor para URLs agradables? .[#toc-how-to-configure-a-server-for-nice-urls] diff --git a/nette/fr/troubleshooting.texy b/nette/fr/troubleshooting.texy index 5e466938c7..97a4e0114c 100644 --- a/nette/fr/troubleshooting.texy +++ b/nette/fr/troubleshooting.texy @@ -74,7 +74,7 @@ Le répertoire `www/` utilisé dans les exemples de projets de Nette est le rép Pour exécuter l'application sur l'hébergement, vous devez définir le document-root sur ce répertoire dans la configuration de l'hébergement. Ou, si l'hébergement a un dossier prédéfini pour le répertoire public avec un nom différent (par exemple `web`, `public_html` etc.), renommez simplement `www/`. -La solution **n'est pas** de se "débarrasser" du dossier `www/` en utilisant des règles dans le fichier `.htaccess` ou dans le routeur. Si l'hébergement ne vous permet pas de définir document-root sur un sous-répertoire (c'est-à-dire de créer des répertoires un niveau au-dessus du répertoire public), cherchez-en un autre. Sinon, vous prenez un risque important en matière de sécurité. Ce serait comme vivre dans un appartement où vous ne pouvez pas fermer la porte d'entrée et où elle est toujours grande ouverte. +La solution **n'est pas** d'empêcher l'accès à tous les dossiers sauf `www/` en utilisant des règles dans le fichier `.htaccess` ou dans le routeur. Si votre hébergement ne permet pas de placer la racine du document dans un sous-répertoire (c'est-à-dire de créer des répertoires un niveau au-dessus du répertoire public), vous devriez chercher un autre service d'hébergement. Dans le cas contraire, vous vous exposeriez à des risques de sécurité importants. Ce serait comme vivre dans un appartement dont la porte d'entrée ne peut être fermée et reste toujours grande ouverte. Comment configurer un serveur pour de belles URL ? .[#toc-how-to-configure-a-server-for-nice-urls] diff --git a/nette/hu/troubleshooting.texy b/nette/hu/troubleshooting.texy index 1c2df17f16..b0eba24ce5 100644 --- a/nette/hu/troubleshooting.texy +++ b/nette/hu/troubleshooting.texy @@ -74,7 +74,7 @@ A Nette mintaprojektekben használt `www/` könyvtár a projekt úgynevezett nyi Ahhoz, hogy az alkalmazás a tárhelyen fusson, a tárhely konfigurációjában a document-root-ot erre a könyvtárra kell állítani. Vagy, ha a tárhelyen van egy előre elkészített mappa a nyilvános könyvtár számára más névvel (például `web`, `public_html` stb.), egyszerűen nevezze át `www/`. -A megoldás **nem** a `www/` mappától való "megszabadulás" a `.htaccess` fájlban vagy a routerben található szabályok segítségével. Ha a tárhely nem engedné meg, hogy a document-root-ot egy alkönyvtárra állítsa (azaz a nyilvános könyvtár felett egy szinttel magasabb könyvtárakat hozzon létre), keressen másikat. Ellenkező esetben jelentős biztonsági kockázatot vállalna. Olyan lenne, mintha olyan lakásban élnél, ahol nem tudod becsukni a bejárati ajtót, és az mindig nyitva van. +A megoldás **nem** az, hogy a `www/` kivételével minden mappához való hozzáférést megakadályozzuk a `.htaccess` fájlban vagy az útválasztóban található szabályok segítségével. Ha a tárhelye nem teszi lehetővé a dokumentum gyökerének alkönyvtárba helyezését (azaz a nyilvános könyvtár feletti könyvtárak létrehozását), akkor más tárhelyszolgáltatást kell keresnie. Ellenkező esetben jelentős biztonsági kockázatoknak teszi ki magát. Ez olyan lenne, mintha olyan lakásban élne, ahol a bejárati ajtót nem lehet bezárni, és mindig nyitva van. Hogyan konfiguráljunk egy kiszolgálót a szép URL-ekhez? .[#toc-how-to-configure-a-server-for-nice-urls] diff --git a/nette/it/troubleshooting.texy b/nette/it/troubleshooting.texy index da0869ae5c..bb772c17a9 100644 --- a/nette/it/troubleshooting.texy +++ b/nette/it/troubleshooting.texy @@ -74,7 +74,7 @@ La directory `www/` utilizzata nei progetti di esempio di Nette è la cosiddetta Per eseguire l'applicazione sull'hosting, è necessario impostare la document-root su questa directory nella configurazione dell'hosting. Oppure, se l'hosting ha una cartella preconfezionata per la directory pubblica con un nome diverso (ad esempio `web`, `public_html` ecc.), è sufficiente rinominare `www/`. -La soluzione **non** è quella di "sbarazzarsi" della cartella `www/` usando regole nel file `.htaccess` o nel router. Se l'hosting non vi permette di impostare document-root su una sottodirectory (cioè di creare directory un livello sopra la directory pubblica), cercatene un'altra. In caso contrario, si correrebbe un rischio significativo per la sicurezza. Sarebbe come vivere in un appartamento in cui non si può chiudere la porta d'ingresso, che rimane sempre aperta. +La soluzione non è impedire l'accesso a tutte le cartelle tranne `www/` utilizzando regole nel file `.htaccess` o nel router. Se il vostro hosting non consente di impostare la radice del documento in una sottodirectory (cioè di creare directory un livello sopra la directory pubblica), dovreste cercare un altro servizio di hosting. In caso contrario, ci si esporrebbe a rischi significativi per la sicurezza. Sarebbe come vivere in un appartamento dove la porta d'ingresso non può essere chiusa ed è sempre spalancata. Come configurare un server per avere URL gradevoli? .[#toc-how-to-configure-a-server-for-nice-urls] diff --git a/nette/pl/troubleshooting.texy b/nette/pl/troubleshooting.texy index 6a5a9aab0d..f2fe8b9c8f 100644 --- a/nette/pl/troubleshooting.texy +++ b/nette/pl/troubleshooting.texy @@ -74,7 +74,7 @@ Katalog `www/` używany w przykładowych projektach Nette jest katalogiem public Aby aplikacja działała na hostingu, należy w konfiguracji hostingu ustawić document-root na ten katalog. Lub, jeśli hosting ma przygotowany folder o innej nazwie dla katalogu publicznego (na przykład `web`, `public_html`, itp.), po prostu zmień nazwę `www/`. -Rozwiązaniem **nie jest** "pozbycie się" folderu `www/` za pomocą reguł w pliku `.htaccess` lub w routerze. Jeśli hosting nie pozwoliłby Ci ustawić document-root na podkatalog (czyli tworzyć katalogi jeden poziom powyżej katalogu publicznego), poszukaj innego. W przeciwnym razie podejmowałbyś znaczne ryzyko związane z bezpieczeństwem. Byłoby to jak mieszkanie, w którym nie można zamknąć drzwi wejściowych i są one zawsze szeroko otwarte. +Rozwiązaniem **nie jest** uniemożliwienie dostępu do wszystkich folderów z wyjątkiem `www/` za pomocą reguł w pliku `.htaccess` lub w routerze. Jeśli twój hosting nie pozwala na ustawienie katalogu głównego dokumentu w podkatalogu (tj. tworzenie katalogów na poziomie wyższym niż katalog publiczny), powinieneś poszukać innej usługi hostingowej. W przeciwnym razie narazisz się na poważne zagrożenia bezpieczeństwa. Byłoby to jak mieszkanie w mieszkaniu, w którym drzwi wejściowe nie mogą być zamknięte i są zawsze szeroko otwarte. Jak założyć serwer dla ładnych adresów URL? .[#toc-how-to-configure-a-server-for-nice-urls] diff --git a/nette/pt/troubleshooting.texy b/nette/pt/troubleshooting.texy index bd64f473e0..d1f69bd21b 100644 --- a/nette/pt/troubleshooting.texy +++ b/nette/pt/troubleshooting.texy @@ -74,7 +74,7 @@ O diretório `www/` usado nos projetos modelo em Nette é o chamado diretório p Para executar o aplicativo na hospedagem, é necessário definir a raiz do documento para este diretório na configuração de hospedagem. Ou, se a hospedagem tiver uma pasta pré-fabricada para o diretório público com um nome diferente (por exemplo `web`, `public_html` etc.), simplesmente renomeie `www/`. -A solução ** não é*** para "se livrar" da pasta `www/` usando regras no arquivo `.htaccess` ou no roteador. Se a hospedagem não permitir que você coloque a raiz do documento em um subdiretório (ou seja, criar diretórios um nível acima do diretório público), procure por outro. Caso contrário, você estaria correndo um risco significativo de segurança. Seria como viver em um apartamento onde não se pode fechar a porta da frente e ela está sempre aberta. +A solução **não é** impedir o acesso a todas as pastas, exceto `www/`, usando regras no arquivo `.htaccess` ou no roteador. Se a sua hospedagem não permitir a configuração da raiz do documento em um subdiretório (ou seja, a criação de diretórios um nível acima do diretório público), você deverá procurar outro serviço de hospedagem. Caso contrário, você estará se expondo a riscos de segurança significativos. Seria como morar em um apartamento em que a porta da frente não pode ser fechada e está sempre aberta. Como configurar um servidor para URLs legais? .[#toc-how-to-configure-a-server-for-nice-urls] diff --git a/nette/ro/troubleshooting.texy b/nette/ro/troubleshooting.texy index dfe631e766..04c72e77c2 100644 --- a/nette/ro/troubleshooting.texy +++ b/nette/ro/troubleshooting.texy @@ -74,7 +74,7 @@ Directorul `www/` utilizat în proiectele de exemplu din Nette este așa-numitul Pentru a rula aplicația pe găzduire, trebuie să setați documentul-root la acest director în configurația de găzduire. Sau, dacă găzduirea are un dosar predefinit pentru directorul public cu un nume diferit (de exemplu `web`, `public_html` etc.), pur și simplu redenumiți-l `www/`. -Soluția **nu este** de a "scăpa" de folderul `www/` folosind reguli în fișierul `.htaccess` sau în router. Dacă găzduirea nu v-ar permite să setați document-root la un subdirectoriu (adică să creați directoare cu un nivel deasupra directorului public), căutați alta. În caz contrar, v-ați asuma un risc de securitate semnificativ. Ar fi ca și cum ați locui într-un apartament în care nu puteți închide ușa de la intrare și este mereu larg deschisă. +Soluția **nu este** de a împiedica accesul la toate dosarele, cu excepția `www/`, folosind reguli în fișierul `.htaccess` sau în router. În cazul în care serviciul de găzduire nu permite setarea rădăcinii documentului într-un subdirectoriu (adică crearea de directoare la un nivel superior directorului public), ar trebui să căutați un alt serviciu de găzduire. În caz contrar, v-ați expune la riscuri de securitate semnificative. Ar fi ca și cum ați locui într-un apartament în care ușa de la intrare nu poate fi închisă și este întotdeauna larg deschisă. Cum se configurează un server pentru URL-uri frumoase? .[#toc-how-to-configure-a-server-for-nice-urls] diff --git a/nette/ru/troubleshooting.texy b/nette/ru/troubleshooting.texy index 7f9776b64a..c2fbdfa939 100644 --- a/nette/ru/troubleshooting.texy +++ b/nette/ru/troubleshooting.texy @@ -74,7 +74,7 @@ setsebool -P httpd_can_network_connect_db on Чтобы запустить приложение на хостинге, необходимо в конфигурации хостинга установить document-root в эту директорию. Или, если на хостинге есть готовая папка для публичного каталога с другим именем (например, `web`, `public_html` и т.д.), просто переименуйте `www/`. -Решение **не** состоит в том, чтобы "избавиться" от папки `www/` с помощью правил в файле `.htaccess` или в роутере. Если хостинг не позволяет вам установить document-root в подкаталог (т.е. создавать каталоги на один уровень выше публичного каталога), поищите другой. В противном случае вы существенно рискуете безопасностью. Это похоже на жизнь в квартире, где вы не можете закрыть входную дверь, и она всегда открыта. +Решение **не** заключается в том, чтобы запретить доступ ко всем папкам, кроме `www/`, с помощью правил в файле `.htaccess` или в маршрутизаторе. Если ваш хостинг не позволяет устанавливать корень документа в подкаталог (т. е. создавать каталоги на уровень выше публичного каталога), вам следует поискать другой хостинг. В противном случае вы подвергаете себя значительным рискам безопасности. Это все равно что жить в квартире, где входная дверь не закрывается и всегда нараспашку. Как настроить сервер для красивых URL? .[#toc-how-to-configure-a-server-for-nice-urls] diff --git a/nette/sl/troubleshooting.texy b/nette/sl/troubleshooting.texy index 67dfe0c7e0..4190687845 100644 --- a/nette/sl/troubleshooting.texy +++ b/nette/sl/troubleshooting.texy @@ -74,7 +74,7 @@ Imenik `www/`, ki se uporablja v vzorčnih projektih v Nette, je tako imenovani Če želite zagnati aplikacijo na gostovanju, morate v konfiguraciji gostovanja nastaviti document-root na ta imenik. Če pa ima gostovanje vnaprej pripravljeno mapo za javni imenik z drugačnim imenom (na primer `web`, `public_html` itd.), preprosto preimenujte `www/`. -Rešitev **ni**, da bi se mape `www/` "znebili" z uporabo pravil v datoteki `.htaccess` ali v usmerjevalniku. Če gostovanje ne bi dovolilo nastavitve document-root na podimenik (tj. ustvarjanje imenikov eno raven nad javnim imenikom), poiščite drugega. V nasprotnem primeru bi se izpostavili precejšnjemu varnostnemu tveganju. To bi bilo tako, kot če bi živeli v stanovanju, v katerem ne morete zapreti vhodnih vrat in so ta vedno na široko odprta. +Rešitev ni** preprečevanje dostopa do vseh map razen `www/` s pravili v datoteki `.htaccess` ali v usmerjevalniku. Če vaše gostovanje ne dovoljuje nastavitve korena dokumenta v podimenik (tj. ustvarjanja imenikov eno raven nad javnim imenikom), morate poiskati drugo storitev gostovanja. V nasprotnem primeru bi se izpostavili velikim varnostnim tveganjem. To bi bilo tako, kot če bi živeli v stanovanju, kjer vhodnih vrat ni mogoče zapreti in so vedno na široko odprta. Kako konfigurirati strežnik za lepe naslove URL? .[#toc-how-to-configure-a-server-for-nice-urls] diff --git a/nette/tr/troubleshooting.texy b/nette/tr/troubleshooting.texy index 9695448067..a7a0209e37 100644 --- a/nette/tr/troubleshooting.texy +++ b/nette/tr/troubleshooting.texy @@ -74,7 +74,7 @@ Nette'deki örnek projelerde kullanılan `www/` dizini, projenin genel dizini ve Uygulamayı hosting üzerinde çalıştırmak için, hosting yapılandırmasında document-root'u bu dizine ayarlamanız gerekir. Veya, barındırma, farklı bir adla (örneğin `web`, `public_html` vb.) genel dizin için önceden oluşturulmuş bir klasöre sahipse, `www/` adını değiştirmeniz yeterlidir. -Çözüm, `.htaccess` dosyasındaki veya yönlendiricideki kuralları kullanarak `www/` klasöründen "kurtulmak" değildir. Hosting, document-root'u bir alt dizine ayarlamanıza (yani genel dizinin bir seviye üstünde dizinler oluşturmanıza) izin vermiyorsa, başka bir tane arayın. Aksi takdirde önemli bir güvenlik riski almış olursunuz. Bu, ön kapısını kapatamadığınız ve her zaman ardına kadar açık olan bir apartman dairesinde yaşamaya benzer. +Çözüm, `.htaccess` dosyasındaki veya yönlendiricideki kuralları kullanarak `www/` dışındaki tüm klasörlere erişimi engellemek **değildir**. Barındırma hizmetiniz belge kökünü bir alt dizine ayarlamaya (yani genel dizinin bir seviye üstünde dizinler oluşturmaya) izin vermiyorsa, farklı bir barındırma hizmeti aramalısınız. Aksi takdirde, kendinizi önemli güvenlik risklerine maruz bırakmış olursunuz. Bu, ön kapısı kapatılamayan ve her zaman ardına kadar açık olan bir apartman dairesinde yaşamaya benzer. Güzel URL'ler için Sunucu Nasıl Yapılandırılır? .[#toc-how-to-configure-a-server-for-nice-urls] diff --git a/nette/uk/troubleshooting.texy b/nette/uk/troubleshooting.texy index 0eee4e5e76..dffbeb72cb 100644 --- a/nette/uk/troubleshooting.texy +++ b/nette/uk/troubleshooting.texy @@ -74,7 +74,7 @@ setsebool -P httpd_can_network_connect_db on Щоб запустити додаток на хостингу, необхідно в конфігурації хостингу встановити document-root у цю директорію. Або, якщо на хостингу є готова папка для публічного каталогу з іншим ім'ям (наприклад, `web`, `public_html` тощо), просто перейменуйте `www/`. -Рішення **не** полягає в тому, щоб "позбутися" папки `www/` за допомогою правил у файлі `.htaccess` або в роутері. Якщо хостинг не дозволяє вам встановити document-root у підкаталог (тобто створювати каталоги на один рівень вище публічного каталогу), пошукайте інший. В іншому разі ви істотно ризикуєте безпекою. Це схоже на життя у квартирі, де ви не можете закрити вхідні двері, і вони завжди відчинені. +Рішенням **не є** заборонити доступ до всіх папок, крім `www/`, за допомогою правил у файлі `.htaccess` або в маршрутизаторі. Якщо ваш хостинг не дозволяє встановлювати корінь документа в підкаталозі (тобто створювати каталоги на рівень вище загальнодоступного каталогу), вам слід пошукати інший хостинг. В іншому випадку ви наражаєте себе на значні ризики безпеки. Це все одно, що жити в квартирі, де вхідні двері не можна закрити і вони завжди навстіж відчинені. Як налаштувати сервер для красивих URL? .[#toc-how-to-configure-a-server-for-nice-urls] From bdca5586bd2c9dc2efc58753f66789484b6a98d4 Mon Sep 17 00:00:00 2001 From: sallyx Date: Tue, 26 Dec 2023 13:56:31 +0100 Subject: [PATCH 044/137] neon: added missing parameter (#1037) --- neon/bg/@home.texy | 4 ++-- neon/cs/@home.texy | 4 ++-- neon/de/@home.texy | 4 ++-- neon/el/@home.texy | 4 ++-- neon/en/@home.texy | 4 ++-- neon/es/@home.texy | 4 ++-- neon/fr/@home.texy | 4 ++-- neon/hu/@home.texy | 4 ++-- neon/it/@home.texy | 4 ++-- neon/pl/@home.texy | 4 ++-- neon/pt/@home.texy | 4 ++-- neon/ro/@home.texy | 4 ++-- neon/ru/@home.texy | 4 ++-- neon/sl/@home.texy | 4 ++-- neon/tr/@home.texy | 4 ++-- neon/uk/@home.texy | 4 ++-- 16 files changed, 32 insertions(+), 32 deletions(-) diff --git a/neon/bg/@home.texy b/neon/bg/@home.texy index 7825a8cde7..4b244620ff 100644 --- a/neon/bg/@home.texy +++ b/neon/bg/@home.texy @@ -32,8 +32,8 @@ vendor/bin/neon-lint ``` -encode(mixed $value, bool $blockMode=false): string .[method] -------------------------------------------------------------- +encode(mixed $value, bool $blockMode=false, string $indentation="\t"): string .[method] +--------------------------------------------------------------------------------------- Връща `$value`, преобразуван в NEON. Параметърът `$blockMode` може да бъде подаден като true, което ще създаде многоредов изход. Параметърът `$indentation` задава символите, използвани за отстъпите (по подразбиране е tab). diff --git a/neon/cs/@home.texy b/neon/cs/@home.texy index 2f04820c6a..b570e235cf 100644 --- a/neon/cs/@home.texy +++ b/neon/cs/@home.texy @@ -32,8 +32,8 @@ vendor/bin/neon-lint ``` -encode(mixed $value, bool $blockMode=false): string .[method] -------------------------------------------------------------- +encode(mixed $value, bool $blockMode=false, string $indentation="\t"): string .[method] +--------------------------------------------------------------------------------------- Vrací `$value` převedenou na NEON. Jako parametr `$blockMode` můžete předat true, čímž se vytvoří víceřádkový výstup. Parametr `$indentation` určuje znaky použité pro odsazení (výchozí je tabulátor). diff --git a/neon/de/@home.texy b/neon/de/@home.texy index 8ff52bc8dd..cb947a73a8 100644 --- a/neon/de/@home.texy +++ b/neon/de/@home.texy @@ -32,8 +32,8 @@ vendor/bin/neon-lint ``` -encode(mixed $value, bool $blockMode=false): string .[method] -------------------------------------------------------------- +encode(mixed $value, bool $blockMode=false, string $indentation="\t"): string .[method] +--------------------------------------------------------------------------------------- Gibt `$value` in NEON konvertiert zurück. Als Parameter `$blockMode` können Sie true übergeben, was eine mehrzeilige Ausgabe erzeugt. Der Parameter `$indentation` gibt die für die Einrückung verwendeten Zeichen an (Standard ist tab). diff --git a/neon/el/@home.texy b/neon/el/@home.texy index 38e047f559..e61712f6f1 100644 --- a/neon/el/@home.texy +++ b/neon/el/@home.texy @@ -32,8 +32,8 @@ vendor/bin/neon-lint ``` -encode(mixed $value, bool $blockMode=false): string .[method] -------------------------------------------------------------- +encode(mixed $value, bool $blockMode=false, string $indentation="\t"): string .[method] +--------------------------------------------------------------------------------------- Επιστρέφει το `$value` σε NEON. Ως παράμετρος `$blockMode` μπορείτε να περάσετε την true, η οποία θα δημιουργήσει έξοδο πολλαπλών γραμμών. Η παράμετρος `$indentation` καθορίζει τους χαρακτήρες που χρησιμοποιούνται για την εσοχή (προεπιλογή είναι το tab). diff --git a/neon/en/@home.texy b/neon/en/@home.texy index c560bffaf2..8fb97e8cac 100644 --- a/neon/en/@home.texy +++ b/neon/en/@home.texy @@ -32,8 +32,8 @@ vendor/bin/neon-lint ``` -encode(mixed $value, bool $blockMode=false): string .[method] -------------------------------------------------------------- +encode(mixed $value, bool $blockMode=false, string $indentation="\t"): string .[method] +--------------------------------------------------------------------------------------- Returns `$value` converted to NEON. As the parameter `$blockMode` you can pass true, which will create multiline output. The parameter `$indentation` specifies the characters used for indentation (default is tab). diff --git a/neon/es/@home.texy b/neon/es/@home.texy index be13729413..4722e32baa 100644 --- a/neon/es/@home.texy +++ b/neon/es/@home.texy @@ -32,8 +32,8 @@ vendor/bin/neon-lint ``` -encode(mixed $value, bool $blockMode=false): string .[method] -------------------------------------------------------------- +encode(mixed $value, bool $blockMode=false, string $indentation="\t"): string .[method] +--------------------------------------------------------------------------------------- Devuelve `$value` convertido a NEON. Como parámetro `$blockMode` puede pasar true, que creará una salida multilínea. El parámetro `$indentation` especifica los caracteres utilizados para la sangría (por defecto es tabulador). diff --git a/neon/fr/@home.texy b/neon/fr/@home.texy index 8813535de9..c14170ad07 100644 --- a/neon/fr/@home.texy +++ b/neon/fr/@home.texy @@ -32,8 +32,8 @@ vendor/bin/neon-lint ``` -encode(mixed $value, bool $blockMode=false): string .[method] -------------------------------------------------------------- +encode(mixed $value, bool $blockMode=false, string $indentation="\t"): string .[method] +--------------------------------------------------------------------------------------- Renvoie `$value` converti en NEON. Comme paramètre `$blockMode` vous pouvez passer true, ce qui créera une sortie multiligne. Le paramètre `$indentation` spécifie les caractères utilisés pour l'indentation (la tabulation par défaut). diff --git a/neon/hu/@home.texy b/neon/hu/@home.texy index de60f22bed..762dbd923a 100644 --- a/neon/hu/@home.texy +++ b/neon/hu/@home.texy @@ -32,8 +32,8 @@ vendor/bin/neon-lint ``` -encode(mixed $value, bool $blockMode=false): string .[method] -------------------------------------------------------------- +encode(mixed $value, bool $blockMode=false, string $indentation="\t"): string .[method] +--------------------------------------------------------------------------------------- Visszaadja a `$value` fájlt NEON-ra konvertálva. A `$blockMode` paraméterként átadható a true, ami többsoros kimenetet hoz létre. A `$indentation` paraméter megadja a behúzáshoz használt karaktereket (alapértelmezett a tabulátor). diff --git a/neon/it/@home.texy b/neon/it/@home.texy index cca2db9ae2..780064150c 100644 --- a/neon/it/@home.texy +++ b/neon/it/@home.texy @@ -32,8 +32,8 @@ vendor/bin/neon-lint ``` -encode(mixed $value, bool $blockMode=false): string .[method] -------------------------------------------------------------- +encode(mixed $value, bool $blockMode=false, string $indentation="\t"): string .[method] +--------------------------------------------------------------------------------------- Restituisce `$value` convertito in NEON. Come parametro `$blockMode` si può passare true, che creerà un output multilinea. Il parametro `$indentation` specifica i caratteri utilizzati per l'indentazione (l'impostazione predefinita è tab). diff --git a/neon/pl/@home.texy b/neon/pl/@home.texy index cb6acdb3fb..1317df6e5a 100644 --- a/neon/pl/@home.texy +++ b/neon/pl/@home.texy @@ -32,8 +32,8 @@ vendor/bin/neon-lint ``` -encode(mixed $value, bool $blockMode=false): string .[method] -------------------------------------------------------------- +encode(mixed $value, bool $blockMode=false, string $indentation="\t"): string .[method] +--------------------------------------------------------------------------------------- Zwraca `$value` przekonwertowany na NEON. Możesz przekazać true jako parametr `$blockMode`, aby utworzyć wyjście wieloliniowe. Parametr `$indentation` określa znaki używane do wcięć (domyślnie jest to tabulator). diff --git a/neon/pt/@home.texy b/neon/pt/@home.texy index 5b2111ba20..df3a57098b 100644 --- a/neon/pt/@home.texy +++ b/neon/pt/@home.texy @@ -32,8 +32,8 @@ vendor/bin/neon-lint ``` -encode(mixed $value, bool $blockMode=false): string .[method] -------------------------------------------------------------- +encode(mixed $value, bool $blockMode=false, string $indentation="\t"): string .[method] +--------------------------------------------------------------------------------------- Retorna `$value` convertido para NEON. Como o parâmetro `$blockMode` você pode passar verdadeiro, o que criará uma saída multilinha. O parâmetro `$indentation` especifica os caracteres usados para indentação (o padrão é tabulação). diff --git a/neon/ro/@home.texy b/neon/ro/@home.texy index adc84a2078..b37c1f9c08 100644 --- a/neon/ro/@home.texy +++ b/neon/ro/@home.texy @@ -32,8 +32,8 @@ vendor/bin/neon-lint ``` -encode(mixed $value, bool $blockMode=false): string .[method] -------------------------------------------------------------- +encode(mixed $value, bool $blockMode=false, string $indentation="\t"): string .[method] +--------------------------------------------------------------------------------------- Returnează `$value` convertit în NEON. Ca parametru `$blockMode` puteți trece true, care va crea o ieșire multiliniară. Parametrul `$indentation` specifică caracterele utilizate pentru indentare (valoarea implicită este tab). diff --git a/neon/ru/@home.texy b/neon/ru/@home.texy index afc65ca75c..8ee9d2f880 100644 --- a/neon/ru/@home.texy +++ b/neon/ru/@home.texy @@ -32,8 +32,8 @@ vendor/bin/neon-lint ``` -encode(mixed $value, bool $blockMode=false): string .[method] -------------------------------------------------------------- +encode(mixed $value, bool $blockMode=false, string $indentation="\t"): string .[method] +--------------------------------------------------------------------------------------- Возвращает `$value`, преобразованный в NEON. В качестве параметра `$blockMode` можно передать true, что создаст многострочный вывод. Параметр `$indentation` задает символы, используемые для отступов (по умолчанию это tab). diff --git a/neon/sl/@home.texy b/neon/sl/@home.texy index 125fe72f68..45a994a238 100644 --- a/neon/sl/@home.texy +++ b/neon/sl/@home.texy @@ -32,8 +32,8 @@ vendor/bin/neon-lint ``` -encode(mixed $value, bool $blockMode=false): string .[method] -------------------------------------------------------------- +encode(mixed $value, bool $blockMode=false, string $indentation="\t"): string .[method] +--------------------------------------------------------------------------------------- Vrne `$value`, pretvorjeno v NEON. Kot parameter `$blockMode` lahko posredujete true, kar bo ustvarilo večvrstični izpis. Parameter `$indentation` določa znake, ki se uporabljajo za odtiskovanje (privzeto je tabulator). diff --git a/neon/tr/@home.texy b/neon/tr/@home.texy index f2bf1cb356..2b762e7fa8 100644 --- a/neon/tr/@home.texy +++ b/neon/tr/@home.texy @@ -32,8 +32,8 @@ vendor/bin/neon-lint ``` -encode(mixed $value, bool $blockMode=false): string .[method] -------------------------------------------------------------- +encode(mixed $value, bool $blockMode=false, string $indentation="\t"): string .[method] +--------------------------------------------------------------------------------------- NEON'a dönüştürülmüş `$value` döndürür. Parametre olarak `$blockMode` çok satırlı çıktı oluşturacak true değerini geçebilirsiniz. `$indentation` parametresi girinti için kullanılan karakterleri belirtir (varsayılan tab'dır). diff --git a/neon/uk/@home.texy b/neon/uk/@home.texy index 26b3e05d9a..26178bdf6a 100644 --- a/neon/uk/@home.texy +++ b/neon/uk/@home.texy @@ -32,8 +32,8 @@ vendor/bin/neon-lint ``` -encode(mixed $value, bool $blockMode=false): string .[method] -------------------------------------------------------------- +encode(mixed $value, bool $blockMode=false, string $indentation="\t"): string .[method] +--------------------------------------------------------------------------------------- Повертає `$value`, перетворений у NEON. Як параметр `$blockMode` можна передати true, що створить багаторядковий вивід. Параметр `$indentation` задає символи, що використовуються для відступів (за замовчуванням це tab). From b698ccbbe5edbaa725326a677336ae38407088c6 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sun, 31 Dec 2023 15:00:45 +0100 Subject: [PATCH 045/137] typo --- forms/cs/controls.texy | 2 +- forms/en/controls.texy | 2 +- utils/bg/arrays.texy | 4 ++-- utils/cs/arrays.texy | 4 ++-- utils/de/arrays.texy | 4 ++-- utils/el/arrays.texy | 4 ++-- utils/en/arrays.texy | 4 ++-- utils/es/arrays.texy | 4 ++-- utils/fr/arrays.texy | 4 ++-- utils/hu/arrays.texy | 4 ++-- utils/it/arrays.texy | 4 ++-- utils/pl/arrays.texy | 4 ++-- utils/pt/arrays.texy | 4 ++-- utils/ro/arrays.texy | 4 ++-- utils/ru/arrays.texy | 4 ++-- utils/sl/arrays.texy | 4 ++-- utils/tr/arrays.texy | 4 ++-- utils/uk/arrays.texy | 4 ++-- 18 files changed, 34 insertions(+), 34 deletions(-) diff --git a/forms/cs/controls.texy b/forms/cs/controls.texy index a2deebc6b2..978a487f79 100644 --- a/forms/cs/controls.texy +++ b/forms/cs/controls.texy @@ -483,7 +483,7 @@ $form->addText('username', 'Uživatelské jméno:') Disablované prvky prohlížeč vůbec neodesílá na server, tedy je ani nenajdete v datech vrácených funkcí `$form->getValues()`. Pokud však nastavíte `setOmitted(false)`, Nette jejich hodnotu do těchto dat zahrne. -Při volání `setDisabled()` se smaže hodnota prvku. Pokud nastavujete výchozí hodnotu, je tak nutné učinit až po jeho deaktivaci: +Při volání `setDisabled()` se **smaže hodnota prvku**. Pokud nastavujete výchozí hodnotu, je tak nutné učinit až po jeho deaktivaci: ```php $form->addText('username', 'Uživatelské jméno:') diff --git a/forms/en/controls.texy b/forms/en/controls.texy index d81a6cda87..f222681bb9 100644 --- a/forms/en/controls.texy +++ b/forms/en/controls.texy @@ -483,7 +483,7 @@ $form->addText('username', 'User name:') Disabled fields are not sent by the browser to the server at all, so you will not find them in the data returned by the `$form->getValues()` function. However, if you set `setOmitted(false)`, Nette will include their value in this data. -When you call `setDisabled()`, the value of the field is deleted. If you are setting a default value, you must do so after deactivating it: +When you call `setDisabled()`, the **value of the field is deleted**. If you are setting a default value, you must do so after deactivating it: ```php $form->addText('username', 'User name:') diff --git a/utils/bg/arrays.texy b/utils/bg/arrays.texy index 8335fd2567..07d74c2de8 100644 --- a/utils/bg/arrays.texy +++ b/utils/bg/arrays.texy @@ -362,8 +362,8 @@ Arrays::toObject($array, $obj); // nastaví $obj->foo = 1; $obj->bar = 2; ``` -wrap(iterable $array, string $prefix='', string $suffix=''): array .[method] ----------------------------------------------------------------------------- +wrap(array $array, string $prefix='', string $suffix=''): array .[method] +------------------------------------------------------------------------- Извежда всеки елемент от масива в низ и го обвива с префикс `$prefix` и суфикс `$suffix`. diff --git a/utils/cs/arrays.texy b/utils/cs/arrays.texy index 1f4d07cfe7..f4e63d26fb 100644 --- a/utils/cs/arrays.texy +++ b/utils/cs/arrays.texy @@ -362,8 +362,8 @@ Arrays::toObject($array, $obj); // nastaví $obj->foo = 1; $obj->bar = 2; ``` -wrap(iterable $array, string $prefix='', string $suffix=''): array .[method] ----------------------------------------------------------------------------- +wrap(array $array, string $prefix='', string $suffix=''): array .[method] +------------------------------------------------------------------------- Každou položku v poli přetypuje na řetězec a obalí předponou `$prefix` a příponou `$suffix`. diff --git a/utils/de/arrays.texy b/utils/de/arrays.texy index 0e9af6de6f..cd3ec38478 100644 --- a/utils/de/arrays.texy +++ b/utils/de/arrays.texy @@ -362,8 +362,8 @@ Arrays::toObject($array, $obj); // it sets $obj->foo = 1; $obj->bar = 2; ``` -wrap(iterable $array, string $prefix='', string $suffix=''): array .[method] ----------------------------------------------------------------------------- +wrap(array $array, string $prefix='', string $suffix=''): array .[method] +------------------------------------------------------------------------- Jedes Element des Arrays wird in einen String umgewandelt und mit `$prefix` und `$suffix` umschlossen. diff --git a/utils/el/arrays.texy b/utils/el/arrays.texy index ecc30f96e7..6bb271d5e7 100644 --- a/utils/el/arrays.texy +++ b/utils/el/arrays.texy @@ -362,8 +362,8 @@ Arrays::toObject($array, $obj); // θέτει $obj->foo = 1; $obj->bar = 2; ``` -wrap(iterable $array, string $prefix='', string $suffix=''): array .[method] ----------------------------------------------------------------------------- +wrap(array $array, string $prefix='', string $suffix=''): array .[method] +------------------------------------------------------------------------- Μετατρέπει κάθε στοιχείο του πίνακα σε συμβολοσειρά και το περικλείει με τα `$prefix` και `$suffix`. diff --git a/utils/en/arrays.texy b/utils/en/arrays.texy index 1ff2791f1e..d55ef13abb 100644 --- a/utils/en/arrays.texy +++ b/utils/en/arrays.texy @@ -362,8 +362,8 @@ Arrays::toObject($array, $obj); // it sets $obj->foo = 1; $obj->bar = 2; ``` -wrap(iterable $array, string $prefix='', string $suffix=''): array .[method] ----------------------------------------------------------------------------- +wrap(array $array, string $prefix='', string $suffix=''): array .[method] +------------------------------------------------------------------------- It casts each element of array to string and encloses it with `$prefix` and `$suffix`. diff --git a/utils/es/arrays.texy b/utils/es/arrays.texy index 16f64b28d8..219739fbdc 100644 --- a/utils/es/arrays.texy +++ b/utils/es/arrays.texy @@ -362,8 +362,8 @@ Arrays::toObject($array, $obj); // it sets $obj->foo = 1; $obj->bar = 2; ``` -wrap(iterable $array, string $prefix='', string $suffix=''): array .[method] ----------------------------------------------------------------------------- +wrap(array $array, string $prefix='', string $suffix=''): array .[method] +------------------------------------------------------------------------- Convierte cada elemento del array en cadena y lo encierra con `$prefix` y `$suffix`. diff --git a/utils/fr/arrays.texy b/utils/fr/arrays.texy index 8ac6ab134c..b99a079110 100644 --- a/utils/fr/arrays.texy +++ b/utils/fr/arrays.texy @@ -362,8 +362,8 @@ Arrays::toObject($array, $obj); // it sets $obj->foo = 1; $obj->bar = 2; ``` -wrap(iterable $array, string $prefix='', string $suffix=''): array .[method] ----------------------------------------------------------------------------- +wrap(array $array, string $prefix='', string $suffix=''): array .[method] +------------------------------------------------------------------------- Il transforme chaque élément du tableau en chaîne de caractères et l'entoure de `$prefix` et `$suffix`. diff --git a/utils/hu/arrays.texy b/utils/hu/arrays.texy index b38d952c9d..04ad5c1c18 100644 --- a/utils/hu/arrays.texy +++ b/utils/hu/arrays.texy @@ -362,8 +362,8 @@ Arrays::toObject($array, $obj); // beállítja $obj->foo = 1; $obj->bar = 2; ``` -wrap(iterable $array, string $prefix='', string $suffix=''): array .[method] ----------------------------------------------------------------------------- +wrap(array $array, string $prefix='', string $suffix=''): array .[method] +------------------------------------------------------------------------- A tömb minden egyes elemét karakterlánccá alakítja, és a `$prefix` és a `$suffix` objektummal körülveszi. diff --git a/utils/it/arrays.texy b/utils/it/arrays.texy index c9e8f0019b..55a5397fa5 100644 --- a/utils/it/arrays.texy +++ b/utils/it/arrays.texy @@ -362,8 +362,8 @@ Arrays::toObject($array, $obj); // imposta $obj->foo = 1; $obj->bar = 2; ``` -wrap(iterable $array, string $prefix='', string $suffix=''): array .[method] ----------------------------------------------------------------------------- +wrap(array $array, string $prefix='', string $suffix=''): array .[method] +------------------------------------------------------------------------- Lancia ogni elemento dell'array come stringa e lo racchiude con `$prefix` e `$suffix`. diff --git a/utils/pl/arrays.texy b/utils/pl/arrays.texy index f605e4e771..2ca6c6d02d 100644 --- a/utils/pl/arrays.texy +++ b/utils/pl/arrays.texy @@ -362,8 +362,8 @@ Arrays::toObject($array, $obj); // nastaví $obj->foo = 1; $obj->bar = 2; ``` -wrap(iterable $array, string $prefix='', string $suffix=''): array .[method] ----------------------------------------------------------------------------- +wrap(array $array, string $prefix='', string $suffix=''): array .[method] +------------------------------------------------------------------------- Wypisuje każdy element tablicy do łańcucha i opakowuje go prefiksem `$prefix` i sufiksem `$suffix`. diff --git a/utils/pt/arrays.texy b/utils/pt/arrays.texy index 4123f387e7..2b08aa82f7 100644 --- a/utils/pt/arrays.texy +++ b/utils/pt/arrays.texy @@ -362,8 +362,8 @@ Arrays::toObject($array, $obj); // it sets $obj->foo = 1; $obj->bar = 2; ``` -wrap(iterable $array, string $prefix='', string $suffix=''): array .[method] ----------------------------------------------------------------------------- +wrap(array $array, string $prefix='', string $suffix=''): array .[method] +------------------------------------------------------------------------- Ele lança cada elemento da matriz para cordelar e o encerra com `$prefix` e `$suffix`. diff --git a/utils/ro/arrays.texy b/utils/ro/arrays.texy index cef51c281a..82d9789065 100644 --- a/utils/ro/arrays.texy +++ b/utils/ro/arrays.texy @@ -362,8 +362,8 @@ Arrays::toObject($array, $obj); // setează $obj->foo = 1; $obj->bar = 2; ``` -wrap(iterable $array, string $prefix='', string $suffix=''): array .[method] ----------------------------------------------------------------------------- +wrap(array $array, string $prefix='', string $suffix=''): array .[method] +------------------------------------------------------------------------- Transformă fiecare element al tabloului în șir de caractere și îl închide cu `$prefix` și `$suffix`. diff --git a/utils/ru/arrays.texy b/utils/ru/arrays.texy index 65b8239ac0..ba4e191f21 100644 --- a/utils/ru/arrays.texy +++ b/utils/ru/arrays.texy @@ -362,8 +362,8 @@ Arrays::toObject($array, $obj); // nastaví $obj->foo = 1; $obj->bar = 2; ``` -wrap(iterable $array, string $prefix='', string $suffix=''): array .[method] ----------------------------------------------------------------------------- +wrap(array $array, string $prefix='', string $suffix=''): array .[method] +------------------------------------------------------------------------- Выводит каждый элемент массива в строку и оборачивает ее префиксом `$prefix` и суффиксом `$suffix`. diff --git a/utils/sl/arrays.texy b/utils/sl/arrays.texy index f22a6455aa..7f042b7ea8 100644 --- a/utils/sl/arrays.texy +++ b/utils/sl/arrays.texy @@ -362,8 +362,8 @@ Arrays::toObject($array, $obj); // nastavi $obj->foo = 1; $obj->bar = 2; ``` -wrap(iterable $array, string $prefix='', string $suffix=''): array .[method] ----------------------------------------------------------------------------- +wrap(array $array, string $prefix='', string $suffix=''): array .[method] +------------------------------------------------------------------------- Vsak element polja pretvori v niz in ga obkroži z objektoma `$prefix` in `$suffix`. diff --git a/utils/tr/arrays.texy b/utils/tr/arrays.texy index ec00b29131..42130c7358 100644 --- a/utils/tr/arrays.texy +++ b/utils/tr/arrays.texy @@ -362,8 +362,8 @@ Arrays::toObject($array, $obj); // it sets $obj->foo = 1; $obj->bar = 2; ``` -wrap(iterable $array, string $prefix='', string $suffix=''): array .[method] ----------------------------------------------------------------------------- +wrap(array $array, string $prefix='', string $suffix=''): array .[method] +------------------------------------------------------------------------- Dizinin her bir elemanını dizeye dönüştürür ve `$prefix` ve `$suffix` ile çevreler. diff --git a/utils/uk/arrays.texy b/utils/uk/arrays.texy index 7dd065d131..f47e1096a2 100644 --- a/utils/uk/arrays.texy +++ b/utils/uk/arrays.texy @@ -362,8 +362,8 @@ Arrays::toObject($array, $obj); // додаємо $obj->foo = 1; $obj->bar = 2; ``` -wrap(iterable $array, string $prefix='', string $suffix=''): array .[method] ----------------------------------------------------------------------------- +wrap(array $array, string $prefix='', string $suffix=''): array .[method] +------------------------------------------------------------------------- Виводить кожен елемент масиву в рядок і обертає його префіксом `$prefix` і суфіксом `$suffix`. From 56bde14d3277ff59a6764729585c612faaea118a Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 17 Jan 2024 16:18:21 +0100 Subject: [PATCH 046/137] nette/utils 4.0.4 --- utils/bg/@home.texy | 1 + utils/bg/@left-menu.texy | 1 + utils/bg/arrays.texy | 96 ++++++++++++++++++++++++------- utils/bg/images.texy | 5 ++ utils/bg/iterables.texy | 119 +++++++++++++++++++++++++++++++++++++++ utils/cs/@home.texy | 1 + utils/cs/@left-menu.texy | 1 + utils/cs/arrays.texy | 96 ++++++++++++++++++++++++------- utils/cs/images.texy | 5 ++ utils/cs/iterables.texy | 119 +++++++++++++++++++++++++++++++++++++++ utils/de/@home.texy | 1 + utils/de/@left-menu.texy | 1 + utils/de/arrays.texy | 92 ++++++++++++++++++++++++------ utils/de/images.texy | 5 ++ utils/de/iterables.texy | 119 +++++++++++++++++++++++++++++++++++++++ utils/el/@home.texy | 1 + utils/el/@left-menu.texy | 1 + utils/el/arrays.texy | 92 ++++++++++++++++++++++++------ utils/el/images.texy | 5 ++ utils/el/iterables.texy | 119 +++++++++++++++++++++++++++++++++++++++ utils/en/@home.texy | 1 + utils/en/@left-menu.texy | 1 + utils/en/arrays.texy | 92 ++++++++++++++++++++++++------ utils/en/images.texy | 5 ++ utils/en/iterables.texy | 119 +++++++++++++++++++++++++++++++++++++++ utils/es/@home.texy | 1 + utils/es/@left-menu.texy | 1 + utils/es/arrays.texy | 92 ++++++++++++++++++++++++------ utils/es/images.texy | 5 ++ utils/es/iterables.texy | 119 +++++++++++++++++++++++++++++++++++++++ utils/fr/@home.texy | 1 + utils/fr/@left-menu.texy | 1 + utils/fr/arrays.texy | 92 ++++++++++++++++++++++++------ utils/fr/images.texy | 5 ++ utils/fr/iterables.texy | 119 +++++++++++++++++++++++++++++++++++++++ utils/hu/@home.texy | 1 + utils/hu/@left-menu.texy | 1 + utils/hu/arrays.texy | 92 ++++++++++++++++++++++++------ utils/hu/images.texy | 5 ++ utils/hu/iterables.texy | 119 +++++++++++++++++++++++++++++++++++++++ utils/it/@home.texy | 1 + utils/it/@left-menu.texy | 1 + utils/it/arrays.texy | 92 ++++++++++++++++++++++++------ utils/it/images.texy | 5 ++ utils/it/iterables.texy | 119 +++++++++++++++++++++++++++++++++++++++ utils/pl/@home.texy | 1 + utils/pl/@left-menu.texy | 1 + utils/pl/arrays.texy | 96 ++++++++++++++++++++++++------- utils/pl/images.texy | 5 ++ utils/pl/iterables.texy | 119 +++++++++++++++++++++++++++++++++++++++ utils/pt/@home.texy | 1 + utils/pt/@left-menu.texy | 1 + utils/pt/arrays.texy | 92 ++++++++++++++++++++++++------ utils/pt/images.texy | 5 ++ utils/pt/iterables.texy | 119 +++++++++++++++++++++++++++++++++++++++ utils/ro/@home.texy | 1 + utils/ro/@left-menu.texy | 1 + utils/ro/arrays.texy | 92 ++++++++++++++++++++++++------ utils/ro/images.texy | 5 ++ utils/ro/iterables.texy | 119 +++++++++++++++++++++++++++++++++++++++ utils/ru/@home.texy | 1 + utils/ru/@left-menu.texy | 1 + utils/ru/arrays.texy | 96 ++++++++++++++++++++++++------- utils/ru/images.texy | 5 ++ utils/ru/iterables.texy | 119 +++++++++++++++++++++++++++++++++++++++ utils/sl/@home.texy | 1 + utils/sl/@left-menu.texy | 1 + utils/sl/arrays.texy | 92 ++++++++++++++++++++++++------ utils/sl/images.texy | 5 ++ utils/sl/iterables.texy | 119 +++++++++++++++++++++++++++++++++++++++ utils/tr/@home.texy | 1 + utils/tr/@left-menu.texy | 1 + utils/tr/arrays.texy | 92 ++++++++++++++++++++++++------ utils/tr/images.texy | 5 ++ utils/tr/iterables.texy | 119 +++++++++++++++++++++++++++++++++++++++ utils/uk/@home.texy | 1 + utils/uk/@left-menu.texy | 1 + utils/uk/arrays.texy | 96 ++++++++++++++++++++++++------- utils/uk/images.texy | 5 ++ utils/uk/iterables.texy | 119 +++++++++++++++++++++++++++++++++++++++ 80 files changed, 3226 insertions(+), 282 deletions(-) create mode 100644 utils/bg/iterables.texy create mode 100644 utils/cs/iterables.texy create mode 100644 utils/de/iterables.texy create mode 100644 utils/el/iterables.texy create mode 100644 utils/en/iterables.texy create mode 100644 utils/es/iterables.texy create mode 100644 utils/fr/iterables.texy create mode 100644 utils/hu/iterables.texy create mode 100644 utils/it/iterables.texy create mode 100644 utils/pl/iterables.texy create mode 100644 utils/pt/iterables.texy create mode 100644 utils/ro/iterables.texy create mode 100644 utils/ru/iterables.texy create mode 100644 utils/sl/iterables.texy create mode 100644 utils/tr/iterables.texy create mode 100644 utils/uk/iterables.texy diff --git a/utils/bg/@home.texy b/utils/bg/@home.texy index 21e46d7f6c..bf120bdbac 100644 --- a/utils/bg/@home.texy +++ b/utils/bg/@home.texy @@ -13,6 +13,7 @@ | [Nette\Utils\Image |images] | [Пагинация |paginator] | Nette\Utils\Paginator | [Парсинг и генериране на JSON |json] | Nette\Utils\Json +| [Iterables |iterables] | Nette\Utils\Iterables | [Полета |arrays] | Nette\Utils\Arrays | [Низове |strings] | Nette\Utils\Strings | [Тип Nette\Utils\Type |type] diff --git a/utils/bg/@left-menu.texy b/utils/bg/@left-menu.texy index 1c661ebc3d..8c8dc979e3 100644 --- a/utils/bg/@left-menu.texy +++ b/utils/bg/@left-menu.texy @@ -8,6 +8,7 @@ - [Снимки |images] - [Обратни извиквания |callback] - [Пагинатор |paginator] +- [Iterables |iterables] - [Поле |arrays] - [Случайни низове |random] - [Струни |strings] diff --git a/utils/bg/arrays.texy b/utils/bg/arrays.texy index 07d74c2de8..f759d61f5c 100644 --- a/utils/bg/arrays.texy +++ b/utils/bg/arrays.texy @@ -15,7 +15,7 @@ composer require nette/utils Масиви .[#toc-arrays] ===================== -[api:Nette\Utils\Arrays] е статичен клас, който съдържа полезни функции за работа с масиви. +[api:Nette\Utils\Arrays] е статичен клас, който съдържа няколко удобни функции за масиви. Неговият еквивалент за итератори е [Nette\Utils\Iterables |iterables]. Следващите примери предполагат, че псевдонимът вече е създаден: @@ -76,10 +76,10 @@ Arrays::contains(['1', false], 1); // false ``` -every(iterable $array, callable $callback): bool .[method] ----------------------------------------------------------- +every(array $array, callable $predicate): bool .[method] +-------------------------------------------------------- -Проверява дали всички елементи в масива са преминали теста, реализиран в `$callback` с подпис `function ($value, $key, array $array): bool`. +Проверява дали всички елементи в масива са преминали теста, реализиран в `$predicate` с подпис `function ($value, $key, array $array): bool`. ```php $array = [1, 30, 39, 29, 10, 13]; @@ -90,16 +90,52 @@ $res = Arrays::every($array, $isBelowThreshold); // true Вижте [some( |#some]). -first(array $array): mixed .[method] ------------------------------------- +filter(array $array, callable $predicate): array .[method]{data-version:4.0.4} +------------------------------------------------------------------------------ + +Връща нов масив, съдържащ всички двойки ключ-стойност, отговарящи на зададения `$predicate`. Обратното извикване има сигнатурата `function ($value, int|string $key, array $array): bool`. + +```php +Arrays::filter( + ['a' => 1, 'b' => 2, 'c' => 3], + fn($v) => $v < 3, +); +// ['a' => 1, 'b' => 2] +``` + + +first(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------- + +Връща първия елемент (отговарящ на зададеното предсказание, ако е дадено). Ако няма такъв елемент, връща резултата от извикването на `$else` или null. + `$predicate` има сигнатура `function ($value, int|string $key, array $array): bool`. + +Той не променя вътрешния указател за разлика от `reset()`. Параметрите `$predicate` и `$else` съществуват от версия 4.0.4. + +```php +Arrays::first([1, 2, 3]); // 1 +Arrays::first([1, 2, 3], fn($v) => $v > 2); // 3 +Arrays::first([]); // null +Arrays::first([], else: fn() => false); // false +``` -Връща първия запис в масива или null, ако масивът е празен. Не променя вътрешния указател, за разлика от `reset()`. +Вижте [last() |#last()]. + + +firstKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4} +------------------------------------------------------------------------------------------------ + +Връща ключа на първия елемент (отговарящ на зададения предикат, ако е зададен) или null, ако няма такъв елемент. `$predicate` има сигнатура `function ($value, int|string $key, array $array): bool`. ```php -Arrays::first([1, 2, 3]); // 1 -Масиви::first([]); // null +Arrays::firstKey([1, 2, 3]); // 0 +Arrays::firstKey([1, 2, 3], fn($v) => $v > 2); // 2 +Arrays::firstKey(['a' => 1, 'b' => 2]); // 'a' +Arrays::firstKey([]); // null ``` +Вижте [lastKey( |#lastKey()]). + flatten(array $array, bool $preserveKeys=false): array .[method] ---------------------------------------------------------------- @@ -229,21 +265,43 @@ Arrays::isList(['a' => 1, 'b' => 2]); // false ``` -last(array $array): mixed .[method] ------------------------------------ +last(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------ + +Връща последния елемент (отговарящ на зададения предикат, ако е зададен). Ако няма такъв елемент, връща резултата от извикването на `$else` или null. + `$predicate` има сигнатура `function ($value, int|string $key, array $array): bool`. + +Той не променя вътрешния указател за разлика от `end()`. Параметрите `$predicate` и `$else` съществуват от версия 4.0.4. + +```php +Arrays::last([1, 2, 3]); // 3 +Arrays::last([1, 2, 3], fn($v) => $v < 3); // 2 +Arrays::last([]); // null +Arrays::last([], else: fn() => false); // false +``` + +Вижте [first( |#first()]). + -Връща последния запис на масива или null, ако масивът е празен. Не променя вътрешния указател, за разлика от `end()`. +lastKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4} +----------------------------------------------------------------------------------------------- + +Връща ключа на последния елемент (отговарящ на зададения предикат, ако е зададен) или null, ако няма такъв елемент. `$predicate` има сигнатура `function ($value, int|string $key, array $array): bool`. ```php -Arrays::last([1, 2, 3]); // 3 -Arrays::last([]); // null +Arrays::lastKey([1, 2, 3]); // 2 +Arrays::lastKey([1, 2, 3], fn($v) => $v < 3); // 1 +Arrays::lastKey(['a' => 1, 'b' => 2]); // 'b' +Arrays::lastKey([]); // null ``` +Вижте [firstKey( |#firstKey()]). + -map(iterable $array, callable $callback): array .[method] +map(array $array, callable $transformer): array .[method] --------------------------------------------------------- -Извиква `$callback` върху всички елементи на масив и връща масив от върнати стойности. Обратното извикване има сигнатура `function ($value, $key, array $array): bool`. +Извиква `$transformer` върху всички елементи на масив и връща масив от върнати стойности. Обратното извикване има сигнатура `function ($value, $key, array $array): bool`. ```php $array = ['foo', 'bar', 'baz']; @@ -325,10 +383,10 @@ $position = Arrays::getKeyOffset($array, 'not-exists'); // vrátí null ``` -some(iterable $array, callable $callback): bool .[method] ---------------------------------------------------------- +some(array $array, callable $predicate): bool .[method] +------------------------------------------------------- -Проверява се дали поне един елемент от масива е преминал теста, реализиран в `$callback`, с подпис `function ($value, $key, array $array): bool`. +Проверява се дали поне един елемент от масива е преминал теста, реализиран в `$predicate`, с подпис `function ($value, $key, array $array): bool`. ```php $array = [1, 2, 3, 4]; diff --git a/utils/bg/images.texy b/utils/bg/images.texy index 68435e34bd..ba22eb6872 100644 --- a/utils/bg/images.texy +++ b/utils/bg/images.texy @@ -300,6 +300,11 @@ static isTypeSupported(int $type): bool .[method] Определя дали даденият [тип |#Formats] изображение се поддържа. +static getSupportedTypes(): array .[method]{data-version:4.0.4} +--------------------------------------------------------------- +Връща масив от поддържаните типове изображения (константи `ImageType::XXX`). + + static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method] ------------------------------------------------------------------------------------------------------------------------ Изчислява размерите на правоъгълника, който огражда текст с определен шрифт и размер. Връща асоциативен масив, съдържащ ключовете `left`, `top`, `width`, `height`. Лявото поле може да бъде отрицателно, ако текстът започва с ляв надвес. diff --git a/utils/bg/iterables.texy b/utils/bg/iterables.texy new file mode 100644 index 0000000000..8fcdc85e1d --- /dev/null +++ b/utils/bg/iterables.texy @@ -0,0 +1,119 @@ +Функции на итератора +******************** + +.[perex]{data-version:4.0.4} +[api:Nette\Utils\Iterables] е статичен клас с функции за работа с итератори. Неговият аналог за масиви е [Nette\Utils\Arrays |arrays]. + + +Инсталация: + +```shell +composer require nette/utils +``` + +Всички примери предполагат създаването на псевдоним: + +```php +use Nette\Utils\Iterables; +``` + + +contains(iterable $iterable, $value): bool .[method] +---------------------------------------------------- + +Тества за наличие на стойност в итератора. Използва стриктно сравнение (`===`). + +```php +Iterables::contains(new ArrayIterator([1, 2, 3]), 1); // true +Iterables::contains(new ArrayIterator([1, 2, 3]), '1'); // false +``` + + +containsKey(iterable $iterable, $value): bool .[method] +------------------------------------------------------- + +Тества за наличие на ключ в итератора. Използва стриктно сравнение (`===`). + +```php +Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0); // true +Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4); // false +``` + + +every(iterable $iterable, callable $predicate): bool .[method] +-------------------------------------------------------------- + +Проверява дали всички елементи на итератора са преминали тест, реализиран в `$predicate` със сигнатура `function ($value, $key, iterable $iterable): bool`. + +```php +$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]); +$isBelowThreshold = fn($value) => $value < 40; +$res = Iterables::every($iterator, $isBelowThreshold); // true +``` + +Вижте [some( |#some()]). + + +filter(iterable $iterable, callable $predicate): Generator .[method] +-------------------------------------------------------------------- + +Итератор, който филтрира елементите в съответствие с предикат. Предикатът има сигнатурата `function ($value, $key, iterable $iterable): bool`. Запазва оригиналните ключове. + +```php +$iterator = new ArrayIterator([1, 2, 3]); +$iterator = Iterables::filter($iterator, fn($v) => $v < 3); +// 1, 2 +``` + + +first(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------------- + +Връща първия елемент (отговарящ на предиката, ако е зададен). Ако няма такъв елемент, се връща резултатът от извикването на `$else` или null. +Параметърът `$predicate` има сигнатура `function ($value, $key, iterable $iterable): bool`. + +```php +Iterables::first(new ArrayIterator([1, 2, 3])); // 1 +Iterables::first(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 3 +Iterables::first(new ArrayIterator([])); // null +Iterables::first(new ArrayIterator([]), else: fn() => false); // false +``` + + +firstKey(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method] +---------------------------------------------------------------------------------------------- + +Връща ключа на първия елемент (отговарящ на предиката, ако е зададен). Ако няма такъв елемент, се връща резултатът от извикването на `$else` или null. Предикатът има сигнатура `function ($value, $key, iterable $iterable): bool`. + +```php +Iterables::firstKey(new ArrayIterator([1, 2, 3])); // 0 +Iterables::firstKey(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 2 +Iterables::firstKey(new ArrayIterator(['a' => 1, 'b' => 2])); // 'a' +Iterables::firstKey(new ArrayIterator([])); // null +``` + + +map(iterable $iterable, callable $transformer): array .[method] +--------------------------------------------------------------- + +Итератор, който трансформира стойностите чрез извикване на `$transformer`. Той има сигнатура `function ($value, $key, iterable $iterable): bool`. Запазва оригиналните ключове. + +```php +$iterator = new ArrayIterator([1, 2, 3]); +$iterator = Iterables::map($iterator, fn($v) => $v * 2); +// 2, 4, 6 +``` + + +some(iterable $iterable, callable $predicate): bool .[method] +------------------------------------------------------------- + +Проверява дали поне един елемент от итератора преминава тест, реализиран в `$predicate` със сигнатура `function ($value, $key, iterable $iterable): bool`. + +```php +$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]); +$isEven = fn($value) => $value % 2 === 0; +$res = Iterables::some($iterator, $isEven); // true +``` + +Вижте [every( |#every()]). diff --git a/utils/cs/@home.texy b/utils/cs/@home.texy index bd9a730b5f..4afd52488a 100644 --- a/utils/cs/@home.texy +++ b/utils/cs/@home.texy @@ -8,6 +8,7 @@ V balíčku `nette/utils` najdete sadu užitečných tříd pro každodenní pou | [Datum a čas |datetime] | Nette\Utils\DateTime | [Finder] | Nette\Utils\Finder | [HTML elementy |html-elements] | Nette\Utils\Html +| [Iterátory |iterables] | Nette\Utils\Iterables | [JSON |json] | Nette\Utils\Json | [Náhodné řetězce |random] | Nette\Utils\Random | [Obrázky |images] | Nette\Utils\Image diff --git a/utils/cs/@left-menu.texy b/utils/cs/@left-menu.texy index f64ec996d3..387fe25685 100644 --- a/utils/cs/@left-menu.texy +++ b/utils/cs/@left-menu.texy @@ -5,6 +5,7 @@ Balíček nette/utils - [Finder] - [Floats] - [HTML elementy |html-elements] +- [Iterátory |iterables] - [JSON] - [Náhodné řetězce |random] - [Obrázky |images] diff --git a/utils/cs/arrays.texy b/utils/cs/arrays.texy index f4e63d26fb..b97bf5a19b 100644 --- a/utils/cs/arrays.texy +++ b/utils/cs/arrays.texy @@ -15,7 +15,7 @@ composer require nette/utils Arrays ====== -[api:Nette\Utils\Arrays] je statická třída obsahující užitečné funkce pro práci s poli. +[api:Nette\Utils\Arrays] je statická třída obsahující užitečné funkce pro práci s poli. Její obdobou pro iterátory je [Nette\Utils\Iterables|iterables]. Následující příklady předpokládají vytvořený alias: @@ -76,10 +76,10 @@ Arrays::contains(['1', false], 1); // false ``` -every(iterable $array, callable $callback): bool .[method] ----------------------------------------------------------- +every(array $array, callable $predicate): bool .[method] +-------------------------------------------------------- -Testuje, zda všechny prvky v poli projdou testem implementovaným v `$callback` se signaturou `function ($value, $key, array $array): bool`. +Testuje, zda všechny prvky v poli projdou testem implementovaným v `$predicate` se signaturou `function ($value, $key, array $array): bool`. ```php $array = [1, 30, 39, 29, 10, 13]; @@ -90,16 +90,52 @@ $res = Arrays::every($array, $isBelowThreshold); // true Viz [#some()]. -first(array $array): mixed .[method] ------------------------------------- +filter(array $array, callable $predicate): array .[method]{data-version:4.0.4} +------------------------------------------------------------------------------ + +Vrací nové pole obsahující všechny dvojice klíč-hodnota odpovídající zadanému predikátu. Callback má signaturu `function ($value, int|string $key, array $array): bool`. + +```php +Arrays::filter( + ['a' => 1, 'b' => 2, 'c' => 3], + fn($v) => $v < 3, +); +// ['a' => 1, 'b' => 2] +``` + + +first(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------- + +Vrátí první položku (odpovídající predikátu, je-li zadán). Pokud taková položka neexistuje, vrátí výsledek volání `$else` nebo null. +Parametr `$predicate` má signaturu `function ($value, int|string $key, array $array): bool`. + +Nezmění vnitřní ukazatel narozdíl od `reset()`. Parametry `$predicate` a `$else` existují od verze 4.0.4. + +```php +Arrays::first([1, 2, 3]); // 1 +Arrays::first([1, 2, 3], fn($v) => $v > 2); // 3 +Arrays::first([]); // null +Arrays::first([], else: fn() => false); // false +``` -Vrátí první položku z pole nebo null, pokud je pole prázdné. Nezmění vnitřní ukazatel narozdíl od `reset()`. +Viz [#last()]. + + +firstKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4} +------------------------------------------------------------------------------------------------ + +Vrací klíč první položky (odpovídající predikátu, pokud je uveden) nebo null, pokud taková položka neexistuje. Predikát `$predicate` má signaturu `function ($value, int|string $key, array $array): bool`. ```php -Arrays::first([1, 2, 3]); // 1 -Arrays::first([]); // null +Arrays::firstKey([1, 2, 3]); // 0 +Arrays::firstKey([1, 2, 3], fn($v) => $v > 2); // 2 +Arrays::firstKey(['a' => 1, 'b' => 2]); // 'a' +Arrays::firstKey([]); // null ``` +Viz [#lastKey()]. + flatten(array $array, bool $preserveKeys=false): array .[method] ---------------------------------------------------------------- @@ -229,21 +265,43 @@ Arrays::isList(['a' => 1, 'b' => 2]); // false ``` -last(array $array): mixed .[method] ------------------------------------ +last(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------ + +Vrátí poslední položku (odpovídající predikátu, je-li zadán). Pokud taková položka neexistuje, vrátí výsledek volání `$else` nebo null. +Parametr `$predicate` má signaturu `function ($value, int|string $key, array $array): bool`. + +Nezmění vnitřní ukazatel narozdíl od `end()`. Parametry `$predicate` a `$else` existují od verze 4.0.4. + +```php +Arrays::last([1, 2, 3]); // 3 +Arrays::last([1, 2, 3], fn($v) => $v < 3); // 2 +Arrays::last([]); // null +Arrays::last([], else: fn() => false); // false +``` + +Viz [#first()]. + -Vrátí poslední položku z pole nebo null, pokud je pole prázdné. Nezmění vnitřní ukazatel narozdíl od `end()`. +lastKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4} +----------------------------------------------------------------------------------------------- + +Vrací klíč poslední položky (odpovídající predikátu, pokud je uveden) nebo null, pokud taková položka neexistuje. Predikát `$predicate` má signaturu `function ($value, int|string $key, array $array): bool`. ```php -Arrays::last([1, 2, 3]); // 3 -Arrays::last([]); // null +Arrays::lastKey([1, 2, 3]); // 2 +Arrays::lastKey([1, 2, 3], fn($v) => $v < 3); // 1 +Arrays::lastKey(['a' => 1, 'b' => 2]); // 'b' +Arrays::lastKey([]); // null ``` +Viz [#firstKey()]. + -map(iterable $array, callable $callback): array .[method] +map(array $array, callable $transformer): array .[method] --------------------------------------------------------- -Zavolá `$callback` na všechny prvky v poli a vrátí pole vrácených hodnot. Callback má signaturu `function ($value, $key, array $array): bool`. +Zavolá `$transformer` na všechny prvky v poli a vrátí pole vrácených hodnot. Callback má signaturu `function ($value, $key, array $array): bool`. ```php $array = ['foo', 'bar', 'baz']; @@ -325,10 +383,10 @@ $position = Arrays::getKeyOffset($array, 'not-exists'); // vrátí null ``` -some(iterable $array, callable $callback): bool .[method] ---------------------------------------------------------- +some(array $array, callable $predicate): bool .[method] +------------------------------------------------------- -Testuje, zda alespoň jeden prvek v poli projde testem implementovaným v `$callback` se signaturou `function ($value, $key, array $array): bool`. +Testuje, zda alespoň jeden prvek v poli projde testem implementovaným v `$predicate` se signaturou `function ($value, $key, array $array): bool`. ```php $array = [1, 2, 3, 4]; diff --git a/utils/cs/images.texy b/utils/cs/images.texy index 1ae07eb9b7..213eb24804 100644 --- a/utils/cs/images.texy +++ b/utils/cs/images.texy @@ -300,6 +300,11 @@ static isTypeSupported(int $type): bool .[method] Zjišťuje, zda je podporovaný daný [typ|#Formáty] obrázku. +static getSupportedTypes(): array .[method]{data-version:4.0.4} +--------------------------------------------------------------- +Vrací pole podporovaných [typů|#Formáty] obrázku. + + static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method] ------------------------------------------------------------------------------------------------------------------------ Spočítá rozměry obdélníku, který obepne text v určitém písmu a velikosti. Vrací asociativní pole obsahující klíče `left`, `top`, `width`, `height`. Levý okraj může být i záporný, pokud text začíná levým podřezáváním. diff --git a/utils/cs/iterables.texy b/utils/cs/iterables.texy new file mode 100644 index 0000000000..9d1b474457 --- /dev/null +++ b/utils/cs/iterables.texy @@ -0,0 +1,119 @@ +Práce s iterátory +***************** + +.[perex]{data-version:4.0.4} +[api:Nette\Utils\Iterables] je statická třída s funkcemi pro práci s iterátory. Její obdobou pro pole je [Nette\Utils\Arrays|arrays]. + + +Instalace: + +```shell +composer require nette/utils +``` + +Všechny příklady předpokládají vytvořený alias: + +```php +use Nette\Utils\Iterables; +``` + + +contains(iterable $iterable, $value): bool .[method] +---------------------------------------------------- + +Testuje přítomnost hodnoty v iterátoru. Používá striktní porovnání (`===`). + +```php +Iterables::contains(new ArrayIterator([1, 2, 3]), 1); // true +Iterables::contains(new ArrayIterator([1, 2, 3]), '1'); // false +``` + + +containsKey(iterable $iterable, $value): bool .[method] +------------------------------------------------------- + +Testuje přítomnost klíče v iterátoru. Používá striktní porovnání (`===`). + +```php +Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0); // true +Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4); // false +``` + + +every(iterable $iterable, callable $predicate): bool .[method] +-------------------------------------------------------------- + +Testuje, zda všechny prvky iterátoru projdou testem implementovaným v `$predicate` se signaturou `function ($value, $key, iterable $iterable): bool`. + +```php +$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]); +$isBelowThreshold = fn($value) => $value < 40; +$res = Iterables::every($iterator, $isBelowThreshold); // true +``` + +Viz [#some()]. + + +filter(iterable $iterable, callable $predicate): Generator .[method] +-------------------------------------------------------------------- + +Iterátor, který filtruje prvky dle predikátu. Ten má signaturu `function ($value, $key, iterable $iterable): bool`. Zachovává původní klíče. + +```php +$iterator = new ArrayIterator([1, 2, 3]); +$iterator = Iterables::filter($iterator, fn($v) => $v < 3); +// 1, 2 +``` + + +first(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------------- + +Vrátí první položku (odpovídající predikátu, je-li zadán). Pokud taková položka neexistuje, vrátí výsledek volání `$else` nebo null. +Parametr `$predicate` má signaturu `function ($value, $key, iterable $iterable): bool`. + +```php +Iterables::first(new ArrayIterator([1, 2, 3])); // 1 +Iterables::first(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 3 +Iterables::first(new ArrayIterator([])); // null +Iterables::first(new ArrayIterator([]), else: fn() => false); // false +``` + + +firstKey(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method] +---------------------------------------------------------------------------------------------- + +Vrátí klíč první položky (odpovídající predikátu, je-li zadán). Pokud taková položka neexistuje, vrátí výsledek volání `$else` nebo null. Predikát má signaturu `function ($value, $key, iterable $iterable): bool`. + +```php +Iterables::firstKey(new ArrayIterator([1, 2, 3])); // 0 +Iterables::firstKey(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 2 +Iterables::firstKey(new ArrayIterator(['a' => 1, 'b' => 2])); // 'a' +Iterables::firstKey(new ArrayIterator([])); // null +``` + + +map(iterable $iterable, callable $transformer): array .[method] +--------------------------------------------------------------- + +Iterátor, který transformuje hodnoty voláním `$transformer`. Ten má signaturu `function ($value, $key, iterable $iterable): bool`. Zachovává původní klíče. + +```php +$iterator = new ArrayIterator([1, 2, 3]); +$iterator = Iterables::map($iterator, fn($v) => $v * 2); +// 2, 4, 6 +``` + + +some(iterable $iterable, callable $predicate): bool .[method] +------------------------------------------------------------- + +Testuje, zda alespoň jeden prvek iterátoru projde testem implementovaným v `$predicate` se signaturou `function ($value, $key, iterable $iterable): bool`. + +```php +$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]); +$isEven = fn($value) => $value % 2 === 0; +$res = Iterables::some($iterator, $isEven); // true +``` + +Viz [#every()]. diff --git a/utils/de/@home.texy b/utils/de/@home.texy index dd67234580..16b27abe0b 100644 --- a/utils/de/@home.texy +++ b/utils/de/@home.texy @@ -13,6 +13,7 @@ Im Paket `nette/utils` finden Sie eine Reihe von nützlichen Klassen für den t | [Generieren von HTML-Code |html-elements] | Nette\Utils\Html | [Helferfunktionen |helpers] | Nette\Utils\Helfer | [JSON] | Nette\Utils\Json +| [Iterables |iterables] | Nette\Utils\Iterables | [Paginator] | Nette\Utils\Paginator | [PHP-Reflexion |reflection] | Nette\Utils\Reflexion | [Rückruf |Callback] | Nette\Utils\Callback diff --git a/utils/de/@left-menu.texy b/utils/de/@left-menu.texy index 5ca87cc2c6..e94adaa3c3 100644 --- a/utils/de/@left-menu.texy +++ b/utils/de/@left-menu.texy @@ -8,6 +8,7 @@ Paket nette/utils - [Finder] - [Floats] - [Hilfsfunktionen |helpers] +- [Iterabilien |iterables] - [HTML-Elemente |HTML Elements] - [JSON] - [Paginator |paginator] diff --git a/utils/de/arrays.texy b/utils/de/arrays.texy index cd3ec38478..73f7372c02 100644 --- a/utils/de/arrays.texy +++ b/utils/de/arrays.texy @@ -15,7 +15,7 @@ composer require nette/utils Arrays .[#toc-arrays] ===================== -[api:Nette\Utils\Arrays] ist eine statische Klasse, die eine Handvoll praktischer Array-Funktionen enthält. +[api:Nette\Utils\Arrays] ist eine statische Klasse, die eine Handvoll praktischer Array-Funktionen enthält. Ihre Entsprechung für Iteratoren ist [Nette\Utils\Iterables |iterables]. Die folgenden Beispiele setzen voraus, dass der folgende Klassenalias definiert ist: @@ -76,8 +76,8 @@ Arrays::contains(['1', false], 1); // false ``` -every(iterable $array, callable $callback): bool .[method] ----------------------------------------------------------- +every(array $array, callable $predicate): bool .[method] +-------------------------------------------------------- Prüft, ob alle Elemente im Array den Test bestehen, der von der angegebenen Funktion mit der Signatur `function ($value, $key, array $array): bool` implementiert wird. @@ -90,16 +90,52 @@ $res = Arrays::every($array, $isBelowThreshold); // true Siehe [some() |#some()]. -first(array $array): mixed .[method] ------------------------------------- +filter(array $array, callable $predicate): array .[method]{data-version:4.0.4} +------------------------------------------------------------------------------ + +Gibt ein neues Array zurück, das alle Schlüssel-Wert-Paare enthält, die mit dem angegebenen `$predicate` übereinstimmen. Der Callback hat die Signatur `function ($value, int|string $key, array $array): bool`. + +```php +Arrays::filter( + ['a' => 1, 'b' => 2, 'c' => 3], + fn($v) => $v < 3, +); +// ['a' => 1, 'b' => 2] +``` + + +first(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------- + +Gibt das erste Element zurück (das dem angegebenen Prädikat entspricht, falls angegeben). Wenn es kein solches Element gibt, wird das Ergebnis des Aufrufs von `$else` oder null zurückgegeben. + `$predicate` hat die Signatur `function ($value, int|string $key, array $array): bool`. + +Im Gegensatz zu `reset()` wird der interne Zeiger nicht verändert. Die Parameter `$predicate` und `$else` gibt es seit Version 4.0.4. + +```php +Arrays::first([1, 2, 3]); // 1 +Arrays::first([1, 2, 3], fn($v) => $v > 2); // 3 +Arrays::first([]); // null +Arrays::first([], else: fn() => false); // false +``` -Gibt das erste Element aus dem Array zurück oder null, wenn Array leer ist. Im Gegensatz zu `reset()` wird der interne Zeiger nicht verändert. +Siehe [last() |#last()]. + + +firstKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4} +------------------------------------------------------------------------------------------------ + +Gibt den Schlüssel des ersten Elements zurück (das mit dem angegebenen Prädikat übereinstimmt, falls gegeben) oder null, wenn es kein solches Element gibt. `$predicate` hat die Signatur `function ($value, int|string $key, array $array): bool`. ```php -Arrays::first([1, 2, 3]); // 1 -Arrays::first([]); // null +Arrays::firstKey([1, 2, 3]); // 0 +Arrays::firstKey([1, 2, 3], fn($v) => $v > 2); // 2 +Arrays::firstKey(['a' => 1, 'b' => 2]); // 'a' +Arrays::firstKey([]); // null ``` +Siehe [lastKey() |#lastKey()]. + flatten(array $array, bool $preserveKeys=false): array .[method] ---------------------------------------------------------------- @@ -229,21 +265,43 @@ Arrays::isList(['a' => 1, 'b' => 2]); // false ``` -last(array $array): mixed .[method] ------------------------------------ +last(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------ + +Gibt das letzte Element zurück (das dem angegebenen Prädikat entspricht, falls angegeben). Wenn es kein solches Element gibt, wird das Ergebnis des Aufrufs von `$else` oder null zurückgegeben. + `$predicate` hat die Signatur `function ($value, int|string $key, array $array): bool`. + +Im Gegensatz zu `end()` wird der interne Zeiger nicht verändert. Die Parameter `$predicate` und `$else` gibt es seit Version 4.0.4. + +```php +Arrays::last([1, 2, 3]); // 3 +Arrays::last([1, 2, 3], fn($v) => $v < 3); // 2 +Arrays::last([]); // null +Arrays::last([], else: fn() => false); // false +``` + +Siehe [first() |#first()]. + -Gibt das letzte Element des Arrays zurück oder null, wenn das Array leer ist. Im Gegensatz zu `end()` wird der interne Zeiger nicht verändert. +lastKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4} +----------------------------------------------------------------------------------------------- + +Gibt den Schlüssel des letzten Elements zurück (das mit dem angegebenen Prädikat übereinstimmt, falls angegeben) oder null, wenn es kein solches Element gibt. `$predicate` hat die Signatur `function ($value, int|string $key, array $array): bool`. ```php -Arrays::last([1, 2, 3]); // 3 -Arrays::last([]); // null +Arrays::lastKey([1, 2, 3]); // 2 +Arrays::lastKey([1, 2, 3], fn($v) => $v < 3); // 1 +Arrays::lastKey(['a' => 1, 'b' => 2]); // 'b' +Arrays::lastKey([]); // null ``` +Siehe [firstKey() |#firstKey()]. + -map(iterable $array, callable $callback): array .[method] +map(array $array, callable $transformer): array .[method] --------------------------------------------------------- -Ruft `$callback` für alle Elemente im Array auf und gibt das Array der Rückgabewerte zurück. Der Callback hat die Signatur `function ($value, $key, array $array): bool`. +Ruft `$transformer` für alle Elemente im Array auf und gibt das Array der Rückgabewerte zurück. Der Callback hat die Signatur `function ($value, $key, array $array): bool`. ```php $array = ['foo', 'bar', 'baz']; @@ -325,8 +383,8 @@ $position = Arrays::getKeyOffset($array, 'not-exists'); // returns null ``` -some(iterable $array, callable $callback): bool .[method] ---------------------------------------------------------- +some(array $array, callable $predicate): bool .[method] +------------------------------------------------------- Prüft, ob mindestens ein Element im Array den Test besteht, der durch den angegebenen Callback mit der Signatur `function ($value, $key, array $array): bool` implementiert wird. diff --git a/utils/de/images.texy b/utils/de/images.texy index 5aef1e8eb2..861dda114b 100644 --- a/utils/de/images.texy +++ b/utils/de/images.texy @@ -300,6 +300,11 @@ static isTypeSupported(int $type): bool .[method] Ermittelt, ob der angegebene [Bildtyp |#Formats] unterstützt wird. +static getSupportedTypes(): array .[method]{data-version:4.0.4} +--------------------------------------------------------------- +Gibt ein Array der unterstützten Bildtypen zurück (Konstanten `ImageType::XXX`). + + static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method] ------------------------------------------------------------------------------------------------------------------------ Berechnet die Abmessungen des Rechtecks, das den Text in einer bestimmten Schriftart und -größe umschließt. Sie gibt ein assoziatives Array zurück, das die Schlüssel `left`, `top`, `width`, `height` enthält. Der linke Rand kann negativ sein, wenn der Text mit einem linken Überhang beginnt. diff --git a/utils/de/iterables.texy b/utils/de/iterables.texy new file mode 100644 index 0000000000..cf64305f41 --- /dev/null +++ b/utils/de/iterables.texy @@ -0,0 +1,119 @@ +Iterator-Funktionen +******************* + +.[perex]{data-version:4.0.4} +[api:Nette\Utils\Iterables] ist eine statische Klasse mit Funktionen für die Arbeit mit Iteratoren. Ihr Gegenstück für Arrays ist [Nette\Utils\Arrays |arrays]. + + +Installation: + +```shell +composer require nette/utils +``` + +Alle Beispiele gehen von der Erstellung eines Alias aus: + +```php +use Nette\Utils\Iterables; +``` + + +contains(iterable $iterable, $value): bool .[method] +---------------------------------------------------- + +Prüft auf das Vorhandensein eines Wertes im Iterator. Er verwendet einen strengen Vergleich (`===`). + +```php +Iterables::contains(new ArrayIterator([1, 2, 3]), 1); // true +Iterables::contains(new ArrayIterator([1, 2, 3]), '1'); // false +``` + + +containsKey(iterable $iterable, $value): bool .[method] +------------------------------------------------------- + +Prüft auf das Vorhandensein eines Schlüssels im Iterator. Er verwendet einen strengen Vergleich (`===`). + +```php +Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0); // true +Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4); // false +``` + + +every(iterable $iterable, callable $predicate): bool .[method] +-------------------------------------------------------------- + +Prüft, ob alle Elemente des Iterators einen in `$predicate` implementierten Test mit der Signatur `function ($value, $key, iterable $iterable): bool` bestehen. + +```php +$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]); +$isBelowThreshold = fn($value) => $value < 40; +$res = Iterables::every($iterator, $isBelowThreshold); // true +``` + +Siehe [some() |#some()]. + + +filter(iterable $iterable, callable $predicate): Generator .[method] +-------------------------------------------------------------------- + +Iterator, der Elemente nach einem Prädikat filtert. Das Prädikat hat die Signatur `function ($value, $key, iterable $iterable): bool`. Behält die ursprünglichen Schlüssel bei. + +```php +$iterator = new ArrayIterator([1, 2, 3]); +$iterator = Iterables::filter($iterator, fn($v) => $v < 3); +// 1, 2 +``` + + +first(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------------- + +Gibt das erste Element zurück (das dem Prädikat entspricht, falls angegeben). Ist kein solches Element vorhanden, wird das Ergebnis des Aufrufs `$else` oder null zurückgegeben. +Der Parameter `$predicate` hat die Signatur `function ($value, $key, iterable $iterable): bool`. + +```php +Iterables::first(new ArrayIterator([1, 2, 3])); // 1 +Iterables::first(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 3 +Iterables::first(new ArrayIterator([])); // null +Iterables::first(new ArrayIterator([]), else: fn() => false); // false +``` + + +firstKey(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method] +---------------------------------------------------------------------------------------------- + +Gibt den Schlüssel des ersten Elements zurück (das dem Prädikat entspricht, falls angegeben). Ist kein solches Element vorhanden, wird das Ergebnis des Aufrufs `$else` oder null zurückgegeben. Das Prädikat hat die Signatur `function ($value, $key, iterable $iterable): bool`. + +```php +Iterables::firstKey(new ArrayIterator([1, 2, 3])); // 0 +Iterables::firstKey(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 2 +Iterables::firstKey(new ArrayIterator(['a' => 1, 'b' => 2])); // 'a' +Iterables::firstKey(new ArrayIterator([])); // null +``` + + +map(iterable $iterable, callable $transformer): array .[method] +--------------------------------------------------------------- + +Iterator, der Werte durch den Aufruf von `$transformer` umwandelt. Er hat die Signatur `function ($value, $key, iterable $iterable): bool`. Behält die ursprünglichen Schlüssel bei. + +```php +$iterator = new ArrayIterator([1, 2, 3]); +$iterator = Iterables::map($iterator, fn($v) => $v * 2); +// 2, 4, 6 +``` + + +some(iterable $iterable, callable $predicate): bool .[method] +------------------------------------------------------------- + +Prüft, ob mindestens ein Element des Iterators einen in `$predicate` implementierten Test mit der Signatur `function ($value, $key, iterable $iterable): bool` besteht. + +```php +$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]); +$isEven = fn($value) => $value % 2 === 0; +$res = Iterables::some($iterator, $isEven); // true +``` + +Siehe [every() |#every()]. diff --git a/utils/el/@home.texy b/utils/el/@home.texy index d9739dc497..a0678fe23b 100644 --- a/utils/el/@home.texy +++ b/utils/el/@home.texy @@ -13,6 +13,7 @@ | [Helpers |helpers] | Nette\Utils\Helpers | [Στοιχεία HTML |HTML Elements] | Nette\Utils\Html | [Images |Images] | Nette\Utils\Image +| [Iterables |iterables] | Nette\Utils\Iterables | [JSON |JSON] | Nette\Utils\Json | [Paginator |paginator] | Nette\Utils\Paginator | [PHP Reflection |reflection] | Nette\Utils\Reflection diff --git a/utils/el/@left-menu.texy b/utils/el/@left-menu.texy index 6ef2e7ba0b..1f5380b7a1 100644 --- a/utils/el/@left-menu.texy +++ b/utils/el/@left-menu.texy @@ -8,6 +8,7 @@ - [Βοηθοί |helpers] - [Στοιχεία HTML |HTML Elements] - [Εικόνες |Images] +- [Iterables |iterables] - [JSON |JSON] - [Σελιδοποιητής |paginator] - [Τυχαίες συμβολοσειρές |random] diff --git a/utils/el/arrays.texy b/utils/el/arrays.texy index 6bb271d5e7..42a4978c65 100644 --- a/utils/el/arrays.texy +++ b/utils/el/arrays.texy @@ -15,7 +15,7 @@ composer require nette/utils Arrays .[#toc-arrays] ===================== -[api:Nette\Utils\Arrays] είναι μια στατική κλάση, η οποία περιέχει μια χούφτα από εύχρηστες συναρτήσεις συστοιχιών. +[api:Nette\Utils\Arrays] είναι μια στατική κλάση, η οποία περιέχει μια χούφτα από εύχρηστες συναρτήσεις πίνακα. Το ισοδύναμό της για τους επαναλήπτες είναι η [Nette\Utils\Iterables |iterables]. Τα παραδείγματα που ακολουθούν υποθέτουν ότι έχει οριστεί το ακόλουθο ψευδώνυμο της κλάσης: @@ -76,8 +76,8 @@ Arrays::contains(['1', false], 1); // false ``` -every(iterable $array, callable $callback): bool .[method] ----------------------------------------------------------- +every(array $array, callable $predicate): bool .[method] +-------------------------------------------------------- Ελέγχει αν όλα τα στοιχεία του πίνακα περνούν τον έλεγχο που υλοποιείται από την παρεχόμενη συνάρτηση, η οποία έχει την υπογραφή `function ($value, $key, array $array): bool`. @@ -90,16 +90,52 @@ $res = Arrays::every($array, $isBelowThreshold); // true Βλέπε [some() |#some()]. -first(array $array): mixed .[method] ------------------------------------- +filter(array $array, callable $predicate): array .[method]{data-version:4.0.4} +------------------------------------------------------------------------------ + +Επιστρέφει έναν νέο πίνακα που περιέχει όλα τα ζεύγη κλειδιών-τιμών που ταιριάζουν με το δεδομένο `$predicate`. Το callback έχει την υπογραφή `function ($value, int|string $key, array $array): bool`. + +```php +Arrays::filter( + ['a' => 1, 'b' => 2, 'c' => 3], + fn($v) => $v < 3, +); +// ['a' => 1, 'b' => 2] +``` + + +first(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------- + +Επιστρέφει το πρώτο στοιχείο (που ταιριάζει με το καθορισμένο κατηγόρημα, αν δίνεται). Εάν δεν υπάρχει τέτοιο στοιχείο, επιστρέφει το αποτέλεσμα της κλήσης του `$else` ή null. +Το `$predicate` έχει την υπογραφή `function ($value, int|string $key, array $array): bool`. + +Δεν αλλάζει τον εσωτερικό δείκτη σε αντίθεση με το `reset()`. Οι παράμετροι `$predicate` και `$else` υπάρχουν από την έκδοση 4.0.4. + +```php +Arrays::first([1, 2, 3]); // 1 +Arrays::first([1, 2, 3], fn($v) => $v > 2); // 3 +Arrays::first([]); // null +Arrays::first([], else: fn() => false); // false +``` -Επιστρέφει το πρώτο στοιχείο από τον πίνακα ή null αν ο πίνακας είναι άδειος. Δεν αλλάζει τον εσωτερικό δείκτη σε αντίθεση με το `reset()`. +Βλέπε [last() |#last()]. + + +firstKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4} +------------------------------------------------------------------------------------------------ + +Επιστρέφει το κλειδί του πρώτου στοιχείου (που ταιριάζει με το καθορισμένο κατηγόρημα, αν δίνεται) ή null αν δεν υπάρχει τέτοιο στοιχείο. Το `$predicate` έχει την υπογραφή `function ($value, int|string $key, array $array): bool`. ```php -Arrays::first([1, 2, 3]); // 1 -Arrays::first([]); // null +Arrays::firstKey([1, 2, 3]); // 0 +Arrays::firstKey([1, 2, 3], fn($v) => $v > 2); // 2 +Arrays::firstKey(['a' => 1, 'b' => 2]); // 'a' +Arrays::firstKey([]); // null ``` +Βλέπε [lastKey() |#lastKey()]. + flatten(array $array, bool $preserveKeys=false): array .[method] ---------------------------------------------------------------- @@ -229,21 +265,43 @@ Arrays::isList(['a' => 1, 'b' => 2]); // false ``` -last(array $array): mixed .[method] ------------------------------------ +last(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------ + +Επιστρέφει το τελευταίο στοιχείο (που ταιριάζει με το καθορισμένο κατηγόρημα, αν δίνεται). Εάν δεν υπάρχει τέτοιο στοιχείο, επιστρέφει το αποτέλεσμα της κλήσης του `$else` ή null. +Το `$predicate` έχει την υπογραφή `function ($value, int|string $key, array $array): bool`. + +Δεν αλλάζει τον εσωτερικό δείκτη σε αντίθεση με το `end()`. Οι παράμετροι `$predicate` και `$else` υπάρχουν από την έκδοση 4.0.4. + +```php +Arrays::last([1, 2, 3]); // 3 +Arrays::last([1, 2, 3], fn($v) => $v < 3); // 2 +Arrays::last([]); // null +Arrays::last([], else: fn() => false); // false +``` + +Βλέπε [first() |#first()]. + -Επιστρέφει το τελευταίο στοιχείο από τον πίνακα ή null αν ο πίνακας είναι άδειος. Δεν αλλάζει τον εσωτερικό δείκτη σε αντίθεση με το `end()`. +lastKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4} +----------------------------------------------------------------------------------------------- + +Επιστρέφει το κλειδί του τελευταίου στοιχείου (που ταιριάζει με το καθορισμένο κατηγόρημα, αν δίνεται) ή null αν δεν υπάρχει τέτοιο στοιχείο. Το `$predicate` έχει την υπογραφή `function ($value, int|string $key, array $array): bool`. ```php -Arrays::last([1, 2, 3]); // 3 -Arrays::last([]); // null +Arrays::lastKey([1, 2, 3]); // 2 +Arrays::lastKey([1, 2, 3], fn($v) => $v < 3); // 1 +Arrays::lastKey(['a' => 1, 'b' => 2]); // 'b' +Arrays::lastKey([]); // null ``` +Βλέπε [firstKey() |#firstKey()]. + -map(iterable $array, callable $callback): array .[method] +map(array $array, callable $transformer): array .[method] --------------------------------------------------------- -Καλεί το `$callback` σε όλα τα στοιχεία του πίνακα και επιστρέφει τον πίνακα των τιμών επιστροφής. Η ανάκληση έχει την υπογραφή `function ($value, $key, array $array): bool`. +Καλεί το `$transformer` σε όλα τα στοιχεία του πίνακα και επιστρέφει τον πίνακα των τιμών επιστροφής. Η ανάκληση έχει την υπογραφή `function ($value, $key, array $array): bool`. ```php $array = ['foo', 'bar', 'baz']; @@ -325,8 +383,8 @@ $position = Arrays::getKeyOffset($array, 'not-exists'); // επιστρέφει ``` -some(iterable $array, callable $callback): bool .[method] ---------------------------------------------------------- +some(array $array, callable $predicate): bool .[method] +------------------------------------------------------- Ελέγχει αν τουλάχιστον ένα στοιχείο του πίνακα περνάει το τεστ που υλοποιείται από την παρεχόμενη κλήση με υπογραφή `function ($value, $key, array $array): bool`. diff --git a/utils/el/images.texy b/utils/el/images.texy index 6260f68f37..c90e750c2d 100644 --- a/utils/el/images.texy +++ b/utils/el/images.texy @@ -300,6 +300,11 @@ static isTypeSupported(int $type): bool .[method] Καθορίζει αν υποστηρίζεται ο συγκεκριμένος [τύπος |#Formats] εικόνας. +static getSupportedTypes(): array .[method]{data-version:4.0.4} +--------------------------------------------------------------- +Επιστρέφει έναν πίνακα υποστηριζόμενων τύπων εικόνας (σταθερές `ImageType::XXX`). + + static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method] ------------------------------------------------------------------------------------------------------------------------ Υπολογίζει τις διαστάσεις του ορθογωνίου που περικλείει το κείμενο σε καθορισμένη γραμματοσειρά και μέγεθος. Επιστρέφει έναν συσχετιστικό πίνακα που περιέχει τα κλειδιά `left`, `top`, `width`, `height`. Το αριστερό περιθώριο μπορεί να είναι αρνητικό εάν το κείμενο ξεκινά με αριστερή προεξοχή. diff --git a/utils/el/iterables.texy b/utils/el/iterables.texy new file mode 100644 index 0000000000..18b7eca582 --- /dev/null +++ b/utils/el/iterables.texy @@ -0,0 +1,119 @@ +Λειτουργίες επαναλήπτη +********************** + +.[perex]{data-version:4.0.4} +[api:Nette\Utils\Iterables] είναι μια στατική κλάση με συναρτήσεις για την εργασία με επαναλήπτες. Η αντίστοιχη κλάση για πίνακες είναι η [Nette\Utils\Arrays |arrays]. + + +Εγκατάσταση: + +```shell +composer require nette/utils +``` + +Όλα τα παραδείγματα προϋποθέτουν τη δημιουργία ενός ψευδώνυμου: + +```php +use Nette\Utils\Iterables; +``` + + +contains(iterable $iterable, $value): bool .[method] +---------------------------------------------------- + +Ελέγχει την παρουσία μιας τιμής στον επαναλήπτη. Χρησιμοποιεί αυστηρή σύγκριση (`===`). + +```php +Iterables::contains(new ArrayIterator([1, 2, 3]), 1); // true +Iterables::contains(new ArrayIterator([1, 2, 3]), '1'); // false +``` + + +containsKey(iterable $iterable, $value): bool .[method] +------------------------------------------------------- + +Ελέγχει την παρουσία ενός κλειδιού στον επαναλήπτη. Χρησιμοποιεί αυστηρή σύγκριση (`===`). + +```php +Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0); // true +Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4); // false +``` + + +every(iterable $iterable, callable $predicate): bool .[method] +-------------------------------------------------------------- + +Ελέγχει αν όλα τα στοιχεία του επαναλήπτη περνούν ένα τεστ που υλοποιείται στο `$predicate` με την υπογραφή `function ($value, $key, iterable $iterable): bool`. + +```php +$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]); +$isBelowThreshold = fn($value) => $value < 40; +$res = Iterables::every($iterator, $isBelowThreshold); // true +``` + +Βλέπε [some() |#some()]. + + +filter(iterable $iterable, callable $predicate): Generator .[method] +-------------------------------------------------------------------- + +Επαναλήπτης που φιλτράρει τα στοιχεία σύμφωνα με ένα κατηγόρημα. Το κατηγόρημα έχει την υπογραφή `function ($value, $key, iterable $iterable): bool`. Διατηρεί τα αρχικά κλειδιά. + +```php +$iterator = new ArrayIterator([1, 2, 3]); +$iterator = Iterables::filter($iterator, fn($v) => $v < 3); +// 1, 2 +``` + + +first(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------------- + +Επιστρέφει το πρώτο στοιχείο (που ταιριάζει με το κατηγόρημα, αν έχει καθοριστεί). Εάν δεν υπάρχει τέτοιο στοιχείο, επιστρέφει το αποτέλεσμα της κλήσης του `$else` ή null. +Η παράμετρος `$predicate` έχει την υπογραφή `function ($value, $key, iterable $iterable): bool`. + +```php +Iterables::first(new ArrayIterator([1, 2, 3])); // 1 +Iterables::first(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 3 +Iterables::first(new ArrayIterator([])); // null +Iterables::first(new ArrayIterator([]), else: fn() => false); // false +``` + + +firstKey(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method] +---------------------------------------------------------------------------------------------- + +Επιστρέφει το κλειδί του πρώτου στοιχείου (που ταιριάζει με το κατηγόρημα, αν έχει καθοριστεί). Εάν δεν υπάρχει τέτοιο στοιχείο, επιστρέφει το αποτέλεσμα της κλήσης του `$else` ή null. Το κατηγόρημα έχει την υπογραφή `function ($value, $key, iterable $iterable): bool`. + +```php +Iterables::firstKey(new ArrayIterator([1, 2, 3])); // 0 +Iterables::firstKey(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 2 +Iterables::firstKey(new ArrayIterator(['a' => 1, 'b' => 2])); // 'a' +Iterables::firstKey(new ArrayIterator([])); // null +``` + + +map(iterable $iterable, callable $transformer): array .[method] +--------------------------------------------------------------- + +Επαναλήπτης που μετασχηματίζει τις τιμές καλώντας το `$transformer`. Έχει την υπογραφή `function ($value, $key, iterable $iterable): bool`. Διατηρεί τα αρχικά κλειδιά. + +```php +$iterator = new ArrayIterator([1, 2, 3]); +$iterator = Iterables::map($iterator, fn($v) => $v * 2); +// 2, 4, 6 +``` + + +some(iterable $iterable, callable $predicate): bool .[method] +------------------------------------------------------------- + +Ελέγχει αν τουλάχιστον ένα στοιχείο του επαναλήπτη περνάει ένα τεστ που υλοποιείται στο `$predicate` με την υπογραφή `function ($value, $key, iterable $iterable): bool`. + +```php +$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]); +$isEven = fn($value) => $value % 2 === 0; +$res = Iterables::some($iterator, $isEven); // true +``` + +Βλέπε [every() |#every()]. diff --git a/utils/en/@home.texy b/utils/en/@home.texy index 470030790b..a46e587848 100644 --- a/utils/en/@home.texy +++ b/utils/en/@home.texy @@ -13,6 +13,7 @@ In package `nette/utils` you will find a set of useful classes for everyday use: | [Helpers |helpers] | Nette\Utils\Helpers | [HTML Elements] | Nette\Utils\Html | [Images] | Nette\Utils\Image +| [Iterables] | Nette\Utils\Iterables | [JSON] | Nette\Utils\Json | [Paginator |paginator] | Nette\Utils\Paginator | [PHP Reflection |reflection] | Nette\Utils\Reflection diff --git a/utils/en/@left-menu.texy b/utils/en/@left-menu.texy index fc5b708ef1..8a94eff2d9 100644 --- a/utils/en/@left-menu.texy +++ b/utils/en/@left-menu.texy @@ -8,6 +8,7 @@ Package nette/utils - [Helpers |helpers] - [HTML Elements] - [Images] +- [Iterables] - [JSON] - [Paginator |paginator] - [Random Strings |random] diff --git a/utils/en/arrays.texy b/utils/en/arrays.texy index d55ef13abb..a529286644 100644 --- a/utils/en/arrays.texy +++ b/utils/en/arrays.texy @@ -15,7 +15,7 @@ composer require nette/utils Arrays ====== -[api:Nette\Utils\Arrays] is a static class, which contains a handful of handy array functions. +[api:Nette\Utils\Arrays] is a static class, which contains a handful of handy array functions. Its equivalent for iterators is [Nette\Utils\Iterables|iterables]. Following examples assume the following class alias is defined: @@ -76,8 +76,8 @@ Arrays::contains(['1', false], 1); // false ``` -every(iterable $array, callable $callback): bool .[method] ----------------------------------------------------------- +every(array $array, callable $predicate): bool .[method] +-------------------------------------------------------- Tests whether all elements in the array pass the test implemented by the provided function, which has the signature `function ($value, $key, array $array): bool`. @@ -90,16 +90,52 @@ $res = Arrays::every($array, $isBelowThreshold); // true See [#some()]. -first(array $array): mixed .[method] ------------------------------------- +filter(array $array, callable $predicate): array .[method]{data-version:4.0.4} +------------------------------------------------------------------------------ + +Returns a new array containing all key-value pairs matching the given `$predicate`. The callback has the signature `function ($value, int|string $key, array $array): bool`. + +```php +Arrays::filter( + ['a' => 1, 'b' => 2, 'c' => 3], + fn($v) => $v < 3, +); +// ['a' => 1, 'b' => 2] +``` + + +first(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------- + +Returns the first item (matching the specified predicate if given). If there is no such item, it returns result of invoking `$else` or null. +The `$predicate` has the signature `function ($value, int|string $key, array $array): bool`. + +It does not change the internal pointer unlike `reset()`. The `$predicate` and `$else` parameters exist since version 4.0.4. + +```php +Arrays::first([1, 2, 3]); // 1 +Arrays::first([1, 2, 3], fn($v) => $v > 2); // 3 +Arrays::first([]); // null +Arrays::first([], else: fn() => false); // false +``` -Returns the first item from the array or null if array is empty. It does not change the internal pointer unlike `reset()`. +See [#last()]. + + +firstKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4} +------------------------------------------------------------------------------------------------ + +Returns the key of first item (matching the specified predicate if given) or null if there is no such item. The `$predicate` has the signature `function ($value, int|string $key, array $array): bool`. ```php -Arrays::first([1, 2, 3]); // 1 -Arrays::first([]); // null +Arrays::firstKey([1, 2, 3]); // 0 +Arrays::firstKey([1, 2, 3], fn($v) => $v > 2); // 2 +Arrays::firstKey(['a' => 1, 'b' => 2]); // 'a' +Arrays::firstKey([]); // null ``` +See [#lastKey()]. + flatten(array $array, bool $preserveKeys=false): array .[method] ---------------------------------------------------------------- @@ -229,21 +265,43 @@ Arrays::isList(['a' => 1, 'b' => 2]); // false ``` -last(array $array): mixed .[method] ------------------------------------ +last(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------ + +Returns the last item (matching the specified predicate if given). If there is no such item, it returns result of invoking `$else` or null. +The `$predicate` has the signature `function ($value, int|string $key, array $array): bool`. + +It does not change the internal pointer unlike `end()`. The `$predicate` and `$else` parameters exist since version 4.0.4. + +```php +Arrays::last([1, 2, 3]); // 3 +Arrays::last([1, 2, 3], fn($v) => $v < 3); // 2 +Arrays::last([]); // null +Arrays::last([], else: fn() => false); // false +``` + +See [#first()]. + -Returns the last item from the array or null if array is empty. It does not change the internal pointer unlike `end()`. +lastKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4} +----------------------------------------------------------------------------------------------- + +Returns the key of last item (matching the specified predicate if given) or null if there is no such item. The `$predicate` has the signature `function ($value, int|string $key, array $array): bool`. ```php -Arrays::last([1, 2, 3]); // 3 -Arrays::last([]); // null +Arrays::lastKey([1, 2, 3]); // 2 +Arrays::lastKey([1, 2, 3], fn($v) => $v < 3); // 1 +Arrays::lastKey(['a' => 1, 'b' => 2]); // 'b' +Arrays::lastKey([]); // null ``` +See [#firstKey()]. + -map(iterable $array, callable $callback): array .[method] +map(array $array, callable $transformer): array .[method] --------------------------------------------------------- -Calls `$callback` on all elements in the array and returns the array of return values. The callback has the signature `function ($value, $key, array $array): bool`. +Calls `$transformer` on all elements in the array and returns the array of return values. The callback has the signature `function ($value, $key, array $array): bool`. ```php $array = ['foo', 'bar', 'baz']; @@ -325,8 +383,8 @@ $position = Arrays::getKeyOffset($array, 'not-exists'); // returns null ``` -some(iterable $array, callable $callback): bool .[method] ---------------------------------------------------------- +some(array $array, callable $predicate): bool .[method] +------------------------------------------------------- Tests whether at least one element in the array passes the test implemented by the provided callback with signature `function ($value, $key, array $array): bool`. diff --git a/utils/en/images.texy b/utils/en/images.texy index 214cd3daae..e6ef329deb 100644 --- a/utils/en/images.texy +++ b/utils/en/images.texy @@ -300,6 +300,11 @@ static isTypeSupported(int $type): bool .[method] Determines if the given image [type|#Formats] is supported. +static getSupportedTypes(): array .[method]{data-version:4.0.4} +--------------------------------------------------------------- +Returns an array of supported image [types|#Formats]. + + static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method] ------------------------------------------------------------------------------------------------------------------------ Calculates the dimensions of the rectangle that encloses the text in a specified font and size. It returns an associative array containing the keys `left`, `top`, `width`, `height`. The left margin can be negative if the text starts with a left overhang. diff --git a/utils/en/iterables.texy b/utils/en/iterables.texy new file mode 100644 index 0000000000..b348fdf336 --- /dev/null +++ b/utils/en/iterables.texy @@ -0,0 +1,119 @@ +Iterator Functions +****************** + +.[perex]{data-version:4.0.4} +[api:Nette\Utils\Iterables] is a static class with functions for working with iterators. Its counterpart for arrays is [Nette\Utils\Arrays|arrays]. + + +Installation: + +```shell +composer require nette/utils +``` + +All examples assume the creation of an alias: + +```php +use Nette\Utils\Iterables; +``` + + +contains(iterable $iterable, $value): bool .[method] +---------------------------------------------------- + +Tests for the presence of a value in the iterator. It uses strict comparison (`===`). + +```php +Iterables::contains(new ArrayIterator([1, 2, 3]), 1); // true +Iterables::contains(new ArrayIterator([1, 2, 3]), '1'); // false +``` + + +containsKey(iterable $iterable, $value): bool .[method] +------------------------------------------------------- + +Tests for the presence of a key in the iterator. It uses strict comparison (`===`). + +```php +Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0); // true +Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4); // false +``` + + +every(iterable $iterable, callable $predicate): bool .[method] +-------------------------------------------------------------- + +Tests whether all elements of the iterator pass a test implemented in `$predicate` with the signature `function ($value, $key, iterable $iterable): bool`. + +```php +$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]); +$isBelowThreshold = fn($value) => $value < 40; +$res = Iterables::every($iterator, $isBelowThreshold); // true +``` + +See [#some()]. + + +filter(iterable $iterable, callable $predicate): Generator .[method] +-------------------------------------------------------------------- + +Iterator that filters elements according to a predicate. The predicate has the signature `function ($value, $key, iterable $iterable): bool`. Maintains original keys. + +```php +$iterator = new ArrayIterator([1, 2, 3]); +$iterator = Iterables::filter($iterator, fn($v) => $v < 3); +// 1, 2 +``` + + +first(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------------- + +Returns the first item (matching the predicate, if specified). If no such item exists, returns the result of calling `$else` or null. +The `$predicate` parameter has the signature `function ($value, $key, iterable $iterable): bool`. + +```php +Iterables::first(new ArrayIterator([1, 2, 3])); // 1 +Iterables::first(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 3 +Iterables::first(new ArrayIterator([])); // null +Iterables::first(new ArrayIterator([]), else: fn() => false); // false +``` + + +firstKey(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method] +---------------------------------------------------------------------------------------------- + +Returns the key of the first item (matching the predicate, if specified). If no such item exists, returns the result of calling `$else` or null. The predicate has the signature `function ($value, $key, iterable $iterable): bool`. + +```php +Iterables::firstKey(new ArrayIterator([1, 2, 3])); // 0 +Iterables::firstKey(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 2 +Iterables::firstKey(new ArrayIterator(['a' => 1, 'b' => 2])); // 'a' +Iterables::firstKey(new ArrayIterator([])); // null +``` + + +map(iterable $iterable, callable $transformer): array .[method] +--------------------------------------------------------------- + +Iterator that transforms values by calling `$transformer`. It has the signature `function ($value, $key, iterable $iterable): bool`. Maintains original keys. + +```php +$iterator = new ArrayIterator([1, 2, 3]); +$iterator = Iterables::map($iterator, fn($v) => $v * 2); +// 2, 4, 6 +``` + + +some(iterable $iterable, callable $predicate): bool .[method] +------------------------------------------------------------- + +Tests whether at least one element of the iterator passes a test implemented in `$predicate` with the signature `function ($value, $key, iterable $iterable): bool`. + +```php +$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]); +$isEven = fn($value) => $value % 2 === 0; +$res = Iterables::some($iterator, $isEven); // true +``` + +See [#every()]. diff --git a/utils/es/@home.texy b/utils/es/@home.texy index de0038e21f..0bfdbb5347 100644 --- a/utils/es/@home.texy +++ b/utils/es/@home.texy @@ -13,6 +13,7 @@ En el paquete `nette/utils` encontrará un conjunto de clases útiles para el us | [Generación de cadenas aleatorias |random] | Nette\Utils\Random | [Generar código HTML |html-elements] | Nette\Utils\Html | [Generar PHP Reflection |reflection] | Nette\Utils\Reflection +| [Iterables |iterables] | Nette\Utils\Iterables | [Imágenes |Images] | Nette\Utils\Image | [JSON] | Nette\Utils\Json | [Matrices |Arrays] | Nette\Utils\Arrays diff --git a/utils/es/@left-menu.texy b/utils/es/@left-menu.texy index 5bea16e074..efa56faafc 100644 --- a/utils/es/@left-menu.texy +++ b/utils/es/@left-menu.texy @@ -8,6 +8,7 @@ Paquete nette/utils - [Fecha y hora |datetime] - [Flotadores |Floats] - [Funciones auxiliares |helpers] +- [Iterables |iterables] - [Imágenes |Images] - [JSON] - [Matrices |Arrays] diff --git a/utils/es/arrays.texy b/utils/es/arrays.texy index 219739fbdc..8f3956f59c 100644 --- a/utils/es/arrays.texy +++ b/utils/es/arrays.texy @@ -15,7 +15,7 @@ composer require nette/utils Arrays .[#toc-arrays] ===================== -[api:Nette\Utils\Arrays] es una clase estática que contiene un puñado de prácticas funciones de array. +[api:Nette\Utils\Arrays] es una clase estática, que contiene un puñado de prácticas funciones de array. Su equivalente para iteradores es [Nette\Utils\Iterables |iterables]. Los siguientes ejemplos asumen que el siguiente alias de clase está definido: @@ -76,8 +76,8 @@ Arrays::contains(['1', false], 1); // false ``` -every(iterable $array, callable $callback): bool .[method] ----------------------------------------------------------- +every(array $array, callable $predicate): bool .[method] +-------------------------------------------------------- Comprueba si todos los elementos de la matriz pasan la prueba implementada por la función proporcionada, que tiene la firma `function ($value, $key, array $array): bool`. @@ -90,16 +90,52 @@ $res = Arrays::every($array, $isBelowThreshold); // true Véase [some() |#some()]. -first(array $array): mixed .[method] ------------------------------------- +filter(array $array, callable $predicate): array .[method]{data-version:4.0.4} +------------------------------------------------------------------------------ + +Devuelve una nueva matriz que contiene todos los pares clave-valor que coinciden con la dirección `$predicate`. La llamada de retorno tiene la firma `function ($value, int|string $key, array $array): bool`. + +```php +Arrays::filter( + ['a' => 1, 'b' => 2, 'c' => 3], + fn($v) => $v < 3, +); +// ['a' => 1, 'b' => 2] +``` + + +first(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------- + +Devuelve el primer elemento (que coincida con el predicado especificado si se da). Si no existe tal elemento, devuelve el resultado de invocar `$else` o null. +El `$predicate` tiene la firma `function ($value, int|string $key, array $array): bool`. + +No modifica el puntero interno, a diferencia de `reset()`. Los parámetros `$predicate` y `$else` existen desde la versión 4.0.4. + +```php +Arrays::first([1, 2, 3]); // 1 +Arrays::first([1, 2, 3], fn($v) => $v > 2); // 3 +Arrays::first([]); // null +Arrays::first([], else: fn() => false); // false +``` -Devuelve el primer elemento del array o null si el array está vacío. No cambia el puntero interno a diferencia de `reset()`. +Véase [last() |#last()]. + + +firstKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4} +------------------------------------------------------------------------------------------------ + +Devuelve la clave del primer elemento (que coincida con el predicado especificado si se da) o null si no existe tal elemento. `$predicate` tiene la firma `function ($value, int|string $key, array $array): bool`. ```php -Arrays::first([1, 2, 3]); // 1 -Arrays::first([]); // null +Arrays::firstKey([1, 2, 3]); // 0 +Arrays::firstKey([1, 2, 3], fn($v) => $v > 2); // 2 +Arrays::firstKey(['a' => 1, 'b' => 2]); // 'a' +Arrays::firstKey([]); // null ``` +Véase [lastKey() |#lastKey()]. + flatten(array $array, bool $preserveKeys=false): array .[method] ---------------------------------------------------------------- @@ -229,21 +265,43 @@ Arrays::isList(['a' => 1, 'b' => 2]); // false ``` -last(array $array): mixed .[method] ------------------------------------ +last(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------ + +Devuelve el último elemento (que coincida con el predicado especificado si se da). Si no existe tal elemento, devuelve el resultado de invocar `$else` o null. +El `$predicate` tiene la firma `function ($value, int|string $key, array $array): bool`. + +No modifica el puntero interno, a diferencia de `end()`. Los parámetros `$predicate` y `$else` existen desde la versión 4.0.4. + +```php +Arrays::last([1, 2, 3]); // 3 +Arrays::last([1, 2, 3], fn($v) => $v < 3); // 2 +Arrays::last([]); // null +Arrays::last([], else: fn() => false); // false +``` + +Véase [first() |#first()]. + -Devuelve el último elemento del array o null si el array está vacío. No cambia el puntero interno a diferencia de `end()`. +lastKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4} +----------------------------------------------------------------------------------------------- + +Devuelve la clave del último elemento (que coincida con el predicado especificado si se da) o null si no existe tal elemento. `$predicate` tiene la firma `function ($value, int|string $key, array $array): bool`. ```php -Arrays::last([1, 2, 3]); // 3 -Arrays::last([]); // null +Arrays::lastKey([1, 2, 3]); // 2 +Arrays::lastKey([1, 2, 3], fn($v) => $v < 3); // 1 +Arrays::lastKey(['a' => 1, 'b' => 2]); // 'b' +Arrays::lastKey([]); // null ``` +Véase [firstKey() |#firstKey()]. + -map(iterable $array, callable $callback): array .[method] +map(array $array, callable $transformer): array .[method] --------------------------------------------------------- -Llama a `$callback` en todos los elementos de la matriz y devuelve la matriz de valores de retorno. La llamada de retorno tiene la firma `function ($value, $key, array $array): bool`. +Llama a `$transformer` en todos los elementos de la matriz y devuelve la matriz de valores de retorno. La llamada de retorno tiene la firma `function ($value, $key, array $array): bool`. ```php $array = ['foo', 'bar', 'baz']; @@ -325,8 +383,8 @@ $position = Arrays::getKeyOffset($array, 'not-exists'); // returns null ``` -some(iterable $array, callable $callback): bool .[method] ---------------------------------------------------------- +some(array $array, callable $predicate): bool .[method] +------------------------------------------------------- Comprueba si al menos un elemento de la matriz supera la prueba implementada por la llamada de retorno proporcionada con la firma `function ($value, $key, array $array): bool`. diff --git a/utils/es/images.texy b/utils/es/images.texy index 3d34e6f2c0..85e01cfd60 100644 --- a/utils/es/images.texy +++ b/utils/es/images.texy @@ -300,6 +300,11 @@ static isTypeSupported(int $type): bool .[method] Determina si el [tipo de |#Formats] imagen dado es compatible. +static getSupportedTypes(): array .[method]{data-version:4.0.4} +--------------------------------------------------------------- +Devuelve un array de tipos de imagen soportados (constantes `ImageType::XXX`). + + static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method] ------------------------------------------------------------------------------------------------------------------------ Calcula las dimensiones del rectángulo que encierra el texto en una fuente y tamaño especificados. Devuelve una matriz asociativa que contiene las claves `left`, `top`, `width`, `height`. El margen izquierdo puede ser negativo si el texto comienza con un saliente a la izquierda. diff --git a/utils/es/iterables.texy b/utils/es/iterables.texy new file mode 100644 index 0000000000..fd4aa9ef4f --- /dev/null +++ b/utils/es/iterables.texy @@ -0,0 +1,119 @@ +Funciones de iteración +********************** + +.[perex]{data-version:4.0.4} +[api:Nette\Utils\Iterables] es una clase estática con funciones para trabajar con iteradores. Su homólogo para arrays es [Nette\Utils\Arrays |arrays]. + + +Instalación: + +```shell +composer require nette/utils +``` + +Todos los ejemplos suponen la creación de un alias: + +```php +use Nette\Utils\Iterables; +``` + + +contains(iterable $iterable, $value): bool .[method] +---------------------------------------------------- + +Comprueba la presencia de un valor en el iterador. Utiliza la comparación estricta (`===`). + +```php +Iterables::contains(new ArrayIterator([1, 2, 3]), 1); // true +Iterables::contains(new ArrayIterator([1, 2, 3]), '1'); // false +``` + + +containsKey(iterable $iterable, $value): bool .[method] +------------------------------------------------------- + +Comprueba la presencia de una clave en el iterador. Utiliza la comparación estricta (`===`). + +```php +Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0); // true +Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4); // false +``` + + +every(iterable $iterable, callable $predicate): bool .[method] +-------------------------------------------------------------- + +Comprueba si todos los elementos del iterador pasan una prueba implementada en `$predicate` con la firma `function ($value, $key, iterable $iterable): bool`. + +```php +$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]); +$isBelowThreshold = fn($value) => $value < 40; +$res = Iterables::every($iterator, $isBelowThreshold); // true +``` + +Véase [some() |#some()]. + + +filter(iterable $iterable, callable $predicate): Generator .[method] +-------------------------------------------------------------------- + +Iterador que filtra elementos según un predicado. El predicado tiene la firma `function ($value, $key, iterable $iterable): bool`. Mantiene las claves originales. + +```php +$iterator = new ArrayIterator([1, 2, 3]); +$iterator = Iterables::filter($iterator, fn($v) => $v < 3); +// 1, 2 +``` + + +first(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------------- + +Devuelve el primer elemento (que coincida con el predicado, si se especifica). Si no existe tal elemento, devuelve el resultado de llamar a `$else` o null. +El parámetro `$predicate` tiene la firma `function ($value, $key, iterable $iterable): bool`. + +```php +Iterables::first(new ArrayIterator([1, 2, 3])); // 1 +Iterables::first(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 3 +Iterables::first(new ArrayIterator([])); // null +Iterables::first(new ArrayIterator([]), else: fn() => false); // false +``` + + +firstKey(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method] +---------------------------------------------------------------------------------------------- + +Devuelve la clave del primer elemento (que coincida con el predicado, si se especifica). Si no existe tal elemento, devuelve el resultado de llamar a `$else` o null. El predicado tiene la firma `function ($value, $key, iterable $iterable): bool`. + +```php +Iterables::firstKey(new ArrayIterator([1, 2, 3])); // 0 +Iterables::firstKey(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 2 +Iterables::firstKey(new ArrayIterator(['a' => 1, 'b' => 2])); // 'a' +Iterables::firstKey(new ArrayIterator([])); // null +``` + + +map(iterable $iterable, callable $transformer): array .[method] +--------------------------------------------------------------- + +Iterador que transforma valores llamando a `$transformer`. Tiene la firma `function ($value, $key, iterable $iterable): bool`. Mantiene las claves originales. + +```php +$iterator = new ArrayIterator([1, 2, 3]); +$iterator = Iterables::map($iterator, fn($v) => $v * 2); +// 2, 4, 6 +``` + + +some(iterable $iterable, callable $predicate): bool .[method] +------------------------------------------------------------- + +Comprueba si al menos un elemento del iterador pasa una prueba implementada en `$predicate` con la firma `function ($value, $key, iterable $iterable): bool`. + +```php +$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]); +$isEven = fn($value) => $value % 2 === 0; +$res = Iterables::some($iterator, $isEven); // true +``` + +Véase [every() |#every()]. diff --git a/utils/fr/@home.texy b/utils/fr/@home.texy index c22a155f85..174f8aadf2 100644 --- a/utils/fr/@home.texy +++ b/utils/fr/@home.texy @@ -13,6 +13,7 @@ Dans le paquetage `nette/utils`, vous trouverez un ensemble de classes utiles po | [Chaînes de caractères |Strings] | Nette\Utils\Strings | [Images] | Nette\Utils\Image | [JSON] | Nette\Utils\Json +| [Iterables |iterables] | Nette\Utils\Iterables | [Finder] | Nette\Utils\Finder | [Paginateur |Paginator] | Nette\Utils\Paginator | [PHP Reflection |reflection] | Nette\Utils\Reflection diff --git a/utils/fr/@left-menu.texy b/utils/fr/@left-menu.texy index bddfa8c498..93efe1a2b7 100644 --- a/utils/fr/@left-menu.texy +++ b/utils/fr/@left-menu.texy @@ -8,6 +8,7 @@ Paquet net/utils - [Chaînes aléatoires |random] - [Chaînes de caractères |Strings] - [Images] +- [Itérables |iterables] - [JSON] - [Paginateur |paginator] - [PHP Reflection |reflection] diff --git a/utils/fr/arrays.texy b/utils/fr/arrays.texy index b99a079110..bf9ad09adf 100644 --- a/utils/fr/arrays.texy +++ b/utils/fr/arrays.texy @@ -15,7 +15,7 @@ composer require nette/utils Matrices .[#toc-arrays] ======================= -[api:Nette\Utils\Arrays] est une classe statique, qui contient une poignée de fonctions pratiques pour les tableaux. +[api:Nette\Utils\Arrays] est une classe statique qui contient une poignée de fonctions pratiques pour les tableaux. Son équivalent pour les itérateurs est [Nette\Utils\Iterables |iterables]. Les exemples suivants supposent que l'alias de classe suivant est défini : @@ -76,8 +76,8 @@ Arrays::contains(['1', false], 1); // false ``` -every(iterable $array, callable $callback): bool .[method] ----------------------------------------------------------- +every(array $array, callable $predicate): bool .[method] +-------------------------------------------------------- Teste si tous les éléments du tableau passent le test implémenté par la fonction fournie, qui a la signature `function ($value, $key, array $array): bool`. @@ -90,16 +90,52 @@ $res = Arrays::every($array, $isBelowThreshold); // true Voir [some() |#some()]. -first(array $array): mixed .[method] ------------------------------------- +filter(array $array, callable $predicate): array .[method]{data-version:4.0.4} +------------------------------------------------------------------------------ + +Renvoie un nouveau tableau contenant toutes les paires clé-valeur correspondant à l'adresse `$predicate`. Le rappel a la signature `function ($value, int|string $key, array $array): bool`. + +```php +Arrays::filter( + ['a' => 1, 'b' => 2, 'c' => 3], + fn($v) => $v < 3, +); +// ['a' => 1, 'b' => 2] +``` + + +first(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------- + +Renvoie le premier élément (correspondant au prédicat spécifié s'il est donné). S'il n'y a pas d'élément de ce type, il renvoie le résultat de l'invocation de `$else` ou null. +Le site `$predicate` a la signature `function ($value, int|string $key, array $array): bool`. + +Il ne modifie pas le pointeur interne, contrairement à `reset()`. Les paramètres `$predicate` et `$else` existent depuis la version 4.0.4. + +```php +Arrays::first([1, 2, 3]); // 1 +Arrays::first([1, 2, 3], fn($v) => $v > 2); // 3 +Arrays::first([]); // null +Arrays::first([], else: fn() => false); // false +``` -Retourne le premier élément du tableau ou null si le tableau est vide. Elle ne modifie pas le pointeur interne contrairement à `reset()`. +Voir [last() |#last()]. + + +firstKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4} +------------------------------------------------------------------------------------------------ + +Renvoie la clé du premier élément (correspondant au prédicat spécifié s'il est donné) ou null s'il n'y a pas d'élément de ce type. La signature de `$predicate` est `function ($value, int|string $key, array $array): bool`. ```php -Arrays::first([1, 2, 3]); // 1 -Arrays::first([]); // null +Arrays::firstKey([1, 2, 3]); // 0 +Arrays::firstKey([1, 2, 3], fn($v) => $v > 2); // 2 +Arrays::firstKey(['a' => 1, 'b' => 2]); // 'a' +Arrays::firstKey([]); // null ``` +Voir [lastKey() |#lastKey()]. + flatten(array $array, bool $preserveKeys=false): array .[method] ---------------------------------------------------------------- @@ -229,21 +265,43 @@ Arrays::isList(['a' => 1, 'b' => 2]); // false ``` -last(array $array): mixed .[method] ------------------------------------ +last(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------ + +Renvoie le dernier élément (correspondant au prédicat spécifié, le cas échéant). S'il n'existe pas d'élément de ce type, il renvoie le résultat de l'invocation de `$else` ou null. +Le site `$predicate` a la signature `function ($value, int|string $key, array $array): bool`. + +Il ne modifie pas le pointeur interne, contrairement à `end()`. Les paramètres `$predicate` et `$else` existent depuis la version 4.0.4. + +```php +Arrays::last([1, 2, 3]); // 3 +Arrays::last([1, 2, 3], fn($v) => $v < 3); // 2 +Arrays::last([]); // null +Arrays::last([], else: fn() => false); // false +``` + +Voir [first() |#first()]. + -Retourne le dernier élément du tableau ou null si le tableau est vide. Elle ne modifie pas le pointeur interne contrairement à `end()`. +lastKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4} +----------------------------------------------------------------------------------------------- + +Renvoie la clé du dernier élément (correspondant au prédicat spécifié s'il est donné) ou null s'il n'y a pas d'élément de ce type. La signature de `$predicate` est `function ($value, int|string $key, array $array): bool`. ```php -Arrays::last([1, 2, 3]); // 3 -Arrays::last([]); // null +Arrays::lastKey([1, 2, 3]); // 2 +Arrays::lastKey([1, 2, 3], fn($v) => $v < 3); // 1 +Arrays::lastKey(['a' => 1, 'b' => 2]); // 'b' +Arrays::lastKey([]); // null ``` +Voir [firstKey() |#firstKey()]. + -map(iterable $array, callable $callback): array .[method] +map(array $array, callable $transformer): array .[method] --------------------------------------------------------- -Appelle `$callback` sur tous les éléments du tableau et renvoie le tableau des valeurs de retour. Le callback a la signature `function ($value, $key, array $array): bool`. +Appelle `$transformer` sur tous les éléments du tableau et renvoie le tableau des valeurs de retour. Le callback a la signature `function ($value, $key, array $array): bool`. ```php $array = ['foo', 'bar', 'baz']; @@ -325,8 +383,8 @@ $position = Arrays::getKeyOffset($array, 'not-exists'); // returns null ``` -some(iterable $array, callable $callback): bool .[method] ---------------------------------------------------------- +some(array $array, callable $predicate): bool .[method] +------------------------------------------------------- Teste si au moins un élément du tableau passe le test implémenté par la callback fournie avec la signature `function ($value, $key, array $array): bool`. diff --git a/utils/fr/images.texy b/utils/fr/images.texy index 293f68cb22..33836488b4 100644 --- a/utils/fr/images.texy +++ b/utils/fr/images.texy @@ -300,6 +300,11 @@ static isTypeSupported(int $type): bool .[method] Détermine si le [type d' |#Formats] image donné est pris en charge. +static getSupportedTypes(): array .[method]{data-version:4.0.4} +--------------------------------------------------------------- +Renvoie un tableau des types d'images pris en charge (constantes `ImageType::XXX`). + + static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method] ------------------------------------------------------------------------------------------------------------------------ Calcule les dimensions du rectangle qui entoure le texte d'une police et d'une taille spécifiées. Il renvoie un tableau associatif contenant les clés `left`, `top`, `width`, `height`. La marge de gauche peut être négative si le texte commence avec un débordement à gauche. diff --git a/utils/fr/iterables.texy b/utils/fr/iterables.texy new file mode 100644 index 0000000000..cc63f3c5c7 --- /dev/null +++ b/utils/fr/iterables.texy @@ -0,0 +1,119 @@ +Fonctions de l'itérateur +************************ + +.[perex]{data-version:4.0.4} +[api:Nette\Utils\Iterables] est une classe statique contenant des fonctions permettant de travailler avec des itérateurs. Son équivalent pour les tableaux est [Nette\Utils\Arrays |arrays]. + + +L'installation : + +```shell +composer require nette/utils +``` + +Tous les exemples supposent la création d'un alias : + +```php +use Nette\Utils\Iterables; +``` + + +contains(iterable $iterable, $value): bool .[method] +---------------------------------------------------- + +Teste la présence d'une valeur dans l'itérateur. Il utilise une comparaison stricte (`===`). + +```php +Iterables::contains(new ArrayIterator([1, 2, 3]), 1); // true +Iterables::contains(new ArrayIterator([1, 2, 3]), '1'); // false +``` + + +containsKey(iterable $iterable, $value): bool .[method] +------------------------------------------------------- + +Teste la présence d'une clé dans l'itérateur. Il utilise la comparaison stricte (`===`). + +```php +Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0); // true +Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4); // false +``` + + +every(iterable $iterable, callable $predicate): bool .[method] +-------------------------------------------------------------- + +Teste si tous les éléments de l'itérateur passent un test implémenté dans `$predicate` avec la signature `function ($value, $key, iterable $iterable): bool`. + +```php +$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]); +$isBelowThreshold = fn($value) => $value < 40; +$res = Iterables::every($iterator, $isBelowThreshold); // true +``` + +Voir [some() |#some()]. + + +filter(iterable $iterable, callable $predicate): Generator .[method] +-------------------------------------------------------------------- + +Itérateur qui filtre les éléments en fonction d'un prédicat. Le prédicat a la signature `function ($value, $key, iterable $iterable): bool`. Maintient les clés d'origine. + +```php +$iterator = new ArrayIterator([1, 2, 3]); +$iterator = Iterables::filter($iterator, fn($v) => $v < 3); +// 1, 2 +``` + + +first(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------------- + +Renvoie le premier élément (correspondant au prédicat, s'il est spécifié). Si aucun élément de ce type n'existe, il renvoie le résultat de l'appel à `$else` ou null. +Le paramètre `$predicate` a la signature `function ($value, $key, iterable $iterable): bool`. + +```php +Iterables::first(new ArrayIterator([1, 2, 3])); // 1 +Iterables::first(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 3 +Iterables::first(new ArrayIterator([])); // null +Iterables::first(new ArrayIterator([]), else: fn() => false); // false +``` + + +firstKey(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method] +---------------------------------------------------------------------------------------------- + +Renvoie la clé du premier élément (correspondant au prédicat, s'il est spécifié). Si aucun élément de ce type n'existe, il renvoie le résultat de l'appel à `$else` ou null. Le prédicat a la signature `function ($value, $key, iterable $iterable): bool`. + +```php +Iterables::firstKey(new ArrayIterator([1, 2, 3])); // 0 +Iterables::firstKey(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 2 +Iterables::firstKey(new ArrayIterator(['a' => 1, 'b' => 2])); // 'a' +Iterables::firstKey(new ArrayIterator([])); // null +``` + + +map(iterable $iterable, callable $transformer): array .[method] +--------------------------------------------------------------- + +Itérateur qui transforme les valeurs en appelant `$transformer`. Il porte la signature `function ($value, $key, iterable $iterable): bool`. Il conserve les clés d'origine. + +```php +$iterator = new ArrayIterator([1, 2, 3]); +$iterator = Iterables::map($iterator, fn($v) => $v * 2); +// 2, 4, 6 +``` + + +some(iterable $iterable, callable $predicate): bool .[method] +------------------------------------------------------------- + +Teste si au moins un élément de l'itérateur passe un test implémenté dans `$predicate` avec la signature `function ($value, $key, iterable $iterable): bool`. + +```php +$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]); +$isEven = fn($value) => $value % 2 === 0; +$res = Iterables::some($iterator, $isEven); // true +``` + +Voir [every() |#every()]. diff --git a/utils/hu/@home.texy b/utils/hu/@home.texy index 3ad3dae544..9597ed506f 100644 --- a/utils/hu/@home.texy +++ b/utils/hu/@home.texy @@ -13,6 +13,7 @@ A `nette/utils` csomagban a mindennapi használatra hasznos osztályok találhat | [Segédprogramok |helpers] | Nette\Utils\Helpers | [HTML elemek |HTML Elements] | Nette\Utils\Html | [Képek |Images] | Nette\Utils\Image +| [Iterables |iterables] | Nette\Utils\Iterables | [JSON |JSON] | Nette\Utils\Json | [Paginátor |paginator] | Nette\Utils\Paginátor | [PHP Reflection |reflection] | Nette\Utils\Reflection diff --git a/utils/hu/@left-menu.texy b/utils/hu/@left-menu.texy index 9e6f969b23..8068605260 100644 --- a/utils/hu/@left-menu.texy +++ b/utils/hu/@left-menu.texy @@ -8,6 +8,7 @@ Csomag nette/utils - [Segédprogramok |helpers] - [HTML elemek |HTML Elements] - [Képek |Images] +- [Iterábilisok |iterables] - [JSON |JSON] - [Paginátor |paginator] - [Véletlenszerű karakterláncok |random] diff --git a/utils/hu/arrays.texy b/utils/hu/arrays.texy index 04ad5c1c18..178927eb84 100644 --- a/utils/hu/arrays.texy +++ b/utils/hu/arrays.texy @@ -15,7 +15,7 @@ composer require nette/utils Arrays .[#toc-arrays] ===================== -[api:Nette\Utils\Arrays] egy statikus osztály, amely egy maroknyi praktikus tömbfüggvényt tartalmaz. +[api:Nette\Utils\Arrays] egy statikus osztály, amely egy maroknyi hasznos tömbfüggvényt tartalmaz. Ennek megfelelője az iterátorok esetében a [Nette\Utils\Iterables |iterables]. A következő példák feltételezik, hogy a következő osztály alias definiálva van: @@ -76,8 +76,8 @@ Arrays::contains(['1', false], 1); // false ``` -every(iterable $array, callable $callback): bool .[method] ----------------------------------------------------------- +every(array $array, callable $predicate): bool .[method] +-------------------------------------------------------- Megvizsgálja, hogy a tömb minden eleme megfelel-e a megadott függvény által végrehajtott tesztnek, amelynek aláírása `function ($value, $key, array $array): bool`. @@ -90,16 +90,52 @@ $res = Arrays::every($array, $isBelowThreshold); // true Lásd [some() |#some()]. -first(array $array): mixed .[method] ------------------------------------- +filter(array $array, callable $predicate): array .[method]{data-version:4.0.4} +------------------------------------------------------------------------------ + +Visszaad egy új tömböt, amely tartalmazza az összes kulcs-érték párt, amely megfelel a megadott `$predicate`. A visszahívás aláírása `function ($value, int|string $key, array $array): bool`. + +```php +Arrays::filter( + ['a' => 1, 'b' => 2, 'c' => 3], + fn($v) => $v < 3, +); +// ['a' => 1, 'b' => 2] +``` + + +first(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------- + +Visszaadja az első elemet (amely megfelel a megadott predikátumnak, ha megadva van). Ha nincs ilyen elem, akkor a `$else` meghívásának eredményét vagy nullát adja vissza. +A `$predicate` aláírása `function ($value, int|string $key, array $array): bool`. + +Nem változtatja meg a belső mutatót, ellentétben a `reset()`. A `$predicate` és `$else` paraméterek a 4.0.4-es verzió óta léteznek. + +```php +Arrays::first([1, 2, 3]); // 1 +Arrays::first([1, 2, 3], fn($v) => $v > 2); // 3 +Arrays::first([]); // null +Arrays::first([], else: fn() => false); // false +``` -Visszaadja a tömb első elemét, vagy null, ha a tömb üres. Nem változtatja meg a belső mutatót, ellentétben a `reset()`. +Lásd [last() |#last()]. + + +firstKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4} +------------------------------------------------------------------------------------------------ + +Visszaadja az első elem kulcsát (amely megfelel a megadott predikátumnak, ha megadva van), vagy null, ha nincs ilyen elem. A `$predicate` aláírása `function ($value, int|string $key, array $array): bool`. ```php -Arrays::first([1, 2, 3]); // 1 -Arrays::first([]); // null +Arrays::firstKey([1, 2, 3]); // 0 +Arrays::firstKey([1, 2, 3], fn($v) => $v > 2); // 2 +Arrays::firstKey(['a' => 1, 'b' => 2]); // 'a' +Arrays::firstKey([]); // null ``` +Lásd [lastKey() |#lastKey()]. + flatten(array $array, bool $preserveKeys=false): array .[method] ---------------------------------------------------------------- @@ -229,21 +265,43 @@ Arrays::isList(['a' => 1, 'b' => 2]); // false ``` -last(array $array): mixed .[method] ------------------------------------ +last(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------ + +Visszaadja az utolsó elemet (amely megfelel a megadott predikátumnak, ha megadva van). Ha nincs ilyen elem, akkor a `$else` meghívásának eredményét vagy nullát adja vissza. +A `$predicate` aláírása `function ($value, int|string $key, array $array): bool`. + +Nem változtatja meg a belső mutatót, ellentétben a `end()`. A `$predicate` és `$else` paraméterek a 4.0.4-es verzió óta léteznek. + +```php +Arrays::last([1, 2, 3]); // 3 +Arrays::last([1, 2, 3], fn($v) => $v < 3); // 2 +Arrays::last([]); // null +Arrays::last([], else: fn() => false); // false +``` + +Lásd [first() |#first()]. + -Visszaadja a tömb utolsó elemét vagy nullát, ha a tömb üres. Nem változtatja meg a belső mutatót, ellentétben a `end()`. +lastKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4} +----------------------------------------------------------------------------------------------- + +Visszaadja az utolsó elem kulcsát (amely megfelel a megadott predikátumnak, ha meg van adva), vagy null, ha nincs ilyen elem. A `$predicate` aláírása `function ($value, int|string $key, array $array): bool`. ```php -Arrays::last([1, 2, 3]); // 3 -Arrays::last([]); // null +Arrays::lastKey([1, 2, 3]); // 2 +Arrays::lastKey([1, 2, 3], fn($v) => $v < 3); // 1 +Arrays::lastKey(['a' => 1, 'b' => 2]); // 'b' +Arrays::lastKey([]); // null ``` +Lásd [firstKey() |#firstKey()]. + -map(iterable $array, callable $callback): array .[method] +map(array $array, callable $transformer): array .[method] --------------------------------------------------------- -A `$callback` meghívja a tömb összes elemét, és visszaadja a visszatérési értékek tömbjét. A visszahívás aláírása `function ($value, $key, array $array): bool`. +A `$transformer` meghívja a tömb összes elemét, és visszaadja a visszatérési értékek tömbjét. A visszahívás aláírása `function ($value, $key, array $array): bool`. ```php $array = ['foo', 'bar', 'baz']; @@ -325,8 +383,8 @@ $position = Arrays::getKeyOffset($array, 'not-exists'); // nullát ad vissza ``` -some(iterable $array, callable $callback): bool .[method] ---------------------------------------------------------- +some(array $array, callable $predicate): bool .[method] +------------------------------------------------------- Megvizsgálja, hogy a tömb legalább egy eleme átmegy-e a `function ($value, $key, array $array): bool` aláírással ellátott callback által végrehajtott teszten. diff --git a/utils/hu/images.texy b/utils/hu/images.texy index 7c8be60c3b..b1c513f87e 100644 --- a/utils/hu/images.texy +++ b/utils/hu/images.texy @@ -300,6 +300,11 @@ static isTypeSupported(int $type): bool .[method] Megállapítja, hogy az adott [képtípus |#Formats] támogatott-e. +static getSupportedTypes(): array .[method]{data-version:4.0.4} +--------------------------------------------------------------- +Visszaadja a támogatott képtípusok tömbjét (konstansok `ImageType::XXX`). + + static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method] ------------------------------------------------------------------------------------------------------------------------ Kiszámítja a megadott betűtípusú és méretű szöveget körülvevő téglalap méreteit. Egy asszociatív tömböt ad vissza, amely a `left`, `top`, `width`, `height` kulcsokat tartalmazza. A bal oldali margó negatív lehet, ha a szöveg bal oldali túlnyúlással kezdődik. diff --git a/utils/hu/iterables.texy b/utils/hu/iterables.texy new file mode 100644 index 0000000000..8abc933d62 --- /dev/null +++ b/utils/hu/iterables.texy @@ -0,0 +1,119 @@ +Iterátor funkciók +***************** + +.[perex]{data-version:4.0.4} +[api:Nette\Utils\Iterables] egy statikus osztály, amely az iterátorokkal való munkához szükséges függvényeket tartalmazza. A tömbökre vonatkozó megfelelője a [Nette\Utils\Arrays |arrays]. + + +Telepítés: + +```shell +composer require nette/utils +``` + +Minden példa feltételezi egy alias létrehozását: + +```php +use Nette\Utils\Iterables; +``` + + +contains(iterable $iterable, $value): bool .[method] +---------------------------------------------------- + +Az iterátorban lévő érték jelenlétének vizsgálata. Szigorú összehasonlítást használ (`===`). + +```php +Iterables::contains(new ArrayIterator([1, 2, 3]), 1); // true +Iterables::contains(new ArrayIterator([1, 2, 3]), '1'); // false +``` + + +containsKey(iterable $iterable, $value): bool .[method] +------------------------------------------------------- + +Az iterátorban lévő kulcs jelenlétét vizsgálja. Szigorú összehasonlítást használ (`===`). + +```php +Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0); // true +Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4); // false +``` + + +every(iterable $iterable, callable $predicate): bool .[method] +-------------------------------------------------------------- + +Azt vizsgálja, hogy az iterátor minden eleme megfelel-e a `$predicate` -ban megvalósított, `function ($value, $key, iterable $iterable): bool` aláírással ellátott tesztnek. + +```php +$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]); +$isBelowThreshold = fn($value) => $value < 40; +$res = Iterables::every($iterator, $isBelowThreshold); // true +``` + +Lásd [some() |#some()]. + + +filter(iterable $iterable, callable $predicate): Generator .[method] +-------------------------------------------------------------------- + +Iterátor, amely az elemeket egy predikátum alapján szűri. A predikátum aláírása `function ($value, $key, iterable $iterable): bool`. Fenntartja az eredeti kulcsokat. + +```php +$iterator = new ArrayIterator([1, 2, 3]); +$iterator = Iterables::filter($iterator, fn($v) => $v < 3); +// 1, 2 +``` + + +first(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------------- + +Visszaadja az első elemet (amely megfelel a predikátumnak, ha meg van adva). Ha ilyen elem nem létezik, a `$else` hívásának eredményét vagy nullát adja vissza. +A `$predicate` paraméter aláírása `function ($value, $key, iterable $iterable): bool`. + +```php +Iterables::first(new ArrayIterator([1, 2, 3])); // 1 +Iterables::first(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 3 +Iterables::first(new ArrayIterator([])); // null +Iterables::first(new ArrayIterator([]), else: fn() => false); // false +``` + + +firstKey(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method] +---------------------------------------------------------------------------------------------- + +Visszaadja az első elem kulcsát (amely megfelel a predikátumnak, ha meg van adva). Ha ilyen elem nem létezik, a `$else` hívásának eredményét vagy nullát adja vissza. A predikátum aláírása `function ($value, $key, iterable $iterable): bool`. + +```php +Iterables::firstKey(new ArrayIterator([1, 2, 3])); // 0 +Iterables::firstKey(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 2 +Iterables::firstKey(new ArrayIterator(['a' => 1, 'b' => 2])); // 'a' +Iterables::firstKey(new ArrayIterator([])); // null +``` + + +map(iterable $iterable, callable $transformer): array .[method] +--------------------------------------------------------------- + +Iterátor, amely az értékeket a `$transformer` meghívásával alakítja át. Aláírása: `function ($value, $key, iterable $iterable): bool`. Fenntartja az eredeti kulcsokat. + +```php +$iterator = new ArrayIterator([1, 2, 3]); +$iterator = Iterables::map($iterator, fn($v) => $v * 2); +// 2, 4, 6 +``` + + +some(iterable $iterable, callable $predicate): bool .[method] +------------------------------------------------------------- + +Azt vizsgálja, hogy az iterátor legalább egy eleme megfelel-e a `$predicate` nyelven megvalósított, `function ($value, $key, iterable $iterable): bool` aláírással ellátott tesztnek. + +```php +$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]); +$isEven = fn($value) => $value % 2 === 0; +$res = Iterables::some($iterator, $isEven); // true +``` + +Lásd [every() |#every()]. diff --git a/utils/it/@home.texy b/utils/it/@home.texy index a3bf3fc8fe..f1d7290a66 100644 --- a/utils/it/@home.texy +++ b/utils/it/@home.texy @@ -13,6 +13,7 @@ Il pacchetto `nette/utils` contiene un insieme di classi utili per l'uso quotidi | [Helpers |helpers] | Nette\Utils\Helpers | [Elementi HTML |HTML Elements] | Nette\Utils\Html | [Immagini |Images] | Nette\Utils\Image +| [Iterabili |iterables] | Nette\Utils\Iterables | [JSON |JSON] | Nette\Utils\Json | [Paginatore |paginator] | Nette\Utils\Paginatore | [Riflessione PHP |reflection] | Nette\Utils\Reflection diff --git a/utils/it/@left-menu.texy b/utils/it/@left-menu.texy index 0e8f491439..d7407854fc 100644 --- a/utils/it/@left-menu.texy +++ b/utils/it/@left-menu.texy @@ -8,6 +8,7 @@ Pacchetto nette/utils - [Aiutanti |helpers] - [Elementi HTML |HTML Elements] - [Immagini |Images] +- [Iterabili |iterables] - [JSON |JSON] - [Paginatore |paginator] - [Stringhe casuali |random] diff --git a/utils/it/arrays.texy b/utils/it/arrays.texy index 55a5397fa5..cf43f008ad 100644 --- a/utils/it/arrays.texy +++ b/utils/it/arrays.texy @@ -15,7 +15,7 @@ composer require nette/utils Array .[#toc-arrays] ==================== -[api:Nette\Utils\Arrays] è una classe statica che contiene una serie di pratiche funzioni per gli array. +[api:Nette\Utils\Arrays] è una classe statica che contiene una manciata di pratiche funzioni per gli array. Il suo equivalente per gli iteratori è [Nette\Utils\Iterables |iterables]. Gli esempi seguenti presuppongono che sia definito il seguente alias di classe: @@ -76,8 +76,8 @@ Arrays::contains(['1', false], 1); // false ``` -every(iterable $array, callable $callback): bool .[method] ----------------------------------------------------------- +every(array $array, callable $predicate): bool .[method] +-------------------------------------------------------- Verifica se tutti gli elementi dell'array superano il test implementato dalla funzione fornita, che ha la firma `function ($value, $key, array $array): bool`. @@ -90,16 +90,52 @@ $res = Arrays::every($array, $isBelowThreshold); // true Vedere [some() |#some()]. -first(array $array): mixed .[method] ------------------------------------- +filter(array $array, callable $predicate): array .[method]{data-version:4.0.4} +------------------------------------------------------------------------------ + +Restituisce un nuovo array contenente tutte le coppie chiave-valore corrispondenti al dato `$predicate`. Il callback ha la firma `function ($value, int|string $key, array $array): bool`. + +```php +Arrays::filter( + ['a' => 1, 'b' => 2, 'c' => 3], + fn($v) => $v < 3, +); +// ['a' => 1, 'b' => 2] +``` + + +first(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------- + +Restituisce il primo elemento (che corrisponde al predicato specificato, se dato). Se non esiste un elemento, restituisce il risultato dell'invocazione di `$else` o null. + `$predicate` ha la firma `function ($value, int|string $key, array $array): bool`. + +Non modifica il puntatore interno, a differenza di `reset()`. I parametri `$predicate` e `$else` esistono dalla versione 4.0.4. + +```php +Arrays::first([1, 2, 3]); // 1 +Arrays::first([1, 2, 3], fn($v) => $v > 2); // 3 +Arrays::first([]); // null +Arrays::first([], else: fn() => false); // false +``` -Restituisce il primo elemento dell'array o null se l'array è vuoto. Non modifica il puntatore interno, a differenza di `reset()`. +Vedere [last() |#last()]. + + +firstKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4} +------------------------------------------------------------------------------------------------ + +Restituisce la chiave del primo elemento (che corrisponde al predicato specificato, se dato) o null se non esiste un elemento. `$predicate` ha la firma `function ($value, int|string $key, array $array): bool`. ```php -Arrays::first([1, 2, 3]); // 1 -Arrays::first([]); // null +Arrays::firstKey([1, 2, 3]); // 0 +Arrays::firstKey([1, 2, 3], fn($v) => $v > 2); // 2 +Arrays::firstKey(['a' => 1, 'b' => 2]); // 'a' +Arrays::firstKey([]); // null ``` +Vedere [lastKey() |#lastKey()]. + flatten(array $array, bool $preserveKeys=false): array .[method] ---------------------------------------------------------------- @@ -229,21 +265,43 @@ Arrays::isList(['a' => 1, 'b' => 2]); // false ``` -last(array $array): mixed .[method] ------------------------------------ +last(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------ + +Restituisce l'ultimo elemento (che corrisponde al predicato specificato, se dato). Se non esiste un elemento, restituisce il risultato dell'invocazione di `$else` o null. + `$predicate` ha la firma `function ($value, int|string $key, array $array): bool`. + +Non modifica il puntatore interno, a differenza di `end()`. I parametri `$predicate` e `$else` esistono dalla versione 4.0.4. + +```php +Arrays::last([1, 2, 3]); // 3 +Arrays::last([1, 2, 3], fn($v) => $v < 3); // 2 +Arrays::last([]); // null +Arrays::last([], else: fn() => false); // false +``` + +Vedere [prima() |#first()]. + -Restituisce l'ultimo elemento dell'array o null se l'array è vuoto. Non modifica il puntatore interno, a differenza di `end()`. +lastKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4} +----------------------------------------------------------------------------------------------- + +Restituisce la chiave dell'ultimo elemento (che corrisponde al predicato specificato, se dato) o null se non esiste un elemento. `$predicate` ha la firma `function ($value, int|string $key, array $array): bool`. ```php -Arrays::last([1, 2, 3]); // 3 -Arrays::last([]); // null +Arrays::lastKey([1, 2, 3]); // 2 +Arrays::lastKey([1, 2, 3], fn($v) => $v < 3); // 1 +Arrays::lastKey(['a' => 1, 'b' => 2]); // 'b' +Arrays::lastKey([]); // null ``` +Vedere [firstKey() |#firstKey()]. + -map(iterable $array, callable $callback): array .[method] +map(array $array, callable $transformer): array .[method] --------------------------------------------------------- -Richiama `$callback` su tutti gli elementi dell'array e restituisce l'array dei valori di ritorno. Il callback ha la firma `function ($value, $key, array $array): bool`. +Richiama `$transformer` su tutti gli elementi dell'array e restituisce l'array dei valori di ritorno. Il callback ha la firma `function ($value, $key, array $array): bool`. ```php $array = ['foo', 'bar', 'baz']; @@ -325,8 +383,8 @@ $position = Arrays::getKeyOffset($array, 'not-exists'); // restituisce null ``` -some(iterable $array, callable $callback): bool .[method] ---------------------------------------------------------- +some(array $array, callable $predicate): bool .[method] +------------------------------------------------------- Verifica se almeno un elemento dell'array supera il test implementato dal callback fornito con la firma `function ($value, $key, array $array): bool`. diff --git a/utils/it/images.texy b/utils/it/images.texy index 6db8f308cb..9e5065b80c 100644 --- a/utils/it/images.texy +++ b/utils/it/images.texy @@ -300,6 +300,11 @@ static isTypeSupported(int $type): bool .[method] Determina se il [tipo di |#Formats] immagine dato è supportato. +static getSupportedTypes(): array .[method]{data-version:4.0.4} +--------------------------------------------------------------- +Restituisce un array di tipi di immagine supportati (costanti `ImageType::XXX`). + + static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method] ------------------------------------------------------------------------------------------------------------------------ Calcola le dimensioni del rettangolo che racchiude il testo in un font e in una dimensione specificati. Restituisce un array associativo contenente le chiavi `left`, `top`, `width`, `height`. Il margine sinistro può essere negativo se il testo inizia con una sporgenza a sinistra. diff --git a/utils/it/iterables.texy b/utils/it/iterables.texy new file mode 100644 index 0000000000..c0b5462503 --- /dev/null +++ b/utils/it/iterables.texy @@ -0,0 +1,119 @@ +Funzioni di iteratore +********************* + +.[perex]{data-version:4.0.4} +[api:Nette\Utils\Iterables] è una classe statica con funzioni per lavorare con gli iteratori. La sua controparte per gli array è [NetteUtilsArrays |arrays]. + + +Installazione: + +```shell +composer require nette/utils +``` + +Tutti gli esempi presuppongono la creazione di un alias: + +```php +use Nette\Utils\Iterables; +``` + + +contains(iterable $iterable, $value): bool .[method] +---------------------------------------------------- + +Verifica la presenza di un valore nell'iteratore. Utilizza un confronto rigoroso (`===`). + +```php +Iterables::contains(new ArrayIterator([1, 2, 3]), 1); // true +Iterables::contains(new ArrayIterator([1, 2, 3]), '1'); // false +``` + + +containsKey(iterable $iterable, $value): bool .[method] +------------------------------------------------------- + +Verifica la presenza di una chiave nell'iteratore. Utilizza un confronto rigoroso (`===`). + +```php +Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0); // true +Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4); // false +``` + + +every(iterable $iterable, callable $predicate): bool .[method] +-------------------------------------------------------------- + +Verifica se tutti gli elementi dell'iteratore superano un test implementato in `$predicate` con la firma `function ($value, $key, iterable $iterable): bool`. + +```php +$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]); +$isBelowThreshold = fn($value) => $value < 40; +$res = Iterables::every($iterator, $isBelowThreshold); // true +``` + +Vedere [some() |#some()]. + + +filter(iterable $iterable, callable $predicate): Generator .[method] +-------------------------------------------------------------------- + +Iteratore che filtra gli elementi in base a un predicato. Il predicato ha la firma `function ($value, $key, iterable $iterable): bool`. Mantiene le chiavi originali. + +```php +$iterator = new ArrayIterator([1, 2, 3]); +$iterator = Iterables::filter($iterator, fn($v) => $v < 3); +// 1, 2 +``` + + +first(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------------- + +Restituisce il primo elemento (che corrisponde al predicato, se specificato). Se non esiste alcun elemento, restituisce il risultato della chiamata a `$else` o null. +Il parametro `$predicate` ha la firma `function ($value, $key, iterable $iterable): bool`. + +```php +Iterables::first(new ArrayIterator([1, 2, 3])); // 1 +Iterables::first(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 3 +Iterables::first(new ArrayIterator([])); // null +Iterables::first(new ArrayIterator([]), else: fn() => false); // false +``` + + +firstKey(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method] +---------------------------------------------------------------------------------------------- + +Restituisce la chiave del primo elemento (che corrisponde al predicato, se specificato). Se non esiste un elemento, restituisce il risultato della chiamata a `$else` o null. Il predicato ha la firma `function ($value, $key, iterable $iterable): bool`. + +```php +Iterables::firstKey(new ArrayIterator([1, 2, 3])); // 0 +Iterables::firstKey(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 2 +Iterables::firstKey(new ArrayIterator(['a' => 1, 'b' => 2])); // 'a' +Iterables::firstKey(new ArrayIterator([])); // null +``` + + +map(iterable $iterable, callable $transformer): array .[method] +--------------------------------------------------------------- + +Iteratore che trasforma i valori richiamando `$transformer`. Ha la firma `function ($value, $key, iterable $iterable): bool`. Mantiene le chiavi originali. + +```php +$iterator = new ArrayIterator([1, 2, 3]); +$iterator = Iterables::map($iterator, fn($v) => $v * 2); +// 2, 4, 6 +``` + + +some(iterable $iterable, callable $predicate): bool .[method] +------------------------------------------------------------- + +Verifica se almeno un elemento dell'iteratore supera un test implementato in `$predicate` con la firma `function ($value, $key, iterable $iterable): bool`. + +```php +$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]); +$isEven = fn($value) => $value % 2 === 0; +$res = Iterables::some($iterator, $isEven); // true +``` + +Vedere [every() |#every()]. diff --git a/utils/pl/@home.texy b/utils/pl/@home.texy index 4ae656e9ad..a62dd5dc22 100644 --- a/utils/pl/@home.texy +++ b/utils/pl/@home.texy @@ -13,6 +13,7 @@ W pakiecie `nette/utils` znajdziesz zestaw przydatnych klas do codziennego użyt | [Obrazki |images] | Nette\Utils\Image | [Odbicie w PHP |reflection] | Nette\Utils\Reflection | [typy PHP |type] Nette\Utils\Type +| [Iterables |iterables] | Nette\Utils\Iterables | [Arrays |arrays] | Nette\Utils\Arrays | [Helper Functions |helpers] | Nette\Utils\Helpers | [Porównywanie pływaków |floats] | Nette\Utils\Floats diff --git a/utils/pl/@left-menu.texy b/utils/pl/@left-menu.texy index e9c10fbdf0..2cd09d7774 100644 --- a/utils/pl/@left-menu.texy +++ b/utils/pl/@left-menu.texy @@ -8,6 +8,7 @@ Pakiet Nette/utils - [JSON |JSON] - [Losowe ciągi |random] - [Obrazy |images] +- [Iterables |iterables] - [Paginator |paginator] - [Refleksja w PHP |reflection] - [Rodzaje PHP |type] diff --git a/utils/pl/arrays.texy b/utils/pl/arrays.texy index 2ca6c6d02d..23f50f2380 100644 --- a/utils/pl/arrays.texy +++ b/utils/pl/arrays.texy @@ -15,7 +15,7 @@ composer require nette/utils Tablice .[#toc-arrays] ====================== -[api:Nette\Utils\Arrays] jest klasą statyczną zawierającą przydatne funkcje do pracy z tablicami. +[api:Nette\Utils\Arrays] to statyczna klasa, która zawiera kilka przydatnych funkcji tablicowych. Jej odpowiednikiem dla iteratorów jest [Nette\Utils\Iterables |iterables]. Poniższe przykłady zakładają, że alias został utworzony: @@ -76,10 +76,10 @@ Arrays::contains(['1', false], 1); // false ``` -every(iterable $array, callable $callback): bool .[method] ----------------------------------------------------------- +every(array $array, callable $predicate): bool .[method] +-------------------------------------------------------- -Testuje czy wszystkie elementy w tablicy przechodzą test zaimplementowany w `$callback` z podpisem `function ($value, $key, array $array): bool`. +Testuje czy wszystkie elementy w tablicy przechodzą test zaimplementowany w `$predicate` z podpisem `function ($value, $key, array $array): bool`. ```php $array = [1, 30, 39, 29, 10, 13]; @@ -90,16 +90,52 @@ $res = Arrays::every($array, $isBelowThreshold); // true Zobacz [some() |#some]. -first(array $array): mixed .[method] ------------------------------------- +filter(array $array, callable $predicate): array .[method]{data-version:4.0.4} +------------------------------------------------------------------------------ + +Zwraca nową tablicę zawierającą wszystkie pary klucz-wartość pasujące do podanego `$predicate`. Wywołanie zwrotne ma sygnaturę `function ($value, int|string $key, array $array): bool`. + +```php +Arrays::filter( + ['a' => 1, 'b' => 2, 'c' => 3], + fn($v) => $v < 3, +); +// ['a' => 1, 'b' => 2] +``` + + +first(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------- + +Zwraca pierwszy element (pasujący do określonego predykatu, jeśli został podany). Jeśli nie ma takiego elementu, zwraca wynik wywołania `$else` lub null. +Funkcja `$predicate` ma sygnaturę `function ($value, int|string $key, array $array): bool`. + +W przeciwieństwie do `reset()` nie zmienia wewnętrznego wskaźnika. Parametry `$predicate` i `$else` istnieją od wersji 4.0.4. + +```php +Arrays::first([1, 2, 3]); // 1 +Arrays::first([1, 2, 3], fn($v) => $v > 2); // 3 +Arrays::first([]); // null +Arrays::first([], else: fn() => false); // false +``` -Zwraca pierwszy wpis z tablicy lub null jeśli tablica jest pusta. Nie zmienia wewnętrznego wskaźnika w przeciwieństwie do `reset()`. +Zobacz [last() |#last()]. + + +firstKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4} +------------------------------------------------------------------------------------------------ + +Zwraca klucz pierwszego elementu (pasującego do określonego predykatu, jeśli został podany) lub null, jeśli nie ma takiego elementu. Funkcja `$predicate` ma sygnaturę `function ($value, int|string $key, array $array): bool`. ```php -Arrays::first([1, 2, 3]); // 1 -Arrays::first([]); // null +Arrays::firstKey([1, 2, 3]); // 0 +Arrays::firstKey([1, 2, 3], fn($v) => $v > 2); // 2 +Arrays::firstKey(['a' => 1, 'b' => 2]); // 'a' +Arrays::firstKey([]); // null ``` +Zobacz [lastKey() |#lastKey()]. + flatten(array $array, bool $preserveKeys=false): array .[method] ---------------------------------------------------------------- @@ -229,21 +265,43 @@ Arrays::isList(['a' => 1, 'b' => 2]); // false ``` -last(array $array): mixed .[method] ------------------------------------ +last(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------ + +Zwraca ostatni element (pasujący do określonego predykatu, jeśli został podany). Jeśli nie ma takiego elementu, zwraca wynik wywołania `$else` lub null. +Funkcja `$predicate` ma sygnaturę `function ($value, int|string $key, array $array): bool`. + +W przeciwieństwie do `end()` nie zmienia wewnętrznego wskaźnika. Parametry `$predicate` i `$else` istnieją od wersji 4.0.4. + +```php +Arrays::last([1, 2, 3]); // 3 +Arrays::last([1, 2, 3], fn($v) => $v < 3); // 2 +Arrays::last([]); // null +Arrays::last([], else: fn() => false); // false +``` + +Zobacz [first() |#first()]. + -Zwraca ostatni wpis tablicy lub null jeśli tablica jest pusta. Nie zmienia wewnętrznego wskaźnika w przeciwieństwie do `end()`. +lastKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4} +----------------------------------------------------------------------------------------------- + +Zwraca klucz ostatniego elementu (pasującego do określonego predykatu, jeśli został podany) lub null, jeśli nie ma takiego elementu. Funkcja `$predicate` ma sygnaturę `function ($value, int|string $key, array $array): bool`. ```php -Arrays::last([1, 2, 3]); // 3 -Arrays::last([]); // null +Arrays::lastKey([1, 2, 3]); // 2 +Arrays::lastKey([1, 2, 3], fn($v) => $v < 3); // 1 +Arrays::lastKey(['a' => 1, 'b' => 2]); // 'b' +Arrays::lastKey([]); // null ``` +Zobacz [firstKey() |#firstKey()]. + -map(iterable $array, callable $callback): array .[method] +map(array $array, callable $transformer): array .[method] --------------------------------------------------------- -Wywołuje `$callback` na wszystkich elementach tablicy i zwraca tablicę wartości zwrotnych. Callback ma podpis `function ($value, $key, array $array): bool`. +Wywołuje `$transformer` na wszystkich elementach tablicy i zwraca tablicę wartości zwrotnych. Callback ma podpis `function ($value, $key, array $array): bool`. ```php $array = ['foo', 'bar', 'baz']; @@ -325,10 +383,10 @@ $position = Arrays::getKeyOffset($array, 'not-exists'); // vrátí null ``` -some(iterable $array, callable $callback): bool .[method] ---------------------------------------------------------- +some(array $array, callable $predicate): bool .[method] +------------------------------------------------------- -Testuje czy przynajmniej jeden element w tablicy przechodzi test zaimplementowany w `$callback` z podpisem `function ($value, $key, array $array): bool`. +Testuje czy przynajmniej jeden element w tablicy przechodzi test zaimplementowany w `$predicate` z podpisem `function ($value, $key, array $array): bool`. ```php $array = [1, 2, 3, 4]; diff --git a/utils/pl/images.texy b/utils/pl/images.texy index c21623a869..077a3e652e 100644 --- a/utils/pl/images.texy +++ b/utils/pl/images.texy @@ -300,6 +300,11 @@ static isTypeSupported(int $type): bool .[method] Określa, czy dany [typ |#Formats] obrazu jest obsługiwany. +static getSupportedTypes(): array .[method]{data-version:4.0.4} +--------------------------------------------------------------- +Zwraca tablicę obsługiwanych typów obrazów (stałe `ImageType::XXX`). + + static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method] ------------------------------------------------------------------------------------------------------------------------ Oblicza wymiary prostokąta otaczającego tekst o określonej czcionce i rozmiarze. Zwraca tablicę asocjacyjną zawierającą klucze `left`, `top`, `width`, `height`. Lewy margines może być ujemny, jeśli tekst zaczyna się od lewego nawisu. diff --git a/utils/pl/iterables.texy b/utils/pl/iterables.texy new file mode 100644 index 0000000000..6b9b3718ff --- /dev/null +++ b/utils/pl/iterables.texy @@ -0,0 +1,119 @@ +Funkcje iteratora +***************** + +.[perex]{data-version:4.0.4} +[api:Nette\Utils\Iterables] to statyczna klasa z funkcjami do pracy z iteratorami. Jej odpowiednikiem dla tablic jest [Nette\Utils\Arrays |arrays]. + + +Instalacja: + +```shell +composer require nette/utils +``` + +Wszystkie przykłady zakładają utworzenie aliasu: + +```php +use Nette\Utils\Iterables; +``` + + +contains(iterable $iterable, $value): bool .[method] +---------------------------------------------------- + +Sprawdza obecność wartości w iteratorze. Używa ścisłego porównania (`===`). + +```php +Iterables::contains(new ArrayIterator([1, 2, 3]), 1); // true +Iterables::contains(new ArrayIterator([1, 2, 3]), '1'); // false +``` + + +containsKey(iterable $iterable, $value): bool .[method] +------------------------------------------------------- + +Sprawdza obecność klucza w iteratorze. Używa ścisłego porównania (`===`). + +```php +Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0); // true +Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4); // false +``` + + +every(iterable $iterable, callable $predicate): bool .[method] +-------------------------------------------------------------- + +Sprawdza, czy wszystkie elementy iteratora przechodzą test zaimplementowany w `$predicate` z podpisem `function ($value, $key, iterable $iterable): bool`. + +```php +$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]); +$isBelowThreshold = fn($value) => $value < 40; +$res = Iterables::every($iterator, $isBelowThreshold); // true +``` + +Zobacz [some() |#some()]. + + +filter(iterable $iterable, callable $predicate): Generator .[method] +-------------------------------------------------------------------- + +Iterator filtrujący elementy zgodnie z predykatem. Predykat ma sygnaturę `function ($value, $key, iterable $iterable): bool`. Zachowuje oryginalne klucze. + +```php +$iterator = new ArrayIterator([1, 2, 3]); +$iterator = Iterables::filter($iterator, fn($v) => $v < 3); +// 1, 2 +``` + + +first(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------------- + +Zwraca pierwszy element (pasujący do predykatu, jeśli został określony). Jeśli taki element nie istnieje, zwraca wynik wywołania `$else` lub null. +Parametr `$predicate` ma sygnaturę `function ($value, $key, iterable $iterable): bool`. + +```php +Iterables::first(new ArrayIterator([1, 2, 3])); // 1 +Iterables::first(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 3 +Iterables::first(new ArrayIterator([])); // null +Iterables::first(new ArrayIterator([]), else: fn() => false); // false +``` + + +firstKey(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method] +---------------------------------------------------------------------------------------------- + +Zwraca klucz pierwszego elementu (pasującego do predykatu, jeśli został określony). Jeśli taki element nie istnieje, zwraca wynik wywołania `$else` lub wartość null. Predykat ma sygnaturę `function ($value, $key, iterable $iterable): bool`. + +```php +Iterables::firstKey(new ArrayIterator([1, 2, 3])); // 0 +Iterables::firstKey(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 2 +Iterables::firstKey(new ArrayIterator(['a' => 1, 'b' => 2])); // 'a' +Iterables::firstKey(new ArrayIterator([])); // null +``` + + +map(iterable $iterable, callable $transformer): array .[method] +--------------------------------------------------------------- + +Iterator, który przekształca wartości poprzez wywołanie `$transformer`. Ma sygnaturę `function ($value, $key, iterable $iterable): bool`. Zachowuje oryginalne klucze. + +```php +$iterator = new ArrayIterator([1, 2, 3]); +$iterator = Iterables::map($iterator, fn($v) => $v * 2); +// 2, 4, 6 +``` + + +some(iterable $iterable, callable $predicate): bool .[method] +------------------------------------------------------------- + +Sprawdza, czy co najmniej jeden element iteratora przechodzi test zaimplementowany w `$predicate` z podpisem `function ($value, $key, iterable $iterable): bool`. + +```php +$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]); +$isEven = fn($value) => $value % 2 === 0; +$res = Iterables::some($iterator, $isEven); // true +``` + +Zobacz [every() |#every()]. diff --git a/utils/pt/@home.texy b/utils/pt/@home.texy index 46bff91082..984915289e 100644 --- a/utils/pt/@home.texy +++ b/utils/pt/@home.texy @@ -13,6 +13,7 @@ No pacote `nette/utils` você encontrará um conjunto de aulas úteis para o uso | [Ajudantes |helpers] | Nette\Utils\Helpers | [Elementos HTML |HTML Elements] | Nette\Utils\Html | [Imagens |Images] | Nette\Utils\Image +| [Iterables |iterables] | Nette\Utils\Iterables | [JSON |JSON] | Nette\Utils\Json | [Paginador de Paginadores |paginator] | Nette\Utils\Paginator | [Reflexão PHP Ref |reflection] | Nette\Utils\Reflection diff --git a/utils/pt/@left-menu.texy b/utils/pt/@left-menu.texy index 83178cea74..041f24a015 100644 --- a/utils/pt/@left-menu.texy +++ b/utils/pt/@left-menu.texy @@ -8,6 +8,7 @@ Pacote nette/utils - [Ajudantes |helpers] - [Elementos HTML |HTML Elements] - [Imagens |Images] +- [Iteráveis |iterables] - [JSON |JSON] - [Paginador |paginator] - [Cordas Aleatórias |random] diff --git a/utils/pt/arrays.texy b/utils/pt/arrays.texy index 2b08aa82f7..142ccc6ee3 100644 --- a/utils/pt/arrays.texy +++ b/utils/pt/arrays.texy @@ -15,7 +15,7 @@ composer require nette/utils Arrays .[#toc-arrays] ===================== -[api:Nette\Utils\Arrays] é uma classe estática, que contém um punhado de funções de matriz úteis. +[api:Nette\Utils\Arrays] é uma classe estática que contém um punhado de funções úteis de matriz. Seu equivalente para iteradores é [Nette\Utils\Iterables |iterables]. Os exemplos a seguir assumem que a seguinte classe está definida: @@ -76,8 +76,8 @@ Arrays::contains(['1', false], 1); // false ``` -every(iterable $array, callable $callback): bool .[method] ----------------------------------------------------------- +every(array $array, callable $predicate): bool .[method] +-------------------------------------------------------- Testa se todos os elementos da matriz passam no teste implementado pela função fornecida, que tem a assinatura `function ($value, $key, array $array): bool`. @@ -90,16 +90,52 @@ $res = Arrays::every($array, $isBelowThreshold); // true Veja [algumas() |#some()]. -first(array $array): mixed .[method] ------------------------------------- +filter(array $array, callable $predicate): array .[method]{data-version:4.0.4} +------------------------------------------------------------------------------ + +Retorna uma nova matriz contendo todos os pares de valores-chave que correspondem ao endereço `$predicate` fornecido. O retorno de chamada tem a assinatura `function ($value, int|string $key, array $array): bool`. + +```php +Arrays::filter( + ['a' => 1, 'b' => 2, 'c' => 3], + fn($v) => $v < 3, +); +// ['a' => 1, 'b' => 2] +``` + + +first(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------- + +Retorna o primeiro item (que corresponde ao predicado especificado, se fornecido). Se não houver tal item, ele retorna o resultado da invocação de `$else` ou nulo. +O `$predicate` tem a assinatura `function ($value, int|string $key, array $array): bool`. + +Ele não altera o ponteiro interno, ao contrário de `reset()`. Os parâmetros `$predicate` e `$else` existem desde a versão 4.0.4. + +```php +Arrays::first([1, 2, 3]); // 1 +Arrays::first([1, 2, 3], fn($v) => $v > 2); // 3 +Arrays::first([]); // null +Arrays::first([], else: fn() => false); // false +``` -Devolve o primeiro item da matriz ou nulo se a matriz estiver vazia. Ele não muda o ponteiro interno ao contrário de `reset()`. +Consulte [last() |#last()]. + + +firstKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4} +------------------------------------------------------------------------------------------------ + +Retorna a chave do primeiro item (que corresponde ao predicado especificado, se fornecido) ou nula se não houver tal item. O `$predicate` tem a assinatura `function ($value, int|string $key, array $array): bool`. ```php -Arrays::first([1, 2, 3]); // 1 -Arrays::first([]); // null +Arrays::firstKey([1, 2, 3]); // 0 +Arrays::firstKey([1, 2, 3], fn($v) => $v > 2); // 2 +Arrays::firstKey(['a' => 1, 'b' => 2]); // 'a' +Arrays::firstKey([]); // null ``` +Consulte [lastKey() |#lastKey()]. + flatten(array $array, bool $preserveKeys=false): array .[method] ---------------------------------------------------------------- @@ -229,21 +265,43 @@ Arrays::isList(['a' => 1, 'b' => 2]); // false ``` -last(array $array): mixed .[method] ------------------------------------ +last(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------ + +Retorna o último item (que corresponde ao predicado especificado, se fornecido). Se não houver tal item, ele retorna o resultado da invocação de `$else` ou nulo. +O `$predicate` tem a assinatura `function ($value, int|string $key, array $array): bool`. + +Ele não altera o ponteiro interno, ao contrário de `end()`. Os parâmetros `$predicate` e `$else` existem desde a versão 4.0.4. + +```php +Arrays::last([1, 2, 3]); // 3 +Arrays::last([1, 2, 3], fn($v) => $v < 3); // 2 +Arrays::last([]); // null +Arrays::last([], else: fn() => false); // false +``` + +Consulte [first() |#first()]. + -Devolve o último item da matriz ou nulo se a matriz estiver vazia. Ele não muda o ponteiro interno ao contrário de `end()`. +lastKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4} +----------------------------------------------------------------------------------------------- + +Retorna a chave do último item (que corresponde ao predicado especificado, se fornecido) ou nula se não houver tal item. O `$predicate` tem a assinatura `function ($value, int|string $key, array $array): bool`. ```php -Arrays::last([1, 2, 3]); // 3 -Arrays::last([]); // null +Arrays::lastKey([1, 2, 3]); // 2 +Arrays::lastKey([1, 2, 3], fn($v) => $v < 3); // 1 +Arrays::lastKey(['a' => 1, 'b' => 2]); // 'b' +Arrays::lastKey([]); // null ``` +Consulte [firstKey() |#firstKey()]. + -map(iterable $array, callable $callback): array .[method] +map(array $array, callable $transformer): array .[method] --------------------------------------------------------- -Liga para `$callback` sobre todos os elementos da matriz e retorna a matriz de valores de retorno. A chamada de retorno tem a assinatura `function ($value, $key, array $array): bool`. +Liga para `$transformer` sobre todos os elementos da matriz e retorna a matriz de valores de retorno. A chamada de retorno tem a assinatura `function ($value, $key, array $array): bool`. ```php $array = ['foo', 'bar', 'baz']; @@ -325,8 +383,8 @@ $position = Arrays::getKeyOffset($array, 'not-exists'); // returns null ``` -some(iterable $array, callable $callback): bool .[method] ---------------------------------------------------------- +some(array $array, callable $predicate): bool .[method] +------------------------------------------------------- Testa se pelo menos um elemento da matriz passa no teste implementado pela callback fornecida com a assinatura `function ($value, $key, array $array): bool`. diff --git a/utils/pt/images.texy b/utils/pt/images.texy index 20a1f45b09..a15b4ccf43 100644 --- a/utils/pt/images.texy +++ b/utils/pt/images.texy @@ -300,6 +300,11 @@ static isTypeSupported(int $type): bool .[method] Determina se o [tipo |#Formats] de imagem fornecido é compatível. +static getSupportedTypes(): array .[method]{data-version:4.0.4} +--------------------------------------------------------------- +Retorna uma matriz de tipos de imagens compatíveis (constantes `ImageType::XXX`). + + static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method] ------------------------------------------------------------------------------------------------------------------------ Calcula as dimensões do retângulo que envolve o texto em uma fonte e tamanho especificados. Retorna uma matriz associativa contendo as chaves `left`, `top`, `width`, `height`. A margem esquerda pode ser negativa se o texto começar com uma saliência à esquerda. diff --git a/utils/pt/iterables.texy b/utils/pt/iterables.texy new file mode 100644 index 0000000000..30bea5ca1f --- /dev/null +++ b/utils/pt/iterables.texy @@ -0,0 +1,119 @@ +Funções de iterador +******************* + +.[perex]{data-version:4.0.4} +[api:Nette\Utils\Iterables] é uma classe estática com funções para trabalhar com iteradores. Sua contraparte para matrizes é [Nette\Utils\Arrays |arrays]. + + +Instalação: + +```shell +composer require nette/utils +``` + +Todos os exemplos pressupõem a criação de um alias: + +```php +use Nette\Utils\Iterables; +``` + + +contains(iterable $iterable, $value): bool .[method] +---------------------------------------------------- + +Testa a presença de um valor no iterador. Usa comparação rigorosa (`===`). + +```php +Iterables::contains(new ArrayIterator([1, 2, 3]), 1); // true +Iterables::contains(new ArrayIterator([1, 2, 3]), '1'); // false +``` + + +containsKey(iterable $iterable, $value): bool .[method] +------------------------------------------------------- + +Testa a presença de uma chave no iterador. Usa comparação rigorosa (`===`). + +```php +Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0); // true +Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4); // false +``` + + +every(iterable $iterable, callable $predicate): bool .[method] +-------------------------------------------------------------- + +Testa se todos os elementos do iterador passam em um teste implementado em `$predicate` com a assinatura `function ($value, $key, iterable $iterable): bool`. + +```php +$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]); +$isBelowThreshold = fn($value) => $value < 40; +$res = Iterables::every($iterator, $isBelowThreshold); // true +``` + +Consulte [some() |#some()]. + + +filter(iterable $iterable, callable $predicate): Generator .[method] +-------------------------------------------------------------------- + +Iterador que filtra elementos de acordo com um predicado. O predicado tem a assinatura `function ($value, $key, iterable $iterable): bool`. Mantém as chaves originais. + +```php +$iterator = new ArrayIterator([1, 2, 3]); +$iterator = Iterables::filter($iterator, fn($v) => $v < 3); +// 1, 2 +``` + + +first(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------------- + +Retorna o primeiro item (que corresponde ao predicado, se especificado). Se esse item não existir, retorna o resultado da chamada para `$else` ou nulo. +O parâmetro `$predicate` tem a assinatura `function ($value, $key, iterable $iterable): bool`. + +```php +Iterables::first(new ArrayIterator([1, 2, 3])); // 1 +Iterables::first(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 3 +Iterables::first(new ArrayIterator([])); // null +Iterables::first(new ArrayIterator([]), else: fn() => false); // false +``` + + +firstKey(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method] +---------------------------------------------------------------------------------------------- + +Retorna a chave do primeiro item (que corresponde ao predicado, se especificado). Se esse item não existir, retorna o resultado da chamada para `$else` ou nulo. O predicado tem a assinatura `function ($value, $key, iterable $iterable): bool`. + +```php +Iterables::firstKey(new ArrayIterator([1, 2, 3])); // 0 +Iterables::firstKey(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 2 +Iterables::firstKey(new ArrayIterator(['a' => 1, 'b' => 2])); // 'a' +Iterables::firstKey(new ArrayIterator([])); // null +``` + + +map(iterable $iterable, callable $transformer): array .[method] +--------------------------------------------------------------- + +Iterador que transforma valores chamando `$transformer`. Ele tem a assinatura `function ($value, $key, iterable $iterable): bool`. Mantém as chaves originais. + +```php +$iterator = new ArrayIterator([1, 2, 3]); +$iterator = Iterables::map($iterator, fn($v) => $v * 2); +// 2, 4, 6 +``` + + +some(iterable $iterable, callable $predicate): bool .[method] +------------------------------------------------------------- + +Testa se pelo menos um elemento do iterador passa em um teste implementado em `$predicate` com a assinatura `function ($value, $key, iterable $iterable): bool`. + +```php +$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]); +$isEven = fn($value) => $value % 2 === 0; +$res = Iterables::some($iterator, $isEven); // true +``` + +Consulte [every() |#every()]. diff --git a/utils/ro/@home.texy b/utils/ro/@home.texy index c4beaa362e..98e5316be5 100644 --- a/utils/ro/@home.texy +++ b/utils/ro/@home.texy @@ -13,6 +13,7 @@ Utilități [Ajutoare |helpers] | Helpers | Nette\Utils\Helpers | [Elemente HTML |HTML Elements] | Nette\Utils\Html [Imagini |Images] | Imagini | Nette\Utils\Image +[Iterables |iterables] | Iterables | Nette\Utils\Iterables [JSON |JSON] | JSON | Nette\Utils\Json | [Paginator |paginator] | Nette\Utils\Paginator [PHP Reflection |reflection] | [PHP |reflection] Reflection | Nette\Utils\Reflection diff --git a/utils/ro/@left-menu.texy b/utils/ro/@left-menu.texy index 8b2e3fc881..5218142956 100644 --- a/utils/ro/@left-menu.texy +++ b/utils/ro/@left-menu.texy @@ -8,6 +8,7 @@ Pachetul nette/utils - [Ajutători |helpers] - [Elemente HTML |HTML Elements] - [Imagini |Images] +- [Iterabile |iterables] - [JSON |JSON] - [Paginator |paginator] - [Șiruri aleatorii |random] diff --git a/utils/ro/arrays.texy b/utils/ro/arrays.texy index 82d9789065..82a2e3770e 100644 --- a/utils/ro/arrays.texy +++ b/utils/ro/arrays.texy @@ -15,7 +15,7 @@ composer require nette/utils Array-uri .[#toc-arrays] ======================== -[api:Nette\Utils\Arrays] este o clasă statică, care conține o serie de funcții practice de matrice. +[api:Nette\Utils\Arrays] este o clasă statică, care conține o serie de funcții practice de matrice. Echivalentul său pentru iteratori este [Nette\Utils\Iterables |iterables]. Exemplele următoare presupun că este definit următorul alias de clasă: @@ -76,8 +76,8 @@ Arrays::contains(['1', false], 1); // false ``` -every(iterable $array, callable $callback): bool .[method] ----------------------------------------------------------- +every(array $array, callable $predicate): bool .[method] +-------------------------------------------------------- Testează dacă toate elementele din matrice trec testul implementat de funcția furnizată, care are semnătura `function ($value, $key, array $array): bool`. @@ -90,16 +90,52 @@ $res = Arrays::every($array, $isBelowThreshold); // true A se vedea [some() |#some()]. -first(array $array): mixed .[method] ------------------------------------- +filter(array $array, callable $predicate): array .[method]{data-version:4.0.4} +------------------------------------------------------------------------------ + +Returnează o nouă matrice care conține toate perechile cheie-valoare care corespund cu `$predicate`. Callback-ul are semnătura `function ($value, int|string $key, array $array): bool`. + +```php +Arrays::filter( + ['a' => 1, 'b' => 2, 'c' => 3], + fn($v) => $v < 3, +); +// ['a' => 1, 'b' => 2] +``` + + +first(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------- + +Returnează primul element (care corespunde predicatului specificat, dacă este dat). Dacă nu există un astfel de element, se returnează rezultatul invocării `$else` sau null. + `$predicate` are semnătura `function ($value, int|string $key, array $array): bool`. + +Nu modifică pointerul intern, spre deosebire de `reset()`. Parametrii `$predicate` și `$else` există începând cu versiunea 4.0.4. + +```php +Arrays::first([1, 2, 3]); // 1 +Arrays::first([1, 2, 3], fn($v) => $v > 2); // 3 +Arrays::first([]); // null +Arrays::first([], else: fn() => false); // false +``` -Returnează primul element din tablou sau nul dacă tabloul este gol. Nu modifică pointerul intern, spre deosebire de `reset()`. +A se vedea [last() |#last()]. + + +firstKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4} +------------------------------------------------------------------------------------------------ + +Returnează cheia primului element (care corespunde predicatului specificat, dacă este dat) sau nulă dacă nu există un astfel de element. `$predicate` are semnătura `function ($value, int|string $key, array $array): bool`. ```php -Arrays::first([1, 2, 3]); // 1 -Arrays::first([]); // null +Arrays::firstKey([1, 2, 3]); // 0 +Arrays::firstKey([1, 2, 3], fn($v) => $v > 2); // 2 +Arrays::firstKey(['a' => 1, 'b' => 2]); // 'a' +Arrays::firstKey([]); // null ``` +A se vedea [lastKey() |#lastKey()]. + flatten(array $array, bool $preserveKeys=false): array .[method] ---------------------------------------------------------------- @@ -229,21 +265,43 @@ Arrays::isList(['a' => 1, 'b' => 2]); // false ``` -last(array $array): mixed .[method] ------------------------------------ +last(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------ + +Returnează ultimul element (care corespunde predicatului specificat, dacă este dat). Dacă nu există un astfel de element, se returnează rezultatul invocării `$else` sau null. + `$predicate` are semnătura `function ($value, int|string $key, array $array): bool`. + +Nu modifică pointerul intern, spre deosebire de `end()`. Parametrii `$predicate` și `$else` există începând cu versiunea 4.0.4. + +```php +Arrays::last([1, 2, 3]); // 3 +Arrays::last([1, 2, 3], fn($v) => $v < 3); // 2 +Arrays::last([]); // null +Arrays::last([], else: fn() => false); // false +``` + +A se vedea [first() |#first()]. + -Returnează ultimul element din tablou sau zero dacă tabloul este gol. Spre deosebire de `end()`, nu modifică pointerul intern. +lastKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4} +----------------------------------------------------------------------------------------------- + +Returnează cheia ultimului element (care corespunde predicatului specificat, dacă este dat) sau nulă dacă nu există un astfel de element. `$predicate` are semnătura `function ($value, int|string $key, array $array): bool`. ```php -Arrays::last([1, 2, 3]); // 3 -Arrays::last([]); // null +Arrays::lastKey([1, 2, 3]); // 2 +Arrays::lastKey([1, 2, 3], fn($v) => $v < 3); // 1 +Arrays::lastKey(['a' => 1, 'b' => 2]); // 'b' +Arrays::lastKey([]); // null ``` +A se vedea [firstKey() |#firstKey()]. + -map(iterable $array, callable $callback): array .[method] +map(array $array, callable $transformer): array .[method] --------------------------------------------------------- -Solicită `$callback` pentru toate elementele din matrice și returnează matricea de valori de returnare. Callback-ul are semnătura `function ($value, $key, array $array): bool`. +Solicită `$transformer` pentru toate elementele din matrice și returnează matricea de valori de returnare. Callback-ul are semnătura `function ($value, $key, array $array): bool`. ```php $array = ['foo', 'bar', 'baz']; @@ -325,8 +383,8 @@ $position = Arrays::getKeyOffset($array, 'not-exists'); // returnează null ``` -some(iterable $array, callable $callback): bool .[method] ---------------------------------------------------------- +some(array $array, callable $predicate): bool .[method] +------------------------------------------------------- Testează dacă cel puțin un element din matrice trece testul implementat de callback-ul furnizat cu semnătura `function ($value, $key, array $array): bool`. diff --git a/utils/ro/images.texy b/utils/ro/images.texy index 0444c318a0..ba0a16083d 100644 --- a/utils/ro/images.texy +++ b/utils/ro/images.texy @@ -300,6 +300,11 @@ static isTypeSupported(int $type): bool .[method] Determină dacă [tipul de |#Formats] imagine dat este acceptat. +static getSupportedTypes(): array .[method]{data-version:4.0.4} +--------------------------------------------------------------- +Returnează o matrice de tipuri de imagini acceptate (constante `ImageType::XXX`). + + static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method] ------------------------------------------------------------------------------------------------------------------------ Calculează dimensiunile dreptunghiului care înconjoară textul cu un font și o dimensiune specificate. Se returnează un tablou asociativ care conține cheile `left`, `top`, `width`, `height`. Marja stângă poate fi negativă dacă textul începe cu o depășire la stânga. diff --git a/utils/ro/iterables.texy b/utils/ro/iterables.texy new file mode 100644 index 0000000000..413b1f6ec2 --- /dev/null +++ b/utils/ro/iterables.texy @@ -0,0 +1,119 @@ +Funcții de iterator +******************* + +.[perex]{data-version:4.0.4} +[api:Nette\Utils\Iterables] este o clasă statică cu funcții pentru lucrul cu iteratori. Omologul său pentru array-uri este [Nette\Utils\Arrays |arrays]. + + +Instalare: + +```shell +composer require nette/utils +``` + +Toate exemplele presupun crearea unui alias: + +```php +use Nette\Utils\Iterables; +``` + + +contains(iterable $iterable, $value): bool .[method] +---------------------------------------------------- + +Testează prezența unei valori în iterator. Utilizează o comparație strictă (`===`). + +```php +Iterables::contains(new ArrayIterator([1, 2, 3]), 1); // true +Iterables::contains(new ArrayIterator([1, 2, 3]), '1'); // false +``` + + +containsKey(iterable $iterable, $value): bool .[method] +------------------------------------------------------- + +Testează prezența unei chei în iterator. Utilizează o comparație strictă (`===`). + +```php +Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0); // true +Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4); // false +``` + + +every(iterable $iterable, callable $predicate): bool .[method] +-------------------------------------------------------------- + +Testează dacă toate elementele iteratorului trec un test implementat în `$predicate` cu semnătura `function ($value, $key, iterable $iterable): bool`. + +```php +$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]); +$isBelowThreshold = fn($value) => $value < 40; +$res = Iterables::every($iterator, $isBelowThreshold); // true +``` + +A se vedea [some() |#some()]. + + +filter(iterable $iterable, callable $predicate): Generator .[method] +-------------------------------------------------------------------- + +Iterator care filtrează elementele în funcție de un predicat. Predicatul are semnătura `function ($value, $key, iterable $iterable): bool`. Păstrează cheile originale. + +```php +$iterator = new ArrayIterator([1, 2, 3]); +$iterator = Iterables::filter($iterator, fn($v) => $v < 3); +// 1, 2 +``` + + +first(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------------- + +Returnează primul element (care corespunde predicatului, dacă este specificat). Dacă nu există un astfel de element, se returnează rezultatul apelării `$else` sau null. +Parametrul `$predicate` are semnătura `function ($value, $key, iterable $iterable): bool`. + +```php +Iterables::first(new ArrayIterator([1, 2, 3])); // 1 +Iterables::first(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 3 +Iterables::first(new ArrayIterator([])); // null +Iterables::first(new ArrayIterator([]), else: fn() => false); // false +``` + + +firstKey(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method] +---------------------------------------------------------------------------------------------- + +Returnează cheia primului element (care corespunde predicatului, dacă este specificat). Dacă nu există un astfel de element, se returnează rezultatul apelării `$else` sau null. Predicatul are semnătura `function ($value, $key, iterable $iterable): bool`. + +```php +Iterables::firstKey(new ArrayIterator([1, 2, 3])); // 0 +Iterables::firstKey(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 2 +Iterables::firstKey(new ArrayIterator(['a' => 1, 'b' => 2])); // 'a' +Iterables::firstKey(new ArrayIterator([])); // null +``` + + +map(iterable $iterable, callable $transformer): array .[method] +--------------------------------------------------------------- + +Iterator care transformă valorile prin apelarea `$transformer`. Are semnătura `function ($value, $key, iterable $iterable): bool`. Păstrează cheile originale. + +```php +$iterator = new ArrayIterator([1, 2, 3]); +$iterator = Iterables::map($iterator, fn($v) => $v * 2); +// 2, 4, 6 +``` + + +some(iterable $iterable, callable $predicate): bool .[method] +------------------------------------------------------------- + +Testează dacă cel puțin un element al iteratorului trece un test implementat în `$predicate` cu semnătura `function ($value, $key, iterable $iterable): bool`. + +```php +$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]); +$isEven = fn($value) => $value % 2 === 0; +$res = Iterables::some($iterator, $isEven); // true +``` + +A se vedea [every() |#every()]. diff --git a/utils/ru/@home.texy b/utils/ru/@home.texy index 9a92b30218..c3f516b34f 100644 --- a/utils/ru/@home.texy +++ b/utils/ru/@home.texy @@ -13,6 +13,7 @@ | [Изображения |images] | Nette\Utils\Image | [Пагинация |paginator] | Nette\Utils\Paginator | [Парсинг и генерация JSON |json] | Nette\Utils\Json +| [Iterables |iterables] | Nette\Utils\Iterables | [Поле |arrays] | Nette\Utils\Arrays | [Строки |strings] | Nette\Utils\Strings | [Типы |type] | Nette\Utils\Type diff --git a/utils/ru/@left-menu.texy b/utils/ru/@left-menu.texy index 94fce6f58f..62c1662dd5 100644 --- a/utils/ru/@left-menu.texy +++ b/utils/ru/@left-menu.texy @@ -8,6 +8,7 @@ - [Изображения |images] - [Обратные вызовы |callback] - [Пагинатор |paginator] +- [Итерабельные таблицы |iterables] - [Поле |arrays] - [Случайные строки |random] - [Строки |strings] diff --git a/utils/ru/arrays.texy b/utils/ru/arrays.texy index ba4e191f21..33326625d0 100644 --- a/utils/ru/arrays.texy +++ b/utils/ru/arrays.texy @@ -15,7 +15,7 @@ composer require nette/utils Массивы .[#toc-arrays] ====================== -[api:Nette\Utils\Arrays] это статический класс, содержащий полезные функции для работы с массивами. +[api:Nette\Utils\Arrays] это статический класс, который содержит несколько удобных функций для работы с массивами. Его эквивалентом для итераторов является [Nette\Utils\Iterables |iterables]. В следующих примерах предполагается, что псевдоним уже создан: @@ -76,10 +76,10 @@ Arrays::contains(['1', false], 1); // false ``` -every(iterable $array, callable $callback): bool .[method] ----------------------------------------------------------- +every(array $array, callable $predicate): bool .[method] +-------------------------------------------------------- -Проверяет, все ли элементы в массиве проходят тест, реализованный в `$callback` с сигнатурой `function ($value, $key, array $array): bool`. +Проверяет, все ли элементы в массиве проходят тест, реализованный в `$predicate` с сигнатурой `function ($value, $key, array $array): bool`. ```php $array = [1, 30, 39, 29, 10, 13]; @@ -90,16 +90,52 @@ $res = Arrays::every($array, $isBelowThreshold); // true См. [some() |#some]. -first(array $array): mixed .[method] ------------------------------------- +filter(array $array, callable $predicate): array .[method]{data-version:4.0.4} +------------------------------------------------------------------------------ + +Возвращает новый массив, содержащий все пары ключ-значение, соответствующие заданному `$predicate`. Обратный вызов имеет сигнатуру `function ($value, int|string $key, array $array): bool`. + +```php +Arrays::filter( + ['a' => 1, 'b' => 2, 'c' => 3], + fn($v) => $v < 3, +); +// ['a' => 1, 'b' => 2] +``` + + +first(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------- + +Возвращает первый элемент (соответствующий указанному предикату, если он задан). Если такого элемента нет, возвращается результат вызова `$else` или null. +Функция `$predicate` имеет сигнатуру `function ($value, int|string $key, array $array): bool`. + +Она не изменяет внутренний указатель, в отличие от `reset()`. Параметры `$predicate` и `$else` существуют с версии 4.0.4. + +```php +Arrays::first([1, 2, 3]); // 1 +Arrays::first([1, 2, 3], fn($v) => $v > 2); // 3 +Arrays::first([]); // null +Arrays::first([], else: fn() => false); // false +``` -Возвращает первую запись из массива или null, если массив пуст. Не изменяет внутренний указатель, в отличие от `reset()`. +См. [last() |#last()]. + + +firstKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4} +------------------------------------------------------------------------------------------------ + +Возвращает ключ первого элемента (соответствующего указанному предикату, если он задан) или null, если такого элемента нет. Ключ `$predicate` имеет сигнатуру `function ($value, int|string $key, array $array): bool`. ```php -Arrays::first([1, 2, 3]); // 1 -Arrays::first([]); // null +Arrays::firstKey([1, 2, 3]); // 0 +Arrays::firstKey([1, 2, 3], fn($v) => $v > 2); // 2 +Arrays::firstKey(['a' => 1, 'b' => 2]); // 'a' +Arrays::firstKey([]); // null ``` +См. [lastKey() |#lastKey()]. + flatten(array $array, bool $preserveKeys=false): array .[method] ---------------------------------------------------------------- @@ -229,21 +265,43 @@ Arrays::isList(['a' => 1, 'b' => 2]); // false ``` -last(array $array): mixed .[method] ------------------------------------ +last(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------ + +Возвращает последний элемент (соответствующий указанному предикату, если он задан). Если такого элемента нет, возвращается результат вызова `$else` или null. +Функция `$predicate` имеет сигнатуру `function ($value, int|string $key, array $array): bool`. + +Она не изменяет внутренний указатель, в отличие от `end()`. Параметры `$predicate` и `$else` существуют с версии 4.0.4. + +```php +Arrays::last([1, 2, 3]); // 3 +Arrays::last([1, 2, 3], fn($v) => $v < 3); // 2 +Arrays::last([]); // null +Arrays::last([], else: fn() => false); // false +``` + +См. раздел [first() |#first()]. + -Возвращает последнюю запись массива или null, если массив пуст. Не изменяет внутренний указатель, в отличие от `end()`. +lastKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4} +----------------------------------------------------------------------------------------------- + +Возвращает ключ последнего элемента (соответствующего указанному предикату, если он задан) или null, если такого элемента нет. Ключ `$predicate` имеет сигнатуру `function ($value, int|string $key, array $array): bool`. ```php -Arrays::last([1, 2, 3]); // 3 -Arrays::last([]); // null +Arrays::lastKey([1, 2, 3]); // 2 +Arrays::lastKey([1, 2, 3], fn($v) => $v < 3); // 1 +Arrays::lastKey(['a' => 1, 'b' => 2]); // 'b' +Arrays::lastKey([]); // null ``` +См. [firstKey() |#firstKey()]. + -map(iterable $array, callable $callback): array .[method] +map(array $array, callable $transformer): array .[method] --------------------------------------------------------- -Вызывает `$callback` на всех элементах массива и возвращает массив возвращаемых значений. Обратный вызов имеет сигнатуру `function ($value, $key, array $array): bool`. +Вызывает `$transformer` на всех элементах массива и возвращает массив возвращаемых значений. Обратный вызов имеет сигнатуру `function ($value, $key, array $array): bool`. ```php $array = ['foo', 'bar', 'baz']; @@ -325,10 +383,10 @@ $position = Arrays::getKeyOffset($array, 'not-exists'); // vrátí null ``` -some(iterable $array, callable $callback): bool .[method] ---------------------------------------------------------- +some(array $array, callable $predicate): bool .[method] +------------------------------------------------------- -Проверяет, проходит ли хотя бы один элемент в массиве тест, реализованный в `$callback` с сигнатурой `function ($value, $key, array $array): bool`. +Проверяет, проходит ли хотя бы один элемент в массиве тест, реализованный в `$predicate` с сигнатурой `function ($value, $key, array $array): bool`. ```php $array = [1, 2, 3, 4]; diff --git a/utils/ru/images.texy b/utils/ru/images.texy index e73a3dc303..7a9fe77e4f 100644 --- a/utils/ru/images.texy +++ b/utils/ru/images.texy @@ -300,6 +300,11 @@ static isTypeSupported(int $type): bool .[method] Определяет, поддерживается ли заданный [тип |#Formats] изображения. +static getSupportedTypes(): array .[method]{data-version:4.0.4} +--------------------------------------------------------------- +Возвращает массив поддерживаемых типов изображений (константы `ImageType::XXX`). + + static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method] ------------------------------------------------------------------------------------------------------------------------ Вычисляет размеры прямоугольника, в который заключен текст заданного шрифта и размера. Возвращается ассоциативный массив, содержащий ключи `left`, `top`, `width`, `height`. Левое поле может быть отрицательным, если текст начинается с левого свеса. diff --git a/utils/ru/iterables.texy b/utils/ru/iterables.texy new file mode 100644 index 0000000000..6330be8877 --- /dev/null +++ b/utils/ru/iterables.texy @@ -0,0 +1,119 @@ +Функции итератора +***************** + +.[perex]{data-version:4.0.4} +[api:Nette\Utils\Iterables] это статический класс с функциями для работы с итераторами. Его аналог для массивов - [Nette\Utils\Arrays |arrays]. + + +Установка: + +```shell +composer require nette/utils +``` + +Все примеры предполагают создание псевдонима: + +```php +use Nette\Utils\Iterables; +``` + + +contains(iterable $iterable, $value): bool .[method] +---------------------------------------------------- + +Проверяет наличие значения в итераторе. Используется строгое сравнение (`===`). + +```php +Iterables::contains(new ArrayIterator([1, 2, 3]), 1); // true +Iterables::contains(new ArrayIterator([1, 2, 3]), '1'); // false +``` + + +containsKey(iterable $iterable, $value): bool .[method] +------------------------------------------------------- + +Проверяет наличие ключа в итераторе. Используется строгое сравнение (`===`). + +```php +Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0); // true +Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4); // false +``` + + +every(iterable $iterable, callable $predicate): bool .[method] +-------------------------------------------------------------- + +Проверяет, все ли элементы итератора проходят тест, реализованный в `$predicate` с сигнатурой `function ($value, $key, iterable $iterable): bool`. + +```php +$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]); +$isBelowThreshold = fn($value) => $value < 40; +$res = Iterables::every($iterator, $isBelowThreshold); // true +``` + +См. [some() |#some()]. + + +filter(iterable $iterable, callable $predicate): Generator .[method] +-------------------------------------------------------------------- + +Итератор, который фильтрует элементы в соответствии с предикатом. Предикат имеет сигнатуру `function ($value, $key, iterable $iterable): bool`. Сохраняет исходные ключи. + +```php +$iterator = new ArrayIterator([1, 2, 3]); +$iterator = Iterables::filter($iterator, fn($v) => $v < 3); +// 1, 2 +``` + + +first(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------------- + +Возвращает первый элемент (соответствующий предикату, если он указан). Если такого элемента нет, возвращается результат вызова `$else` или null. +Параметр `$predicate` имеет сигнатуру `function ($value, $key, iterable $iterable): bool`. + +```php +Iterables::first(new ArrayIterator([1, 2, 3])); // 1 +Iterables::first(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 3 +Iterables::first(new ArrayIterator([])); // null +Iterables::first(new ArrayIterator([]), else: fn() => false); // false +``` + + +firstKey(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method] +---------------------------------------------------------------------------------------------- + +Возвращает ключ первого элемента (соответствующего предикату, если он указан). Если такого элемента нет, возвращается результат вызова `$else` или null. Предикат имеет сигнатуру `function ($value, $key, iterable $iterable): bool`. + +```php +Iterables::firstKey(new ArrayIterator([1, 2, 3])); // 0 +Iterables::firstKey(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 2 +Iterables::firstKey(new ArrayIterator(['a' => 1, 'b' => 2])); // 'a' +Iterables::firstKey(new ArrayIterator([])); // null +``` + + +map(iterable $iterable, callable $transformer): array .[method] +--------------------------------------------------------------- + +Итератор, преобразующий значения путем вызова `$transformer`. Имеет сигнатуру `function ($value, $key, iterable $iterable): bool`. Сохраняет исходные ключи. + +```php +$iterator = new ArrayIterator([1, 2, 3]); +$iterator = Iterables::map($iterator, fn($v) => $v * 2); +// 2, 4, 6 +``` + + +some(iterable $iterable, callable $predicate): bool .[method] +------------------------------------------------------------- + +Проверяет, проходит ли хотя бы один элемент итератора тест, реализованный в `$predicate` с подписью `function ($value, $key, iterable $iterable): bool`. + +```php +$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]); +$isEven = fn($value) => $value % 2 === 0; +$res = Iterables::some($iterator, $isEven); // true +``` + +См. [every() |#every()]. diff --git a/utils/sl/@home.texy b/utils/sl/@home.texy index b04f690d17..8e5c925487 100644 --- a/utils/sl/@home.texy +++ b/utils/sl/@home.texy @@ -13,6 +13,7 @@ V paketu `nette/utils` boste našli niz uporabnih razredov za vsakdanjo uporabo: | [Pomočniki |helpers] | Nette\Utils\Helpers | [Elementi HTML |HTML Elements] | Nette\Utils\Html | [Slike |Images] | Nette\Utils\Image +| [Iterables |iterables] | Nette\Utils\Iterables | [JSON |JSON] | Nette\Utils\Json | [Paginator |paginator] | Nette\Utils\Paginator | [PHP Reflection |reflection] | Nette\Utils\Reflection diff --git a/utils/sl/@left-menu.texy b/utils/sl/@left-menu.texy index e9d66c191d..dbd800f038 100644 --- a/utils/sl/@left-menu.texy +++ b/utils/sl/@left-menu.texy @@ -8,6 +8,7 @@ Paket nette/utils - [Pomočniki |helpers] - [Elementi HTML |HTML Elements] - [Slike |Images] +- [Iterables |iterables] - [JSON |JSON] - [Paginator |paginator] - [Naključni nizi |random] diff --git a/utils/sl/arrays.texy b/utils/sl/arrays.texy index 7f042b7ea8..362c4163ac 100644 --- a/utils/sl/arrays.texy +++ b/utils/sl/arrays.texy @@ -15,7 +15,7 @@ composer require nette/utils Mreže .[#toc-arrays] ==================== -[api:Nette\Utils\Arrays] je statični razred, ki vsebuje nekaj priročnih funkcij za polja. +[api:Nette\Utils\Arrays] je statični razred, ki vsebuje nekaj priročnih funkcij za polja. Njegov ekvivalent za iteratorje je [Nette\Utils\Iterables |iterables]. Naslednji primeri predpostavljajo, da je definiran naslednji vzdevek razreda: @@ -76,8 +76,8 @@ Arrays::contains(['1', false], 1); // false ``` -every(iterable $array, callable $callback): bool .[method] ----------------------------------------------------------- +every(array $array, callable $predicate): bool .[method] +-------------------------------------------------------- Preizkusi, ali vsi elementi v polju prestanejo test, ki ga izvaja navedena funkcija s podpisom `function ($value, $key, array $array): bool`. @@ -90,16 +90,52 @@ $res = Arrays::every($array, $isBelowThreshold); // true Glejte [some( |#some()]). -first(array $array): mixed .[method] ------------------------------------- +filter(array $array, callable $predicate): array .[method]{data-version:4.0.4} +------------------------------------------------------------------------------ + +Vrne novo polje, ki vsebuje vse pare ključ-vrednost, ki ustrezajo danemu `$predicate`. Povratni klic ima podpis `function ($value, int|string $key, array $array): bool`. + +```php +Arrays::filter( + ['a' => 1, 'b' => 2, 'c' => 3], + fn($v) => $v < 3, +); +// ['a' => 1, 'b' => 2] +``` + + +first(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------- + +Vrne prvi element (ki ustreza določenemu predikatu, če je podan). Če takega elementa ni, vrne rezultat klica `$else` ali nič. + `$predicate` ima podpis `function ($value, int|string $key, array $array): bool`. + +Za razliko od `reset()` ne spreminja notranjega kazalca. Parametra `$predicate` in `$else` obstajata od različice 4.0.4. + +```php +Arrays::first([1, 2, 3]); // 1 +Arrays::first([1, 2, 3], fn($v) => $v > 2); // 3 +Arrays::first([]); // null +Arrays::first([], else: fn() => false); // false +``` -Vrne prvi element iz polja ali nič, če je polje prazno. Za razliko od `reset()` ne spremeni notranjega kazalca. +Glej [last() |#last()]. + + +firstKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4} +------------------------------------------------------------------------------------------------ + +Vrne ključ prvega elementa (ki ustreza določenemu predikatu, če je podan) ali nič, če takega elementa ni. `$predicate` ima podpis `function ($value, int|string $key, array $array): bool`. ```php -Arrays::first([1, 2, 3]); // 1 -Arrays::first([]); // null +Arrays::firstKey([1, 2, 3]); // 0 +Arrays::firstKey([1, 2, 3], fn($v) => $v > 2); // 2 +Arrays::firstKey(['a' => 1, 'b' => 2]); // 'a' +Arrays::firstKey([]); // null ``` +Glej [lastKey( |#lastKey()]). + flatten(array $array, bool $preserveKeys=false): array .[method] ---------------------------------------------------------------- @@ -229,21 +265,43 @@ Arrays::isList(['a' => 1, 'b' => 2]); // false ``` -last(array $array): mixed .[method] ------------------------------------ +last(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------ + +Vrne zadnji element (ki ustreza določenemu predikatu, če je podan). Če takega elementa ni, vrne rezultat klica `$else` ali nič. + `$predicate` ima podpis `function ($value, int|string $key, array $array): bool`. + +Za razliko od `end()` ne spreminja notranjega kazalca. Parametra `$predicate` in `$else` obstajata od različice 4.0.4. + +```php +Arrays::last([1, 2, 3]); // 3 +Arrays::last([1, 2, 3], fn($v) => $v < 3); // 2 +Arrays::last([]); // null +Arrays::last([], else: fn() => false); // false +``` + +Glej [first( |#first()]). + -Vrne zadnji element iz polja ali nič, če je polje prazno. Za razliko od `end()` ne spremeni notranjega kazalca. +lastKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4} +----------------------------------------------------------------------------------------------- + +Vrne ključ zadnjega elementa (ki ustreza določenemu predikatu, če je podan) ali nič, če takega elementa ni. `$predicate` ima podpis `function ($value, int|string $key, array $array): bool`. ```php -Arrays::last([1, 2, 3]); // 3 -Arrays::last([]); // null +Arrays::lastKey([1, 2, 3]); // 2 +Arrays::lastKey([1, 2, 3], fn($v) => $v < 3); // 1 +Arrays::lastKey(['a' => 1, 'b' => 2]); // 'b' +Arrays::lastKey([]); // null ``` +Glej [firstKey( |#firstKey()]). + -map(iterable $array, callable $callback): array .[method] +map(array $array, callable $transformer): array .[method] --------------------------------------------------------- -Kliče `$callback` na vse elemente v polju in vrne polje vrnjenih vrednosti. Povratni klic ima podpis `function ($value, $key, array $array): bool`. +Kliče `$transformer` na vse elemente v polju in vrne polje vrnjenih vrednosti. Povratni klic ima podpis `function ($value, $key, array $array): bool`. ```php $array = ['foo', 'bar', 'baz']; @@ -325,8 +383,8 @@ $position = Arrays::getKeyOffset($array, 'not-exists'); // vrne nič ``` -some(iterable $array, callable $callback): bool .[method] ---------------------------------------------------------- +some(array $array, callable $predicate): bool .[method] +------------------------------------------------------- Preizkusi, ali vsaj en element v polju prestane test, ki ga izvaja posredovani povratni klic s podpisom `function ($value, $key, array $array): bool`. diff --git a/utils/sl/images.texy b/utils/sl/images.texy index 3af7d1c59d..90f1f83819 100644 --- a/utils/sl/images.texy +++ b/utils/sl/images.texy @@ -300,6 +300,11 @@ static isTypeSupported(int $type): bool .[method] Ugotovi, ali je dana [vrsta |#Formats] slike podprta. +static getSupportedTypes(): array .[method]{data-version:4.0.4} +--------------------------------------------------------------- +Vrne polje podprtih tipov slik (konstante `ImageType::XXX`). + + static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method] ------------------------------------------------------------------------------------------------------------------------ Izračuna dimenzije pravokotnika, ki obkroža besedilo v določeni pisavi in velikosti. Vrne asociativno polje, ki vsebuje ključe `left`, `top`, `width`, `height`. Levi rob je lahko negativen, če se besedilo začne z levim previsom. diff --git a/utils/sl/iterables.texy b/utils/sl/iterables.texy new file mode 100644 index 0000000000..5bcaa78a32 --- /dev/null +++ b/utils/sl/iterables.texy @@ -0,0 +1,119 @@ +Funkcije iteratorja +******************* + +.[perex]{data-version:4.0.4} +[api:Nette\Utils\Iterables] je statični razred s funkcijami za delo z iteratorji. Njegova ustreznica za polja je [Nette\Utils\Arrays |arrays]. + + +Namestitev: + +```shell +composer require nette/utils +``` + +Vsi primeri predvidevajo vzpostavitev vzdevka: + +```php +use Nette\Utils\Iterables; +``` + + +contains(iterable $iterable, $value): bool .[method] +---------------------------------------------------- + +Preizkusi prisotnost vrednosti v iteratorju. Uporablja strogo primerjavo (`===`). + +```php +Iterables::contains(new ArrayIterator([1, 2, 3]), 1); // true +Iterables::contains(new ArrayIterator([1, 2, 3]), '1'); // false +``` + + +containsKey(iterable $iterable, $value): bool .[method] +------------------------------------------------------- + +Preizkusi prisotnost ključa v iteratorju. Uporablja strogo primerjavo (`===`). + +```php +Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0); // true +Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4); // false +``` + + +every(iterable $iterable, callable $predicate): bool .[method] +-------------------------------------------------------------- + +Preizkusi, ali vsi elementi iteratorja prestanejo test, implementiran v `$predicate` s podpisom `function ($value, $key, iterable $iterable): bool`. + +```php +$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]); +$isBelowThreshold = fn($value) => $value < 40; +$res = Iterables::every($iterator, $isBelowThreshold); // true +``` + +Glej [some( |#some()]). + + +filter(iterable $iterable, callable $predicate): Generator .[method] +-------------------------------------------------------------------- + +Iterator, ki filtrira elemente v skladu s predikatom. Predikat ima podpis `function ($value, $key, iterable $iterable): bool`. Ohranja prvotne ključe. + +```php +$iterator = new ArrayIterator([1, 2, 3]); +$iterator = Iterables::filter($iterator, fn($v) => $v < 3); +// 1, 2 +``` + + +first(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------------- + +Vrne prvi element (ki ustreza predikatu, če je določen). Če takega elementa ni, vrne rezultat klica `$else` ali nič. +Parameter `$predicate` ima podpis `function ($value, $key, iterable $iterable): bool`. + +```php +Iterables::first(new ArrayIterator([1, 2, 3])); // 1 +Iterables::first(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 3 +Iterables::first(new ArrayIterator([])); // null +Iterables::first(new ArrayIterator([]), else: fn() => false); // false +``` + + +firstKey(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method] +---------------------------------------------------------------------------------------------- + +Vrne ključ prvega elementa (ki ustreza predikatu, če je določen). Če takega elementa ni, vrne rezultat klica `$else` ali nič. Predikat ima podpis `function ($value, $key, iterable $iterable): bool`. + +```php +Iterables::firstKey(new ArrayIterator([1, 2, 3])); // 0 +Iterables::firstKey(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 2 +Iterables::firstKey(new ArrayIterator(['a' => 1, 'b' => 2])); // 'a' +Iterables::firstKey(new ArrayIterator([])); // null +``` + + +map(iterable $iterable, callable $transformer): array .[method] +--------------------------------------------------------------- + +Iterator, ki preoblikuje vrednosti s klicem `$transformer`. Ima podpis `function ($value, $key, iterable $iterable): bool`. Ohrani prvotne ključe. + +```php +$iterator = new ArrayIterator([1, 2, 3]); +$iterator = Iterables::map($iterator, fn($v) => $v * 2); +// 2, 4, 6 +``` + + +some(iterable $iterable, callable $predicate): bool .[method] +------------------------------------------------------------- + +Preizkusi, ali vsaj en element iteratorja izpolnjuje test, implementiran v `$predicate` s podpisom `function ($value, $key, iterable $iterable): bool`. + +```php +$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]); +$isEven = fn($value) => $value % 2 === 0; +$res = Iterables::some($iterator, $isEven); // true +``` + +Glej [every( |#every()]). diff --git a/utils/tr/@home.texy b/utils/tr/@home.texy index 5fb8feb8e2..9190e91cd9 100644 --- a/utils/tr/@home.texy +++ b/utils/tr/@home.texy @@ -13,6 +13,7 @@ Yardımcı Programlar | [Yardımcılar |helpers] | Nette\Utils\Helpers | [HTML Elemanları |HTML Elements] | Nette\Utils\Html | [Görüntüler |Images] | Nette\Utils\Image +| [Iterables |iterables] | Nette\Utils\Iterables | [JSON |JSON] | Nette\Utils\Json | [Paginator |paginator] | Nette\Utils\Paginator | [PHP |reflection] Yansıması | Nette\Utils\Reflection diff --git a/utils/tr/@left-menu.texy b/utils/tr/@left-menu.texy index a0a5bb879b..5874ca28a6 100644 --- a/utils/tr/@left-menu.texy +++ b/utils/tr/@left-menu.texy @@ -8,6 +8,7 @@ Paket nette/utils - [Yardımcılar |helpers] - [HTML Öğeleri |HTML Elements] - [Görüntüler |Images] +- [Iterables |iterables] - [JSON |JSON] - [Paginator |paginator] - [Rastgele Dizeler |random] diff --git a/utils/tr/arrays.texy b/utils/tr/arrays.texy index 42130c7358..a7e8b892b7 100644 --- a/utils/tr/arrays.texy +++ b/utils/tr/arrays.texy @@ -15,7 +15,7 @@ composer require nette/utils Diziler .[#toc-arrays] ====================== -[api:Nette\Utils\Arrays] bir avuç kullanışlı dizi işlevi içeren statik bir sınıftır. +[api:Nette\Utils\Arrays] bir avuç kullanışlı dizi işlevi içeren statik bir sınıftır. Yineleyiciler için karşılığı [Nette\Utils\Iterables' |iterables]dır. Aşağıdaki örneklerde, aşağıdaki sınıf takma adının tanımlandığı varsayılmaktadır: @@ -76,8 +76,8 @@ Arrays::contains(['1', false], 1); // false ``` -every(iterable $array, callable $callback): bool .[method] ----------------------------------------------------------- +every(array $array, callable $predicate): bool .[method] +-------------------------------------------------------- Dizideki tüm öğelerin, `function ($value, $key, array $array): bool` imzasına sahip olan sağlanan işlev tarafından uygulanan testi geçip geçmediğini sınar. @@ -90,16 +90,52 @@ $res = Arrays::every($array, $isBelowThreshold); // true [some() |#some()] işlevine bakın. -first(array $array): mixed .[method] ------------------------------------- +filter(array $array, callable $predicate): array .[method]{data-version:4.0.4} +------------------------------------------------------------------------------ + +Verilen `$predicate` ile eşleşen tüm anahtar-değer çiftlerini içeren yeni bir dizi döndürür. Geri arama `function ($value, int|string $key, array $array): bool` imzasına sahiptir. + +```php +Arrays::filter( + ['a' => 1, 'b' => 2, 'c' => 3], + fn($v) => $v < 3, +); +// ['a' => 1, 'b' => 2] +``` + + +first(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------- + +İlk öğeyi döndürür (verilmişse belirtilen yüklemle eşleşen). Böyle bir öğe yoksa, `$else` çağrısının sonucunu veya null döndürür. + `$predicate`, `function ($value, int|string $key, array $array): bool` imzasına sahiptir. + + `reset()` adresinden farklı olarak dahili işaretçiyi değiştirmez. `$predicate` ve `$else` parametreleri 4.0.4 sürümünden beri mevcuttur. + +```php +Arrays::first([1, 2, 3]); // 1 +Arrays::first([1, 2, 3], fn($v) => $v > 2); // 3 +Arrays::first([]); // null +Arrays::first([], else: fn() => false); // false +``` -Dizideki ilk öğeyi veya dizi boşsa null döndürür. `reset()` adresinden farklı olarak dahili göstericiyi değiştirmez. +Bkz. [last() |#last()]. + + +firstKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4} +------------------------------------------------------------------------------------------------ + +İlk öğenin anahtarını (verilmişse belirtilen yüklemle eşleşen) veya böyle bir öğe yoksa null döndürür. `$predicate` , `function ($value, int|string $key, array $array): bool` imzasına sahiptir. ```php -Arrays::first([1, 2, 3]); // 1 -Arrays::first([]); // null +Arrays::firstKey([1, 2, 3]); // 0 +Arrays::firstKey([1, 2, 3], fn($v) => $v > 2); // 2 +Arrays::firstKey(['a' => 1, 'b' => 2]); // 'a' +Arrays::firstKey([]); // null ``` + [lastKey() |#lastKey()] işlevine bakın. + flatten(array $array, bool $preserveKeys=false): array .[method] ---------------------------------------------------------------- @@ -229,21 +265,43 @@ Arrays::isList(['a' => 1, 'b' => 2]); // false ``` -last(array $array): mixed .[method] ------------------------------------ +last(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------ + +Son öğeyi döndürür (verilmişse belirtilen yüklemle eşleşen). Böyle bir öğe yoksa, `$else` çağrısının sonucunu veya null döndürür. + `$predicate`, `function ($value, int|string $key, array $array): bool` imzasına sahiptir. + + `end()` adresinden farklı olarak dahili işaretçiyi değiştirmez. `$predicate` ve `$else` parametreleri 4.0.4 sürümünden beri mevcuttur. + +```php +Arrays::last([1, 2, 3]); // 3 +Arrays::last([1, 2, 3], fn($v) => $v < 3); // 2 +Arrays::last([]); // null +Arrays::last([], else: fn() => false); // false +``` + +[First() |#first()] işlevine bakın. + -Dizideki son öğeyi veya dizi boşsa null döndürür. `end()` adresinden farklı olarak dahili göstericiyi değiştirmez. +lastKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4} +----------------------------------------------------------------------------------------------- + +Son öğenin anahtarını (verilmişse belirtilen yüklemle eşleşen) veya böyle bir öğe yoksa null döndürür. `$predicate` , `function ($value, int|string $key, array $array): bool` imzasına sahiptir. ```php -Arrays::last([1, 2, 3]); // 3 -Arrays::last([]); // null +Arrays::lastKey([1, 2, 3]); // 2 +Arrays::lastKey([1, 2, 3], fn($v) => $v < 3); // 1 +Arrays::lastKey(['a' => 1, 'b' => 2]); // 'b' +Arrays::lastKey([]); // null ``` + [firstKey() |#firstKey()] işlevine bakın. + -map(iterable $array, callable $callback): array .[method] +map(array $array, callable $transformer): array .[method] --------------------------------------------------------- -Dizideki tüm öğeler üzerinde `$callback` adresini çağırır ve dönüş değerleri dizisini döndürür. Geri arama `function ($value, $key, array $array): bool` imzasına sahiptir. +Dizideki tüm öğeler üzerinde `$transformer` adresini çağırır ve dönüş değerleri dizisini döndürür. Geri arama `function ($value, $key, array $array): bool` imzasına sahiptir. ```php $array = ['foo', 'bar', 'baz']; @@ -325,8 +383,8 @@ $position = Arrays::getKeyOffset($array, 'not-exists'); // returns null ``` -some(iterable $array, callable $callback): bool .[method] ---------------------------------------------------------- +some(array $array, callable $predicate): bool .[method] +------------------------------------------------------- Dizideki en az bir öğenin `function ($value, $key, array $array): bool` imzasıyla sağlanan geri arama tarafından uygulanan testi geçip geçmediğini sınar. diff --git a/utils/tr/images.texy b/utils/tr/images.texy index fafc8c5deb..285a6bddbf 100644 --- a/utils/tr/images.texy +++ b/utils/tr/images.texy @@ -300,6 +300,11 @@ static isTypeSupported(int $type): bool .[method] Verilen görüntü [türünün |#Formats] desteklenip desteklenmediğini belirler. +static getSupportedTypes(): array .[method]{data-version:4.0.4} +--------------------------------------------------------------- +Desteklenen görüntü türlerinin bir dizisini döndürür (sabitler `ImageType::XXX`). + + static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method] ------------------------------------------------------------------------------------------------------------------------ Metni belirtilen yazı tipi ve boyutta çevreleyen dikdörtgenin boyutlarını hesaplar. `left` , `top`, `width`, `height` anahtarlarını içeren bir ilişkisel dizi döndürür. Metin sola doğru bir çıkıntıyla başlıyorsa, sol kenar boşluğu negatif olabilir. diff --git a/utils/tr/iterables.texy b/utils/tr/iterables.texy new file mode 100644 index 0000000000..9bb6750c49 --- /dev/null +++ b/utils/tr/iterables.texy @@ -0,0 +1,119 @@ +Yineleyici İşlevleri +******************** + +.[perex]{data-version:4.0.4} +[api:Nette\Utils\Iterables] yineleyicilerle çalışmak için işlevler içeren statik bir sınıftır. Diziler için karşılığı [Nette\Utils\Arrays' |arrays]dir. + + +Kurulum: + +```shell +composer require nette/utils +``` + +Tüm örneklerde bir takma ad oluşturulduğu varsayılmaktadır: + +```php +use Nette\Utils\Iterables; +``` + + +contains(iterable $iterable, $value): bool .[method] +---------------------------------------------------- + +Yineleyicide bir değerin varlığını test eder. Sıkı karşılaştırma kullanır (`===`). + +```php +Iterables::contains(new ArrayIterator([1, 2, 3]), 1); // true +Iterables::contains(new ArrayIterator([1, 2, 3]), '1'); // false +``` + + +containsKey(iterable $iterable, $value): bool .[method] +------------------------------------------------------- + +Yineleyicide bir anahtarın varlığını test eder. Sıkı karşılaştırma kullanır (`===`). + +```php +Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0); // true +Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4); // false +``` + + +every(iterable $iterable, callable $predicate): bool .[method] +-------------------------------------------------------------- + +Yineleyicinin tüm öğelerinin `$predicate` içinde `function ($value, $key, iterable $iterable): bool` imzasıyla uygulanan bir testi geçip geçmediğini test eder. + +```php +$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]); +$isBelowThreshold = fn($value) => $value < 40; +$res = Iterables::every($iterator, $isBelowThreshold); // true +``` + + [some() |#some()] işlevine bakın. + + +filter(iterable $iterable, callable $predicate): Generator .[method] +-------------------------------------------------------------------- + +Öğeleri bir yükleme göre filtreleyen yineleyici. Yüklem `function ($value, $key, iterable $iterable): bool` imzasına sahiptir. Orijinal anahtarları korur. + +```php +$iterator = new ArrayIterator([1, 2, 3]); +$iterator = Iterables::filter($iterator, fn($v) => $v < 3); +// 1, 2 +``` + + +first(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------------- + +İlk öğeyi döndürür (belirtilmişse, yüklemle eşleşen). Böyle bir öğe yoksa, `$else` çağrısının sonucunu veya null döndürür. + `$predicate` parametresi `function ($value, $key, iterable $iterable): bool` imzasına sahiptir. + +```php +Iterables::first(new ArrayIterator([1, 2, 3])); // 1 +Iterables::first(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 3 +Iterables::first(new ArrayIterator([])); // null +Iterables::first(new ArrayIterator([]), else: fn() => false); // false +``` + + +firstKey(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method] +---------------------------------------------------------------------------------------------- + +İlk öğenin anahtarını döndürür (belirtilmişse, yüklemle eşleşen). Böyle bir öğe yoksa, `$else` çağrısının sonucunu veya null döndürür. Yüklem `function ($value, $key, iterable $iterable): bool` imzasına sahiptir. + +```php +Iterables::firstKey(new ArrayIterator([1, 2, 3])); // 0 +Iterables::firstKey(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 2 +Iterables::firstKey(new ArrayIterator(['a' => 1, 'b' => 2])); // 'a' +Iterables::firstKey(new ArrayIterator([])); // null +``` + + +map(iterable $iterable, callable $transformer): array .[method] +--------------------------------------------------------------- + + `$transformer` adresini çağırarak değerleri dönüştüren yineleyici. `function ($value, $key, iterable $iterable): bool` imzasına sahiptir. Orijinal anahtarları korur. + +```php +$iterator = new ArrayIterator([1, 2, 3]); +$iterator = Iterables::map($iterator, fn($v) => $v * 2); +// 2, 4, 6 +``` + + +some(iterable $iterable, callable $predicate): bool .[method] +------------------------------------------------------------- + +Yineleyicinin en az bir öğesinin `$predicate` içinde `function ($value, $key, iterable $iterable): bool` imzasıyla uygulanan bir testi geçip geçmediğini test eder. + +```php +$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]); +$isEven = fn($value) => $value % 2 === 0; +$res = Iterables::some($iterator, $isEven); // true +``` + +Bkz. [every() |#every()]. diff --git a/utils/uk/@home.texy b/utils/uk/@home.texy index d2e35c55b6..9fa4b85aba 100644 --- a/utils/uk/@home.texy +++ b/utils/uk/@home.texy @@ -13,6 +13,7 @@ | [Зображення |images] | Nette\Utils\Image | [Пагінація |paginator] | Nette\Utils\Paginator | [Парсинг і генерація JSON |json] | Nette\Utils\Json +| [Змінні |iterables] | Nette\Utils\Iterables | [Поле |arrays] | Nette\Utils\Arrays | [Рядки |strings] | Nette\Utils\Strings | [Типи |type] | Nette\Utils\Type diff --git a/utils/uk/@left-menu.texy b/utils/uk/@left-menu.texy index 69dc75a6e1..66d73a31c6 100644 --- a/utils/uk/@left-menu.texy +++ b/utils/uk/@left-menu.texy @@ -8,6 +8,7 @@ - [Зображення |images] - [Зворотні виклики |callback] - [Пагінатор |paginator] +- [Ітерабельні змінні |iterables] - [Поле |arrays] - [Випадкові рядки |random] - [Рядки |strings] diff --git a/utils/uk/arrays.texy b/utils/uk/arrays.texy index f47e1096a2..cd19d823e4 100644 --- a/utils/uk/arrays.texy +++ b/utils/uk/arrays.texy @@ -15,7 +15,7 @@ composer require nette/utils Масиви .[#toc-arrays] ===================== -[api:Nette\Utils\Arrays] це статичний клас, що містить корисні функції для роботи з масивами. +[api:Nette\Utils\Arrays] це статичний клас, який містить декілька зручних функцій для роботи з масивами. Його еквівалентом для ітераторів є [Nette\Utils\Iterables |iterables]. У наступних прикладах передбачається, що псевдонім уже створено: @@ -76,10 +76,10 @@ Arrays::contains(['1', false], 1); // false ``` -every(iterable $array, callable $callback): bool .[method] ----------------------------------------------------------- +every(array $array, callable $predicate): bool .[method] +-------------------------------------------------------- -Перевіряє, чи всі елементи в масиві проходять тест, реалізований у `$callback` з сигнатурою `function ($value, $key, array $array): bool`. +Перевіряє, чи всі елементи в масиві проходять тест, реалізований у `$predicate` з сигнатурою `function ($value, $key, array $array): bool`. ```php $array = [1, 30, 39, 29, 10, 13]; @@ -90,16 +90,52 @@ $res = Arrays::every($array, $isBelowThreshold); // true Див. [some() |#some]. -first(array $array): mixed .[method] ------------------------------------- +filter(array $array, callable $predicate): array .[method]{data-version:4.0.4} +------------------------------------------------------------------------------ + +Повертає новий масив, що містить всі пари ключ-значення, які відповідають заданому `$predicate`. Зворотний виклик має сигнатуру `function ($value, int|string $key, array $array): bool`. + +```php +Arrays::filter( + ['a' => 1, 'b' => 2, 'c' => 3], + fn($v) => $v < 3, +); +// ['a' => 1, 'b' => 2] +``` + + +first(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------- + +Повертає перший елемент (що відповідає вказаному предикату, якщо він заданий). Якщо такого елемента немає, повертається результат виклику `$else` або нуль. +Функція `$predicate` має підпис `function ($value, int|string $key, array $array): bool`. + +Він не змінює внутрішній вказівник, на відміну від `reset()`. Параметри `$predicate` та `$else` з'явилися починаючи з версії 4.0.4. + +```php +Arrays::first([1, 2, 3]); // 1 +Arrays::first([1, 2, 3], fn($v) => $v > 2); // 3 +Arrays::first([]); // null +Arrays::first([], else: fn() => false); // false +``` -Повертає перший запис із масиву або null, якщо масив порожній. Не змінює внутрішній покажчик, на відміну від `reset()`. +Див. [функцію last( |#last()]). + + +firstKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4} +------------------------------------------------------------------------------------------------ + +Повертає ключ першого елемента (що відповідає вказаному предикату, якщо він заданий) або нуль, якщо такого елемента немає. `$predicate` має підпис `function ($value, int|string $key, array $array): bool`. ```php -Arrays::first([1, 2, 3]); // 1 -Arrays::first([]); // null +Arrays::firstKey([1, 2, 3]); // 0 +Arrays::firstKey([1, 2, 3], fn($v) => $v > 2); // 2 +Arrays::firstKey(['a' => 1, 'b' => 2]); // 'a' +Arrays::firstKey([]); // null ``` +Див. функцію [lastKey( |#lastKey()]). + flatten(array $array, bool $preserveKeys=false): array .[method] ---------------------------------------------------------------- @@ -229,21 +265,43 @@ Arrays::isList(['a' => 1, 'b' => 2]); // false ``` -last(array $array): mixed .[method] ------------------------------------ +last(array $array, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------ + +Повертає останній елемент (що відповідає вказаному предикату, якщо він заданий). Якщо такого елемента немає, повертається результат виклику `$else` або нуль. +Функція `$predicate` має підпис `function ($value, int|string $key, array $array): bool`. + +Він не змінює внутрішній вказівник, на відміну від `end()`. Параметри `$predicate` та `$else` з'явилися починаючи з версії 4.0.4. + +```php +Arrays::last([1, 2, 3]); // 3 +Arrays::last([1, 2, 3], fn($v) => $v < 3); // 2 +Arrays::last([]); // null +Arrays::last([], else: fn() => false); // false +``` + +Див. [функцію first() |#first()]. + -Повертає останній запис масиву або null, якщо масив порожній. Не змінює внутрішній покажчик, на відміну від `end()`. +lastKey(array $array, ?callable $predicate=null): int|string|null .[method]{data-version:4.0.4} +----------------------------------------------------------------------------------------------- + +Повертає ключ останнього елемента (який відповідає вказаному предикату, якщо його задано) або нуль, якщо такого елемента не існує. `$predicate` має підпис `function ($value, int|string $key, array $array): bool`. ```php -Arrays::last([1, 2, 3]); // 3 -Arrays::last([]); // null +Arrays::lastKey([1, 2, 3]); // 2 +Arrays::lastKey([1, 2, 3], fn($v) => $v < 3); // 1 +Arrays::lastKey(['a' => 1, 'b' => 2]); // 'b' +Arrays::lastKey([]); // null ``` +Зверніться до [firstKey( |#firstKey()]). + -map(iterable $array, callable $callback): array .[method] +map(array $array, callable $transformer): array .[method] --------------------------------------------------------- -Викликає `$callback` на всіх елементах масиву і повертає масив значень, що повертаються. Зворотний виклик має сигнатуру `function ($value, $key, array $array): bool`. +Викликає `$transformer` на всіх елементах масиву і повертає масив значень, що повертаються. Зворотний виклик має сигнатуру `function ($value, $key, array $array): bool`. ```php $array = ['foo', 'bar', 'baz']; @@ -325,10 +383,10 @@ $position = Arrays::getKeyOffset($array, 'not-exists'); // vrátí null ``` -some(iterable $array, callable $callback): bool .[method] ---------------------------------------------------------- +some(array $array, callable $predicate): bool .[method] +------------------------------------------------------- -Перевіряє, чи проходить хоча б один елемент у масиві тест, реалізований у `$callback` із сигнатурою `function ($value, $key, array $array): bool`. +Перевіряє, чи проходить хоча б один елемент у масиві тест, реалізований у `$predicate` із сигнатурою `function ($value, $key, array $array): bool`. ```php $array = [1, 2, 3, 4]; diff --git a/utils/uk/images.texy b/utils/uk/images.texy index 398fc1253e..a2d84ce2fd 100644 --- a/utils/uk/images.texy +++ b/utils/uk/images.texy @@ -300,6 +300,11 @@ static isTypeSupported(int $type): bool .[method] Визначає, чи підтримується даний [тип |#Formats] зображення. +static getSupportedTypes(): array .[method]{data-version:4.0.4} +--------------------------------------------------------------- +Повертає масив підтримуваних типів зображень (константи `ImageType::XXX`). + + static calculateTextBox(string $text, string $fontFile, float $size, float $angle=0, array $options=[]): array .[method] ------------------------------------------------------------------------------------------------------------------------ Обчислює розміри прямокутника, який охоплює текст заданого шрифту та розміру. Повертає асоціативний масив, що містить ключі `left`, `top`, `width`, `height`. Ліве поле може бути від'ємним, якщо текст починається з лівого відступу. diff --git a/utils/uk/iterables.texy b/utils/uk/iterables.texy new file mode 100644 index 0000000000..4321573824 --- /dev/null +++ b/utils/uk/iterables.texy @@ -0,0 +1,119 @@ +Функції ітератора +***************** + +.[perex]{data-version:4.0.4} +[api:Nette\Utils\Iterables] статичний клас з функціями для роботи з ітераторами. Його аналогом для масивів є [Nette\Utils\Arrays |arrays]. + + +Встановлення: + +```shell +composer require nette/utils +``` + +Усі приклади передбачають створення псевдоніма: + +```php +use Nette\Utils\Iterables; +``` + + +contains(iterable $iterable, $value): bool .[method] +---------------------------------------------------- + +Перевіряє наявність значення в ітераторі. Використовує строге порівняння (`===`). + +```php +Iterables::contains(new ArrayIterator([1, 2, 3]), 1); // true +Iterables::contains(new ArrayIterator([1, 2, 3]), '1'); // false +``` + + +containsKey(iterable $iterable, $value): bool .[method] +------------------------------------------------------- + +Перевіряє наявність ключа в ітераторі. Використовує строге порівняння (`===`). + +```php +Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0); // true +Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4); // false +``` + + +every(iterable $iterable, callable $predicate): bool .[method] +-------------------------------------------------------------- + +Перевіряє, чи всі елементи ітератора проходять тест, реалізований у `$predicate` з сигнатурою `function ($value, $key, iterable $iterable): bool`. + +```php +$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]); +$isBelowThreshold = fn($value) => $value < 40; +$res = Iterables::every($iterator, $isBelowThreshold); // true +``` + +Див. [функцію some() |#some()]. + + +filter(iterable $iterable, callable $predicate): Generator .[method] +-------------------------------------------------------------------- + +Ітератор, який фільтрує елементи за предикатом. Предикат має сигнатуру `function ($value, $key, iterable $iterable): bool`. Зберігає оригінальні ключі. + +```php +$iterator = new ArrayIterator([1, 2, 3]); +$iterator = Iterables::filter($iterator, fn($v) => $v < 3); +// 1, 2 +``` + + +first(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method] +------------------------------------------------------------------------------------------- + +Повертає перший елемент (що збігається з предикатом, якщо його вказано). Якщо такого елемента не існує, повертає результат виклику `$else` або нуль. +Параметр `$predicate` має сигнатуру `function ($value, $key, iterable $iterable): bool`. + +```php +Iterables::first(new ArrayIterator([1, 2, 3])); // 1 +Iterables::first(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 3 +Iterables::first(new ArrayIterator([])); // null +Iterables::first(new ArrayIterator([]), else: fn() => false); // false +``` + + +firstKey(iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed .[method] +---------------------------------------------------------------------------------------------- + +Повертає ключ першого елемента (збігається з предикатом, якщо вказано). Якщо такого елемента не існує, повертає результат виклику `$else` або нуль. Предикат має сигнатуру `function ($value, $key, iterable $iterable): bool`. + +```php +Iterables::firstKey(new ArrayIterator([1, 2, 3])); // 0 +Iterables::firstKey(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 2 +Iterables::firstKey(new ArrayIterator(['a' => 1, 'b' => 2])); // 'a' +Iterables::firstKey(new ArrayIterator([])); // null +``` + + +map(iterable $iterable, callable $transformer): array .[method] +--------------------------------------------------------------- + +Ітератор, що перетворює значення шляхом виклику `$transformer`. Має сигнатуру `function ($value, $key, iterable $iterable): bool`. Зберігає оригінальні ключі. + +```php +$iterator = new ArrayIterator([1, 2, 3]); +$iterator = Iterables::map($iterator, fn($v) => $v * 2); +// 2, 4, 6 +``` + + +some(iterable $iterable, callable $predicate): bool .[method] +------------------------------------------------------------- + +Перевіряє, чи проходить хоча б один елемент ітератора тест, реалізований у `$predicate` з сигнатурою `function ($value, $key, iterable $iterable): bool`. + +```php +$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]); +$isEven = fn($value) => $value % 2 === 0; +$res = Iterables::some($iterator, $isEven); // true +``` + +Див. [функцію every() |#every()]. From a99d5129a930394022d86126a3e39dcaf2b2d144 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Karbula?= Date: Sun, 21 Jan 2024 17:43:24 +0100 Subject: [PATCH 047/137] tester: option -l replaced with -o --- tester/bg/running-tests.texy | 22 +++++++--------------- tester/cs/running-tests.texy | 22 +++++++--------------- tester/de/running-tests.texy | 22 +++++++--------------- tester/el/running-tests.texy | 22 +++++++--------------- tester/en/running-tests.texy | 22 +++++++--------------- tester/es/running-tests.texy | 22 +++++++--------------- tester/fr/running-tests.texy | 22 +++++++--------------- tester/hu/running-tests.texy | 22 +++++++--------------- tester/it/running-tests.texy | 22 +++++++--------------- tester/pl/running-tests.texy | 22 +++++++--------------- tester/pt/running-tests.texy | 22 +++++++--------------- tester/ro/running-tests.texy | 22 +++++++--------------- tester/ru/running-tests.texy | 22 +++++++--------------- tester/sl/running-tests.texy | 22 +++++++--------------- tester/tr/running-tests.texy | 22 +++++++--------------- tester/uk/running-tests.texy | 22 +++++++--------------- 16 files changed, 112 insertions(+), 240 deletions(-) diff --git a/tester/bg/running-tests.texy b/tester/bg/running-tests.texy index 5fe8d2728f..4fff8846a6 100644 --- a/tester/bg/running-tests.texy +++ b/tester/bg/running-tests.texy @@ -58,16 +58,16 @@ PHP 7.4.8 (cli) | php -n | 8 threads -p <путь> Укажите интерпретатор PHP для запуска (по умолчанию: php). -c Искать php.ini файл (или искать в директории) . -C Использовать общесистемный php.ini. - -l | --log <путь> Запись журнала в файл <путь>. -d <ключ=значение>... Определить INI-запись 'key' со значением 'value'. -s Показать информацию о пропущенных тестах. --stop-on-fail Остановить выполнение при первом сбое. -j Выполнять заданий параллельно (по умолчанию: 8). - -o Указать формат вывода. + -o (напр. -o junit:output.xml) + Посочете един или повече изходни формати с незадължително име на файл. -w | --watch <путь> Каталог просмотра. -i | --info Показать информацию об окружении тестов и выйти. --setup <путь> Сценарий для настройки бегущей строки. - --temp <путь> Путь к временному каталогу. По умолчанию: sys_get_temp_dir(). + --temp Път до временна директория. По подразбиране от sys_get_temp_dir(). --colors [1|0] Включить или отключить цвета. --coverage <путь> Генерировать отчет о покрытии кода в файл. --coverage-src <путь> Путь к исходному коду. @@ -94,15 +94,6 @@ tester -p /home/user/php-7.2.0-beta/php-cgi tests Използва се общосистемният `php.ini`. Така че на платформата UNIX се използват и всички файлове `/etc/php/{sapi}/conf.d/*.ini`. Вижте раздела [Собствен php.ini |#Own php.ini]. -''-l | --log '' .[filter] -------------------------------- -Напредъкът на тестването се записва във файл. Всички неуспешни, пропуснати, а също и успешни тестове: - -/--pre .[terminal] -tester --log /var/log/tests.log tests -\-- - - -d .[filter] ------------------------ Задава стойността на конфигурационната директива на PHP за тестове. Параметърът може да се използва многократно. @@ -127,13 +118,14 @@ tester -d max_execution_time=20 Тестовете се изпълняват в `` паралелни прецеси. Стойността по подразбиране е 8. Ако искаме да изпълняваме тестовете последователно, използваме стойност 1. --o .[filter] -------------------------------------- -Формат на изхода. По подразбиране е конзолният формат. +-o .[filter] +----------------------------------------- +Изходен формат. По подразбиране е конзолният формат. Можете да посочите името на файла, в който ще бъде записан изходният файл (напр. `-o junit:output.xml`). Опцията `-o` може да се повтори многократно, за да се генерират няколко формата наведнъж. - `console`: същият като по подразбиране, но в този случай не се отпечатва ASCII логото - `tap`: [TAP формат, |https://en.wikipedia.org/wiki/Test_Anything_Protocol] подходящ за машинна обработка - `junit`: JUnit XML формат, подходящ и за машинна обработка +- `log`: Извежда информация за хода на тестването. Всички неуспешни, пропуснати, а също и успешни тестове - `none`: не се отпечатва нищо diff --git a/tester/cs/running-tests.texy b/tester/cs/running-tests.texy index ee894e59c7..574862fa20 100644 --- a/tester/cs/running-tests.texy +++ b/tester/cs/running-tests.texy @@ -58,16 +58,16 @@ Options: -p Specify PHP interpreter to run (default: php). -c Look for php.ini file (or look in directory) . -C Use system-wide php.ini. - -l | --log Write log to file . -d ... Define INI entry 'key' with value 'value'. -s Show information about skipped tests. --stop-on-fail Stop execution upon the first failure. -j Run jobs in parallel (default: 8). - -o Specify output format. + -o (e.g. -o junit:output.xml) + Specify one or more output formats with optional file name. -w | --watch Watch directory. -i | --info Show tests environment info and exit. --setup Script for runner setup. - --temp Path to temporary directory. Default: sys_get_temp_dir(). + --temp Path to temporary directory. Default by sys_get_temp_dir(). --colors [1|0] Enable or disable colors. --coverage Generate code coverage report to file. --coverage-src Path to source code. @@ -94,15 +94,6 @@ Určuje, který `php.ini` se bude používat při spouštění testů. Ve výcho Použije se systémové `php.ini`. Na UNIXu také všechny příslušné INI soubory `/etc/php/{sapi}/conf.d/*.ini`. Více v části [#Vlastní php.ini]. -''-l | --log '' .[filter] -------------------------------- -Do uvedeného souboru bude zapsán průběh testování. Všechny selhané, přeskočené, ale i úspěšné testy: - -/--pre .[terminal] -tester --log /var/log/tests.log tests -\-- - - -d .[filter] ------------------------ Nastavuje hodnotu PHP konfigurační direktivy pro testy. Parametr může být použit vícekrát. @@ -127,13 +118,14 @@ Tester zastaví testování u prvního selhávajícího testu. Určuje, kolik paralelních procesů s testy se spustí. Výchozí hodnota je 8. Chceme-li, aby všechny testy proběhly v sérii, použijeme hodnotu 1. --o .[filter] -------------------------------------- -Nastaví formát výstupu. Výchozí je formát pro konzoli. +-o .[filter] +----------------------------------------- +Nastaví formát výstupu. Výchozí je formát pro konzoli. Můžete uvést jméno souboru, do kterého se výstup zapíše (např `-o junit:output.xml`). Volbu `-o` lze zopakovat vícekrát a vygenerovat tak více formátů najednou. - `console`: shodné s výchozím formátem, ale v tomto případě se nezobrazí ASCII logo - `tap`: [TAP formát |https://en.wikipedia.org/wiki/Test_Anything_Protocol] vhodný pro strojové zpracování - `junit`: XML formát JUnit, taktéž vhodný pro strojové zpracování +- `log`: Výstupy průběhu testování. Všechny neúspěšné, přeskočené a také úspěšné testy - `none`: nic se nevypisuje diff --git a/tester/de/running-tests.texy b/tester/de/running-tests.texy index 1e5cd5098a..821ca8805d 100644 --- a/tester/de/running-tests.texy +++ b/tester/de/running-tests.texy @@ -58,16 +58,16 @@ Options: -p Specify PHP interpreter to run (default: php). -c Look for php.ini file (or look in directory) . -C Use system-wide php.ini. - -l | --log Write log to file . -d ... Define INI entry 'key' with value 'value'. -s Show information about skipped tests. --stop-on-fail Stop execution upon the first failure. -j Run jobs in parallel (default: 8). - -o Specify output format. + -o (z. B. -o junit:output.xml) + Geben Sie ein oder mehrere Ausgabeformate mit optionalem Dateinamen an. -w | --watch Watch directory. -i | --info Show tests environment info and exit. --setup Script for runner setup. - --temp Path to temporary directory. Default: sys_get_temp_dir(). + --temp Pfad zum temporären Verzeichnis. Vorgabe durch sys_get_temp_dir(). --colors [1|0] Enable or disable colors. --coverage Generate code coverage report to file. --coverage-src Path to source code. @@ -94,15 +94,6 @@ Gibt an, welche `php.ini` bei der Ausführung von Tests verwendet wird. Standard Es wird eine systemweite `php.ini` verwendet. Auf der UNIX-Plattform also auch alle `/etc/php/{sapi}/conf.d/*.ini` -Dateien. Siehe Abschnitt [Eigene php.ini |#Own php.ini]. -''-l | --log '' .[filter] -------------------------------- -Der Testfortschritt wird in eine Datei geschrieben. Alle fehlgeschlagenen, übersprungenen und auch erfolgreichen Tests: - -/--pre .[terminal] -tester --log /var/log/tests.log tests -\-- - - -d .[filter] ------------------------ Legt den Wert der PHP-Konfigurationsrichtlinie für Tests fest. Der Parameter kann mehrfach verwendet werden. @@ -127,13 +118,14 @@ Der Tester bricht den Test ab, sobald der erste Test fehlschlägt. Tests laufen in einem `` parallel abläuft. Der Standardwert ist 8. Wenn wir die Tests in Serie laufen lassen wollen, verwenden wir den Wert 1. --o .[filter] -------------------------------------- -Ausgabeformat. Standard ist das Konsolenformat. +-o .[filter] +----------------------------------------- +Ausgabeformat. Standardmäßig wird das Konsolenformat verwendet. Sie können den Namen der Datei angeben, in die die Ausgabe geschrieben werden soll (z. B. `-o junit:output.xml`). Die Option `-o` kann mehrmals wiederholt werden, um mehrere Formate auf einmal zu erzeugen. - `console`: wie Standard, aber das ASCII-Logo wird in diesem Fall nicht gedruckt - `tap`: [TAP-Format |https://en.wikipedia.org/wiki/Test_Anything_Protocol], geeignet für die maschinelle Verarbeitung - `junit`: JUnit XML-Format, auch für die maschinelle Verarbeitung geeignet +- `log`: Gibt den Testfortschritt aus. Alle fehlgeschlagenen, übersprungenen und auch erfolgreichen Tests - `none`: es wird nichts gedruckt diff --git a/tester/el/running-tests.texy b/tester/el/running-tests.texy index 7584b9b4c7..83e2214944 100644 --- a/tester/el/running-tests.texy +++ b/tester/el/running-tests.texy @@ -58,16 +58,16 @@ Options: -p Specify PHP interpreter to run (default: php). -c Look for php.ini file (or look in directory) . -C Use system-wide php.ini. - -l | --log Write log to file . -d ... Define INI entry 'key' with value 'value'. -s Show information about skipped tests. --stop-on-fail Stop execution upon the first failure. -j Run jobs in parallel (default: 8). - -o Specify output format. + -o (π.χ. -o junit:output.xml) + Καθορίστε μία ή περισσότερες μορφές εξόδου με προαιρετικό όνομα αρχείου. -w | --watch Watch directory. -i | --info Show tests environment info and exit. --setup Script for runner setup. - --temp Path to temporary directory. Default: sys_get_temp_dir(). + --temp Διαδρομή προς τον προσωρινό κατάλογο. Προεπιλογή από την sys_get_temp_dir(). --colors [1|0] Enable or disable colors. --coverage Generate code coverage report to file. --coverage-src Path to source code. @@ -94,15 +94,6 @@ tester -p /home/user/php-7.2.0-beta/php-cgi tests Χρησιμοποιείται ένα `php.ini` σε όλο το σύστημα. Έτσι, στην πλατφόρμα UNIX, όλα τα αρχεία `/etc/php/{sapi}/conf.d/*.ini` επίσης. Δείτε την ενότητα [Own php.ini |#Own php.ini]. -''-l | --log '' .[filter] -------------------------------- -Η πρόοδος των δοκιμών γράφεται σε αρχείο. Όλες οι αποτυχημένες, παραλειφθείσες και επιτυχημένες δοκιμές: - -/--pre .[terminal] -tester --log /var/log/tests.log tests -\-- - - -d .[filter] ------------------------ Ορίζει την τιμή της οδηγίας διαμόρφωσης PHP για δοκιμές. Η παράμετρος μπορεί να χρησιμοποιηθεί πολλές φορές. @@ -127,13 +118,14 @@ tester -d max_execution_time=20 Οι δοκιμές εκτελούνται σε ένα `` παράλληλες διεργασίες. Η προεπιλεγμένη τιμή είναι 8. Αν θέλουμε να εκτελούμε δοκιμές σε σειρά, χρησιμοποιούμε την τιμή 1. --o .[filter] -------------------------------------- -Μορφή εξόδου. Η προεπιλογή είναι η μορφή κονσόλας. +-o .[filter] +----------------------------------------- +Μορφή εξόδου. Η προεπιλογή είναι η μορφή κονσόλας. Μπορείτε να καθορίσετε το όνομα του αρχείου στο οποίο θα γραφτεί η έξοδος (π.χ. `-o junit:output.xml`). Η επιλογή `-o` μπορεί να επαναληφθεί πολλές φορές για την ταυτόχρονη παραγωγή πολλαπλών μορφών. - `console`: η ίδια με την προεπιλογή, αλλά το λογότυπο ASCII δεν εκτυπώνεται σε αυτή την περίπτωση. - `tap`: [Μορφή TAP |https://en.wikipedia.org/wiki/Test_Anything_Protocol] κατάλληλη για μηχανική επεξεργασία. - `junit`: Μορφή JUnit XML, κατάλληλη και για μηχανική επεξεργασία. +- `log`: Εξάγει την πρόοδο των δοκιμών. Όλες οι αποτυχημένες, παραλειφθείσες και επιτυχημένες δοκιμές - `none`: δεν εκτυπώνεται τίποτα diff --git a/tester/en/running-tests.texy b/tester/en/running-tests.texy index 201f33718f..1750ac6b52 100644 --- a/tester/en/running-tests.texy +++ b/tester/en/running-tests.texy @@ -58,16 +58,16 @@ Options: -p Specify PHP interpreter to run (default: php). -c Look for php.ini file (or look in directory) . -C Use system-wide php.ini. - -l | --log Write log to file . -d ... Define INI entry 'key' with value 'value'. -s Show information about skipped tests. --stop-on-fail Stop execution upon the first failure. -j Run jobs in parallel (default: 8). - -o Specify output format. + -o (e.g. -o junit:output.xml) + Specify one or more output formats with optional file name. -w | --watch Watch directory. -i | --info Show tests environment info and exit. --setup Script for runner setup. - --temp Path to temporary directory. Default: sys_get_temp_dir(). + --temp Path to temporary directory. Default by sys_get_temp_dir(). --colors [1|0] Enable or disable colors. --coverage Generate code coverage report to file. --coverage-src Path to source code. @@ -94,15 +94,6 @@ Specifies which `php.ini` will be used when running tests. By default, no php.in A system-wide `php.ini` is used. So on UNIX platform, all the `/etc/php/{sapi}/conf.d/*.ini` files too. See [#Own php.ini] section. -''-l | --log '' .[filter] -------------------------------- -Testing progress is written into file. All failed, skipped and also successful tests: - -/--pre .[terminal] -tester --log /var/log/tests.log tests -\-- - - -d .[filter] ------------------------ Sets the value of the PHP configuration directive for tests. The parameter can be used multiple times. @@ -127,13 +118,14 @@ Tester stops testing upon the first failing test. Tests run in a `` parallel precesses. Default value is 8. If we wish to run tests in series, we use value 1. --o .[filter] -------------------------------------- -Output format. Default is the console format. +-o .[filter] +----------------------------------------- +Output format. Default is the console format. You can specify the name of the file into which the output will be written (e.g., `-o junit:output.xml`). The `-o` option can be repeated multiple times to generate multiple formats at once. - `console`: the same as default, but the ASCII logo is not printed in this case - `tap`: [TAP format |https://en.wikipedia.org/wiki/Test_Anything_Protocol] appropriate for machine processing - `junit`: JUnit XML format, appropriate for machine processing too +- `log`: Outputs testing progress. All failed, skipped and also successful tests - `none`: nothing is printed diff --git a/tester/es/running-tests.texy b/tester/es/running-tests.texy index 571b97135b..bc13f7b3aa 100644 --- a/tester/es/running-tests.texy +++ b/tester/es/running-tests.texy @@ -58,16 +58,16 @@ Opciones: -p Especificar intérprete PHP a ejecutar (por defecto: php). -c Buscar el archivo php.ini (o buscar en el directorio) . -C Usar php.ini para todo el sistema. - -l | --log Escribe el registro en el archivo . -d ... Definir entrada INI con valor . -s Mostrar información sobre las pruebas omitidas. --stop-on-fail Detener la ejecución al primer fallo. -j Ejecutar trabajos en paralelo (por defecto: 8). - -o Especifica el formato de salida. + -o (por ejemplo, -o junit:output.xml) + Especifica uno o más formatos de salida con un nombre de archivo opcional. -w | --watch Directorio de vigilancia. -i | --info Mostrar información del entorno de pruebas y salir. --setup Script para la configuración del runner. - --temp Ruta al directorio temporal. Por defecto: sys_get_temp_dir(). + --temp Ruta al directorio temporal. Por defecto por sys_get_temp_dir(). --colors [1|0] Activa o desactiva los colores. --coverage Generar informe de cobertura de código a archivo. --coverage-src Ruta al código fuente. @@ -94,15 +94,6 @@ Especifica qué `php.ini` se utilizará al ejecutar las pruebas. Por defecto, no Se utiliza `php.ini` para todo el sistema. Así que en la plataforma UNIX, todos los archivos `/etc/php/{sapi}/conf.d/*.ini` también. Véase la sección [php.ini propia |#Own php.ini]. -''-l | --log '' .[filter] -------------------------------- -El progreso de las pruebas se escribe en el archivo. Todas las pruebas fallidas, omitidas y también las exitosas: - -/--pre .[terminal] -tester --log /var/log/tests.log tests -\-- - - -d .[filter] ------------------------ Establece el valor de la directiva de configuración PHP para las pruebas. El parámetro se puede utilizar varias veces. @@ -127,13 +118,14 @@ El probador detiene la prueba al fallar la primera prueba. Las pruebas se ejecutan en `` precesos en paralelo. El valor por defecto es 8. Si deseamos ejecutar las pruebas en serie, utilizaremos el valor 1. --o .[filter] -------------------------------------- -Formato de salida. Por defecto es el formato de consola. +-o .[filter] +----------------------------------------- +Formato de salida. Por defecto es el formato de consola. Puede especificar el nombre del archivo en el que se escribirá la salida (por ejemplo, `-o junit:output.xml`). La opción `-o` puede repetirse varias veces para generar varios formatos a la vez. - `console`: igual que por defecto, pero en este caso no se imprime el logotipo ASCII - `tap`: formato [TAP |https://en.wikipedia.org/wiki/Test_Anything_Protocol] apropiado para el procesamiento en máquina - `junit`: formato JUnit XML, apropiado también para el procesamiento en máquina +- `log`: Muestra el progreso de las pruebas. Todas las pruebas fallidas, omitidas y también las exitosas - `none`: no se imprime nada diff --git a/tester/fr/running-tests.texy b/tester/fr/running-tests.texy index a7fee934e3..afcc23f843 100644 --- a/tester/fr/running-tests.texy +++ b/tester/fr/running-tests.texy @@ -58,16 +58,16 @@ Options: -p Specify PHP interpreter to run (default: php). -c Look for php.ini file (or look in directory) . -C Use system-wide php.ini. - -l | --log Write log to file . -d ... Define INI entry 'key' with value 'value'. -s Show information about skipped tests. --stop-on-fail Stop execution upon the first failure. -j Run jobs in parallel (default: 8). - -o Specify output format. + -o (par exemple -o junit:output.xml) + Spécifier un ou plusieurs formats de sortie avec un nom de fichier optionnel. -w | --watch Watch directory. -i | --info Show tests environment info and exit. --setup Script for runner setup. - --temp Path to temporary directory. Default: sys_get_temp_dir(). + --temp Chemin d'accès au répertoire temporaire. Par défaut par sys_get_temp_dir(). --colors [1|0] Enable or disable colors. --coverage Generate code coverage report to file. --coverage-src Path to source code. @@ -94,15 +94,6 @@ Spécifie quel `php.ini` sera utilisé lors de l'exécution des tests. Par défa Un `php.ini` à l'échelle du système est utilisé. Donc, sur une plateforme UNIX, tous les fichiers `/etc/php/{sapi}/conf.d/*.ini` aussi. Voir la section [Own php.ini |#Own php.ini]. -''-l | --log '' .[filter] -------------------------------- -La progression des tests est écrite dans le fichier. Tous les tests échoués, ignorés et aussi les tests réussis : - -/--pre .[terminal] -tester --log /var/log/tests.log tests -\-- - - -d .[filter] ------------------------ Définit la valeur de la directive de configuration PHP pour les tests. Le paramètre peut être utilisé plusieurs fois. @@ -127,13 +118,14 @@ Le testeur arrête les tests au premier échec. Les tests s'exécutent dans un `` parallèles. La valeur par défaut est 8. Si nous souhaitons exécuter les tests en série, nous utilisons la valeur 1. --o .[filter] -------------------------------------- -Format de sortie. Le format par défaut est celui de la console. +-o .[filter] +----------------------------------------- +Format de sortie. Le format par défaut est celui de la console. Vous pouvez spécifier le nom du fichier dans lequel la sortie sera écrite (par exemple, `-o junit:output.xml`). L'option `-o` peut être répétée plusieurs fois pour générer plusieurs formats à la fois. - `console`: identique à celui par défaut, mais le logo ASCII n'est pas imprimé dans ce cas - `tap`: [format TAP |https://en.wikipedia.org/wiki/Test_Anything_Protocol] approprié au traitement machine - `junit`: format XML de JUnit, également approprié au traitement par machine +- `log`: Affiche l'état d'avancement des tests. Tous les tests échoués, ignorés et réussis - `none`: rien n'est imprimé diff --git a/tester/hu/running-tests.texy b/tester/hu/running-tests.texy index a44e03b88a..d618203f7a 100644 --- a/tester/hu/running-tests.texy +++ b/tester/hu/running-tests.texy @@ -58,16 +58,16 @@ Options: -p Specify PHP interpreter to run (default: php). -c Look for php.ini file (or look in directory) . -C Use system-wide php.ini. - -l | --log Write log to file . -d ... Define INI entry 'key' with value 'value'. -s Show information about skipped tests. --stop-on-fail Stop execution upon the first failure. -j Run jobs in parallel (default: 8). - -o Specify output format. + -o (pl. -o junit:output.xml) + Egy vagy több kimeneti formátum megadása opcionális fájlnévvel. -w | --watch Watch directory. -i | --info Show tests environment info and exit. --setup Script for runner setup. - --temp Path to temporary directory. Default: sys_get_temp_dir(). + --temp Az ideiglenes könyvtár elérési útvonala. Alapértelmezett a sys_get_temp_dir() által. --colors [1|0] Enable or disable colors. --coverage Generate code coverage report to file. --coverage-src Path to source code. @@ -94,15 +94,6 @@ Megadja, hogy a tesztek futtatásakor melyik `php.ini` oldalt használja a rends Egy rendszerszintű `php.ini` kerül felhasználásra. Tehát UNIX platformon az összes `/etc/php/{sapi}/conf.d/*.ini` fájl is. Lásd a [saját php.ini |#Own php.ini] részt. -''-l | --log '' .[filter] -------------------------------- -A tesztelés előrehaladása kiíródik a fájlba. Minden sikertelen, kihagyott és sikeres tesztet: - -/--pre .[terminal] -tester --log /var/log/tests.log tests -\-- - - -d .[filter] ------------------------ A tesztek PHP konfigurációs direktíva értékének beállítása. A paraméter többször is használható. @@ -127,13 +118,14 @@ A tesztelő az első sikertelen tesztnél leállítja a tesztelést. A tesztek futtatása egy `` párhuzamos előfeldolgozásban. Az alapértelmezett érték 8. Ha a teszteket sorban szeretnénk futtatni, akkor az 1 értéket használjuk. --o .[filter] -------------------------------------- -Kimeneti formátum. Az alapértelmezett a konzol formátum. +-o .[filter] +----------------------------------------- +Kimeneti formátum. Az alapértelmezett a konzol formátum. Megadhatja annak a fájlnak a nevét, amelybe a kimenetet írja (pl. `-o junit:output.xml`). A `-o` opciót többször is megismételhetjük, hogy egyszerre több formátumot generáljunk. - `console`: ugyanaz, mint az alapértelmezett, de az ASCII logó ebben az esetben nem kerül kiírásra. - `tap`: gépi feldolgozásra alkalmas [TAP formátum |https://en.wikipedia.org/wiki/Test_Anything_Protocol]. - `junit`: JUnit XML formátum, gépi feldolgozásra is alkalmas. +- `log`: A tesztelés előrehaladásának kimenete. Minden sikertelen, kihagyott és sikeres tesztet - `none`: semmi sem kerül kinyomtatásra diff --git a/tester/it/running-tests.texy b/tester/it/running-tests.texy index e3d685a801..2288a0f595 100644 --- a/tester/it/running-tests.texy +++ b/tester/it/running-tests.texy @@ -58,16 +58,16 @@ Options: -p Specify PHP interpreter to run (default: php). -c Look for php.ini file (or look in directory) . -C Use system-wide php.ini. - -l | --log Write log to file . -d ... Define INI entry 'key' with value 'value'. -s Show information about skipped tests. --stop-on-fail Stop execution upon the first failure. -j Run jobs in parallel (default: 8). - -o Specify output format. + -o (ad esempio -o junit:output.xml) + Specifica uno o più formati di output con un nome di file opzionale. -w | --watch Watch directory. -i | --info Show tests environment info and exit. --setup Script for runner setup. - --temp Path to temporary directory. Default: sys_get_temp_dir(). + --temp Percorso della directory temporanea. Predefinito da sys_get_temp_dir(). --colors [1|0] Enable or disable colors. --coverage Generate code coverage report to file. --coverage-src Path to source code. @@ -94,15 +94,6 @@ Specifica quale `php.ini` sarà usato durante l'esecuzione dei test. Per imposta Viene utilizzato un `php.ini` a livello di sistema. Quindi, su piattaforma UNIX, anche tutti i file `/etc/php/{sapi}/conf.d/*.ini`. Vedere la sezione [php.ini |#Own php.ini]. -''-l | --log '' .[filter] -------------------------------- -Il progresso dei test viene scritto nel file. Tutti i test falliti, saltati e anche quelli riusciti: - -/--pre .[terminal] -tester --log /var/log/tests.log tests -\-- - - -d .[filter] ------------------------ Imposta il valore della direttiva di configurazione PHP per i test. Il parametro può essere usato più volte. @@ -127,13 +118,14 @@ Il tester interrompe il test al primo fallimento. I test vengono eseguiti in un `` in parallelo. Il valore predefinito è 8. Se si desidera eseguire i test in serie, si utilizza il valore 1. --o .[filter] -------------------------------------- -Formato di output. Il formato predefinito è quello della console. +-o .[filter] +----------------------------------------- +Formato di uscita. Il formato predefinito è quello della console. È possibile specificare il nome del file in cui verrà scritto l'output (ad esempio, `-o junit:output.xml`). L'opzione `-o` può essere ripetuta più volte per generare più formati contemporaneamente. - `console`: uguale a quello predefinito, ma in questo caso il logo ASCII non viene stampato - `tap`: [formato TAP |https://en.wikipedia.org/wiki/Test_Anything_Protocol] adatto all'elaborazione automatica - `junit`: formato XML JUnit, appropriato anche per l'elaborazione meccanica +- `log`: Visualizza l'avanzamento dei test. Tutti i test falliti, saltati e anche quelli riusciti - `none`: non viene stampato nulla diff --git a/tester/pl/running-tests.texy b/tester/pl/running-tests.texy index f4f3a9625e..9797f65a33 100644 --- a/tester/pl/running-tests.texy +++ b/tester/pl/running-tests.texy @@ -58,16 +58,16 @@ Options: -p Specify PHP interpreter to run (default: php). -c Look for php.ini file (or look in directory) . -C Use system-wide php.ini. - -l | --log Write log to file . -d ... Define INI entry 'key' with value 'value'. -s Show information about skipped tests. --stop-on-fail Stop execution upon the first failure. -j Run jobs in parallel (default: 8). - -o Specify output format. + -o (np. -o junit:output.xml) + Określa jeden lub więcej formatów wyjściowych z opcjonalną nazwą pliku. -w | --watch Watch directory. -i | --info Show tests environment info and exit. --setup Script for runner setup. - --temp Path to temporary directory. Default: sys_get_temp_dir(). + --temp Ścieżka do katalogu tymczasowego. Domyślna przez sys_get_temp_dir(). --colors [1|0] Enable or disable colors. --coverage Generate code coverage report to file. --coverage-src Path to source code. @@ -94,15 +94,6 @@ Określa, która strona `php.ini` będzie używana podczas uruchamiania testów. Używany jest ogólnosystemowy `php.ini`. Czyli na platformie UNIX wszystkie pliki `/etc/php/{sapi}/conf.d/*.ini` również. Patrz rozdział [Własny php.ini |#Own php.ini]. -''-l | --log '' .[filter] -------------------------------- -Postęp testów jest zapisywany do pliku. Wszystkie nieudane, pominięte, a także udane testy: - -/--pre .[terminal] -tester --log /var/log/tests.log tests -\-- - - -d .[filter] ------------------------ Ustawia wartość dyrektywy konfiguracyjnej PHP dla testów. Parametr może być użyty wielokrotnie. @@ -127,13 +118,14 @@ Tester zatrzymuje testowanie po pierwszym nieudanym teście. Testy są uruchamiane w `` równoległych procesach. Domyślna wartość to 8. Jeśli chcemy uruchamiać testy szeregowo, używamy wartości 1. --o .[filter] -------------------------------------- -Format wyjścia. Domyślnie jest to format konsoli. +-o .[filter] +----------------------------------------- +Format wyjścia. Domyślnie jest to format konsolowy. Można określić nazwę pliku, do którego zostaną zapisane dane wyjściowe (np. `-o junit:output.xml`). Opcja `-o` może być powtarzana wielokrotnie w celu wygenerowania wielu formatów jednocześnie. - `console`: taki sam jak domyślny, ale w tym przypadku nie jest wypisywane logo ASCII - `tap`: [format TAP |https://en.wikipedia.org/wiki/Test_Anything_Protocol] odpowiedni do przetwarzania maszynowego - `junit`: format JUnit XML, odpowiedni również do przetwarzania maszynowego +- `log`: Wyświetla postęp testowania. Wszystkie nieudane, pominięte, a także udane testy - `none`: nic nie jest drukowane diff --git a/tester/pt/running-tests.texy b/tester/pt/running-tests.texy index 0621d3f451..74f8b6d440 100644 --- a/tester/pt/running-tests.texy +++ b/tester/pt/running-tests.texy @@ -58,16 +58,16 @@ Options: -p Specify PHP interpreter to run (default: php). -c Look for php.ini file (or look in directory) . -C Use system-wide php.ini. - -l | --log Write log to file . -d ... Define INI entry 'key' with value 'value'. -s Show information about skipped tests. --stop-on-fail Stop execution upon the first failure. -j Run jobs in parallel (default: 8). - -o Specify output format. + -o (por exemplo, -o junit:output.xml) + Especifique um ou mais formatos de saída com um nome de arquivo opcional. -w | --watch Watch directory. -i | --info Show tests environment info and exit. --setup Script for runner setup. - --temp Path to temporary directory. Default: sys_get_temp_dir(). + --temp Caminho para o diretório temporário. Padrão por sys_get_temp_dir(). --colors [1|0] Enable or disable colors. --coverage Generate code coverage report to file. --coverage-src Path to source code. @@ -94,15 +94,6 @@ Especifica qual `php.ini` será usado ao executar testes. Por padrão, nenhum ph É utilizado um sistema de todo o sistema `php.ini`. Assim, na plataforma UNIX, todos os arquivos `/etc/php/{sapi}/conf.d/*.ini` também são utilizados. Veja a seção [php.ini Próprio |#Own php.ini]. -"'-l | --log "'". .[filter] ---------------------------------- -Os testes de progresso são escritos em arquivo. Todos os testes falharam, saltaram e também foram bem-sucedidos: - -/--pre .[terminal] -tester --log /var/log/tests.log tests -\-- - - -d .[filter] ------------------------ Define o valor da diretiva de configuração PHP para testes. O parâmetro pode ser usado várias vezes. @@ -127,13 +118,14 @@ O testador interrompe os testes após o primeiro teste reprovado. Os testes são realizados em um `` precessos paralelos. O valor padrão é 8. Se desejarmos realizar testes em série, usamos o valor 1. --o .[filter] -------------------------------------- -Formato de saída. O formato padrão é o formato do console. +-o .[filter] +----------------------------------------- +Formato de saída. O padrão é o formato do console. Você pode especificar o nome do arquivo no qual a saída será gravada (por exemplo, `-o junit:output.xml`). A opção `-o` pode ser repetida várias vezes para gerar vários formatos de uma só vez. - `console`: o mesmo que o padrão, mas o logotipo ASCII não é impresso neste caso - `tap`: [Formato TAP |https://en.wikipedia.org/wiki/Test_Anything_Protocol] apropriado para o processamento de máquinas - `junit`: formato JUnit XML, apropriado também para processamento em máquinas +- `log`: Exibe o progresso do teste. Todos os testes falhos, ignorados e também os bem-sucedidos - `none`: nada é impresso diff --git a/tester/ro/running-tests.texy b/tester/ro/running-tests.texy index 5563f703e0..93d917d6e4 100644 --- a/tester/ro/running-tests.texy +++ b/tester/ro/running-tests.texy @@ -58,16 +58,16 @@ Options: -p Specify PHP interpreter to run (default: php). -c Look for php.ini file (or look in directory) . -C Use system-wide php.ini. - -l | --log Write log to file . -d ... Define INI entry 'key' with value 'value'. -s Show information about skipped tests. --stop-on-fail Stop execution upon the first failure. -j Run jobs in parallel (default: 8). - -o Specify output format. + -o (de exemplu, -o junit:output.xml) + Specifică unul sau mai multe formate de ieșire cu nume de fișier opțional. -w | --watch Watch directory. -i | --info Show tests environment info and exit. --setup Script for runner setup. - --temp Path to temporary directory. Default: sys_get_temp_dir(). + --temp Calea către directorul temporar. Predefinit de sys_get_temp_dir(). --colors [1|0] Enable or disable colors. --coverage Generate code coverage report to file. --coverage-src Path to source code. @@ -94,15 +94,6 @@ Specifică ce `php.ini` va fi utilizat la rularea testelor. În mod implicit, nu Se utilizează un sistem la nivel de sistem `php.ini`. Deci, pe platforma UNIX, toate fișierele `/etc/php/{sapi}/conf.d/*.ini`. A se vedea secțiunea [Own php.ini |#Own php.ini]. -''-l | --log '' .[filter] -------------------------------- -Progresul testării este scris în fișier. Toate testele eșuate, sărite, dar și cele reușite: - -/--pre .[terminal] -tester --log /var/log/tests.log tests -\-- - - -d .[filter] ------------------------ Stabilește valoarea directivei de configurare PHP pentru teste. Parametrul poate fi utilizat de mai multe ori. @@ -127,13 +118,14 @@ Testerul oprește testarea la primul test eșuat. Testele se execută în `` precesiuni paralele. Valoarea implicită este 8. Dacă dorim să rulăm testele în serie, folosim valoarea 1. --o .[filter] -------------------------------------- -Format de ieșire. Formatul implicit este cel de consolă. +-o .[filter] +----------------------------------------- +Format de ieșire. Formatul implicit este cel de consolă. Puteți specifica numele fișierului în care va fi scrisă ieșirea (de exemplu, `-o junit:output.xml`). Opțiunea `-o` poate fi repetată de mai multe ori pentru a genera mai multe formate deodată. - `console`: la fel ca în mod implicit, dar logo-ul ASCII nu este tipărit în acest caz. - `tap`: [format TAP |https://en.wikipedia.org/wiki/Test_Anything_Protocol] adecvat pentru procesarea pe mașină - `junit`: format JUnit XML, adecvat și pentru procesarea pe mașină +- `log`: Afișează progresul testelor. Toate testele eșuate, sărite și, de asemenea, cele reușite - `none`: nu se tipărește nimic diff --git a/tester/ru/running-tests.texy b/tester/ru/running-tests.texy index 3ab154cdae..9044021024 100644 --- a/tester/ru/running-tests.texy +++ b/tester/ru/running-tests.texy @@ -58,16 +58,16 @@ PHP 7.4.8 (cli) | php -n | 8 threads -p <путь> Укажите интерпретатор PHP для запуска (по умолчанию: php). -c Искать php.ini файл (или искать в директории) . -C Использовать общесистемный php.ini. - -l | --log <путь> Запись журнала в файл <путь>. -d <ключ=значение>... Определить INI-запись 'key' со значением 'value'. -s Показать информацию о пропущенных тестах. --stop-on-fail Остановить выполнение при первом сбое. -j Выполнять заданий параллельно (по умолчанию: 8). - -o Указать формат вывода. + -o (например, -o junit:output.xml) + Укажите один или несколько выходных форматов с необязательным именем файла. -w | --watch <путь> Каталог просмотра. -i | --info Показать информацию об окружении тестов и выйти. --setup <путь> Сценарий для настройки бегущей строки. - --temp <путь> Путь к временному каталогу. По умолчанию: sys_get_temp_dir(). + --temp Путь к временному каталогу. По умолчанию определяется функцией sys_get_temp_dir(). --colors [1|0] Включить или отключить цвета. --coverage <путь> Генерировать отчет о покрытии кода в файл. --coverage-src <путь> Путь к исходному коду. @@ -94,15 +94,6 @@ tester -p /home/user/php-7.2.0-beta/php-cgi tests Используется общесистемный `php.ini`. Поэтому на платформе UNIX все файлы `/etc/php/{sapi}/conf.d/*.ini` тоже. См. раздел [Собственный php.ini |#Own php.ini]. -'' -l | --log '' .[filter] --------------------------------- -Ход тестирования записывается в файл. Все неудачные, пропущенные, а также успешные тесты: - -/--pre .[terminal] -tester --log /var/log/tests.log tests -\-- - - -d .[filter] ------------------------ Устанавливает значение директивы конфигурации PHP для тестов. Параметр может быть использован несколько раз. @@ -127,13 +118,14 @@ tester -d max_execution_time=20 Тесты запускаются в `` параллельно. Значение по умолчанию - 8. Если мы хотим запускать тесты последовательно, мы используем значение 1. --o .[filter] -------------------------------------- -Формат вывода. По умолчанию - консольный формат. +-o .[filter] +----------------------------------------- +Формат вывода. По умолчанию используется консольный формат. Вы можете указать имя файла, в который будет записан вывод (например, `-o junit:output.xml`). Опцию `-o` можно повторить несколько раз, чтобы сгенерировать несколько форматов одновременно. - `console`: то же, что и по умолчанию, но ASCII-логотип в этом случае не печатается. - `tap`: [формат TAP |https://en.wikipedia.org/wiki/Test_Anything_Protocol], подходящий для машинной обработки - `junit`: формат JUnit XML, также подходящий для машинной обработки. +- `log`: Выводит информацию о ходе тестирования. Все неудачные, пропущенные, а также успешные тесты - `none`: ничего не печатается diff --git a/tester/sl/running-tests.texy b/tester/sl/running-tests.texy index 716d247f7c..3008c94407 100644 --- a/tester/sl/running-tests.texy +++ b/tester/sl/running-tests.texy @@ -58,16 +58,16 @@ Options: -p Specify PHP interpreter to run (default: php). -c Look for php.ini file (or look in directory) . -C Use system-wide php.ini. - -l | --log Write log to file . -d ... Define INI entry 'key' with value 'value'. -s Show information about skipped tests. --stop-on-fail Stop execution upon the first failure. -j Run jobs in parallel (default: 8). - -o Specify output format. + -o (npr. -o junit:output.xml) + Določite enega ali več izhodnih formatov z neobveznim imenom datoteke. -w | --watch Watch directory. -i | --info Show tests environment info and exit. --setup Script for runner setup. - --temp Path to temporary directory. Default: sys_get_temp_dir(). + --temp Pot do začasnega imenika. Privzeto s sys_get_temp_dir(). --colors [1|0] Enable or disable colors. --coverage Generate code coverage report to file. --coverage-src Path to source code. @@ -94,15 +94,6 @@ Določa, kateri `php.ini` se bo uporabljal pri izvajanju testov. Privzeto se ne Uporabi se sistemski `php.ini`. Tako so na platformi UNIX uporabljene tudi vse datoteke `/etc/php/{sapi}/conf.d/*.ini`. Oglejte si razdelek [Lastni php.ini |#Own php.ini]. -''-l | --log '' .[filter] -------------------------------- -Potek testiranja se zapiše v datoteko. Vsi neuspešni, preskočeni in tudi uspešni testi: - -/--pre .[terminal] -tester --log /var/log/tests.log tests -\-- - - -d .[filter] ------------------------ Nastavi vrednost konfiguracijske direktive PHP za teste. Parameter lahko uporabite večkrat. @@ -127,13 +118,14 @@ Tester ustavi testiranje ob prvem neuspešnem testu. Testi se izvajajo v `` vzporednih procesih. Privzeta vrednost je 8. Če želimo teste izvajati zaporedno, uporabimo vrednost 1. --o .[filter] -------------------------------------- -Izhodna oblika. Privzeta je konzolna oblika. +-o .[filter] +----------------------------------------- +Izhodni format. Privzeta je konzolna oblika. Določite lahko ime datoteke, v katero se bo zapisal izpis (npr. `-o junit:output.xml`). Možnost `-o` lahko večkrat ponovite, da ustvarite več formatov naenkrat. - `console`: enako kot privzeto, vendar se v tem primeru logotip ASCII ne izpiše. - `tap`: [format TAP, |https://en.wikipedia.org/wiki/Test_Anything_Protocol] primeren za strojno obdelavo - `junit`: format JUnit XML, primeren tudi za strojno obdelavo +- `log`: Izpis poteka testiranja. Vsi neuspešni, preskočeni in tudi uspešni testi - `none`: nič se ne izpiše diff --git a/tester/tr/running-tests.texy b/tester/tr/running-tests.texy index 33eb45386c..fe795109c5 100644 --- a/tester/tr/running-tests.texy +++ b/tester/tr/running-tests.texy @@ -58,16 +58,16 @@ Options: -p Specify PHP interpreter to run (default: php). -c Look for php.ini file (or look in directory) . -C Use system-wide php.ini. - -l | --log Write log to file . -d ... Define INI entry 'key' with value 'value'. -s Show information about skipped tests. --stop-on-fail Stop execution upon the first failure. -j Run jobs in parallel (default: 8). - -o Specify output format. + -o (örneğin -o junit:output.xml) + İsteğe bağlı dosya adıyla birlikte bir veya daha fazla çıktı biçimi belirtin. -w | --watch Watch directory. -i | --info Show tests environment info and exit. --setup Script for runner setup. - --temp Path to temporary directory. Default: sys_get_temp_dir(). + --temp Geçici dizine giden yol. Varsayılan değer sys_get_temp_dir(). --colors [1|0] Enable or disable colors. --coverage Generate code coverage report to file. --coverage-src Path to source code. @@ -94,15 +94,6 @@ Testleri çalıştırırken hangi `php.ini` adresinin kullanılacağını belirt Sistem genelinde bir `php.ini` kullanılır. Yani UNIX platformunda, tüm `/etc/php/{sapi}/conf.d/*.ini` dosyaları da. [Kendi php.ini |#Own php.ini] bölümüne bakın. -''-l | --log '' .[filter] -------------------------------- -Test ilerlemesi dosyaya yazılır. Tüm başarısız, atlanmış ve ayrıca başarılı testler: - -/--pre .[terminal] -tester --log /var/log/tests.log tests -\-- - - -d .[filter] ------------------------ Sınamalar için PHP yapılandırma yönergesinin değerini ayarlar. Değiştirge birden çok kez kullanılabilir. @@ -127,13 +118,14 @@ Test cihazı ilk başarısız testte testi durdurur. Testler bir `` paralel ön işlemler. Varsayılan değer 8'dir. Testleri seri olarak çalıştırmak istiyorsak 1 değerini kullanırız. --o .[filter] -------------------------------------- -Çıktı biçimi. Varsayılan biçim konsol biçimidir. +-o .[filter] +----------------------------------------- +Çıktı biçimi. Varsayılan biçim konsol biçimidir. Çıktının içine yazılacağı dosyanın adını belirtebilirsiniz (örneğin, `-o junit:output.xml`). Aynı anda birden fazla format oluşturmak için `-o` seçeneği birden fazla kez tekrarlanabilir. - `console`: varsayılan ile aynı, ancak ASCII logosu bu durumda yazdırılmaz - `tap`: Makine işlemesi için uygun [TAP formatı |https://en.wikipedia.org/wiki/Test_Anything_Protocol] - `junit`: JUnit XML formatı, makine işlemesi için de uygun +- `log`: Test ilerlemesini çıktılar. Tüm başarısız, atlanmış ve ayrıca başarılı testler - `none`: hiçbir şey yazdırılmaz diff --git a/tester/uk/running-tests.texy b/tester/uk/running-tests.texy index 51c1835d90..3b9ca8bdbc 100644 --- a/tester/uk/running-tests.texy +++ b/tester/uk/running-tests.texy @@ -58,16 +58,16 @@ PHP 7.4.8 (cli) | php -n | 8 threads -p <путь> Укажите интерпретатор PHP для запуска (по умолчанию: php). -c Искать php.ini файл (или искать в директории) . -C Использовать общесистемный php.ini. - -l | --log <путь> Запись журнала в файл <путь>. -d <ключ=значение>... Определить INI-запись 'key' со значением 'value'. -s Показать информацию о пропущенных тестах. --stop-on-fail Остановить выполнение при первом сбое. -j Выполнять заданий параллельно (по умолчанию: 8). - -o Указать формат вывода. + -o (наприклад, -o junit:output.xml) + Вкажіть один або декілька форматів виводу з необов'язковим ім'ям файлу. -w | --watch <путь> Каталог просмотра. -i | --info Показать информацию об окружении тестов и выйти. --setup <путь> Сценарий для настройки бегущей строки. - --temp <путь> Путь к временному каталогу. По умолчанию: sys_get_temp_dir(). + --temp Шлях до тимчасового каталогу. За замовчуванням визначається функцією sys_get_temp_dir(). --colors [1|0] Включить или отключить цвета. --coverage <путь> Генерировать отчет о покрытии кода в файл. --coverage-src <путь> Путь к исходному коду. @@ -94,15 +94,6 @@ tester -p /home/user/php-7.2.0-beta/php-cgi tests Використовується загальносистемний `php.ini`. Отже, на платформі UNIX всі файли `/etc/php/{sapi}/conf.d/*.ini` також. Див. розділ [Власний php.ini |#Own php.ini]. -''-l | --log '' .[filter] -------------------------------- -Прогрес тестування записується у файл. Всі невдалі, пропущені, а також успішні тести: - -/--pre .[terminal] -tester --log /var/log/tests.log tests -\-- - - -d .[filter] ------------------------ Задає значення директиви конфігурації PHP для тестів. Параметр можна використовувати декілька разів. @@ -127,13 +118,14 @@ tester -d max_execution_time=20 Тести виконуються в `` паралельними прецесіями. Значення за замовчуванням 8. Якщо ми хочемо запускати тести послідовно, ми використовуємо значення 1. --o .[filter] -------------------------------------- -Формат виводу. За замовчуванням - формат консолі. +-o .[filter] +----------------------------------------- +Формат виводу. За замовчуванням використовується формат консолі. Ви можете вказати назву файлу, до якого буде записано вивід (наприклад, `-o junit:output.xml`). Параметр `-o` можна повторити декілька разів, щоб згенерувати одразу декілька форматів. - `console`: те саме, що і за замовчуванням, але у цьому випадку не виводиться ASCII-логотип - `tap`: [формат TAP |https://en.wikipedia.org/wiki/Test_Anything_Protocol], придатний для машинної обробки - `junit`: формат JUnit XML, також придатний для машинної обробки +- `log`: Прогрес тестування вихідних даних. Всі невдалі, пропущені та успішні тести - `none`: нічого не друкується From b447533eb51d785fcf146c096aba6dadb5624536 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sun, 21 Jan 2024 17:42:21 +0100 Subject: [PATCH 048/137] nette/tester 2.5.2 --- tester/bg/guide.texy | 4 ++-- tester/bg/helpers.texy | 2 +- tester/bg/running-tests.texy | 13 +++++++------ tester/cs/guide.texy | 4 ++-- tester/cs/helpers.texy | 2 +- tester/cs/running-tests.texy | 13 +++++++------ tester/de/guide.texy | 4 ++-- tester/de/helpers.texy | 2 +- tester/de/running-tests.texy | 13 +++++++------ tester/el/guide.texy | 4 ++-- tester/el/helpers.texy | 2 +- tester/el/running-tests.texy | 13 +++++++------ tester/en/guide.texy | 4 ++-- tester/en/helpers.texy | 2 +- tester/en/running-tests.texy | 13 +++++++------ tester/es/guide.texy | 4 ++-- tester/es/helpers.texy | 2 +- tester/es/running-tests.texy | 13 +++++++------ tester/fr/guide.texy | 4 ++-- tester/fr/helpers.texy | 2 +- tester/fr/running-tests.texy | 13 +++++++------ tester/hu/guide.texy | 4 ++-- tester/hu/helpers.texy | 2 +- tester/hu/running-tests.texy | 13 +++++++------ tester/it/guide.texy | 4 ++-- tester/it/helpers.texy | 2 +- tester/it/running-tests.texy | 13 +++++++------ tester/pl/guide.texy | 4 ++-- tester/pl/helpers.texy | 2 +- tester/pl/running-tests.texy | 13 +++++++------ tester/pt/guide.texy | 4 ++-- tester/pt/helpers.texy | 2 +- tester/pt/running-tests.texy | 13 +++++++------ tester/ro/guide.texy | 4 ++-- tester/ro/helpers.texy | 2 +- tester/ro/running-tests.texy | 13 +++++++------ tester/ru/guide.texy | 4 ++-- tester/ru/helpers.texy | 2 +- tester/ru/running-tests.texy | 13 +++++++------ tester/sl/guide.texy | 4 ++-- tester/sl/helpers.texy | 2 +- tester/sl/running-tests.texy | 13 +++++++------ tester/tr/guide.texy | 4 ++-- tester/tr/helpers.texy | 2 +- tester/tr/running-tests.texy | 13 +++++++------ tester/uk/guide.texy | 4 ++-- tester/uk/helpers.texy | 2 +- tester/uk/running-tests.texy | 13 +++++++------ 48 files changed, 160 insertions(+), 144 deletions(-) diff --git a/tester/bg/guide.texy b/tester/bg/guide.texy index 00093815da..009f594bb4 100644 --- a/tester/bg/guide.texy +++ b/tester/bg/guide.texy @@ -116,10 +116,10 @@ Nette Tester претърсва посочената директория и в /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. -PHP 7.4.8 (cli) | php -n | 8 threads +PHP 8.3.2 (cli) | php -n | 8 threads ........s................F......... diff --git a/tester/bg/helpers.texy b/tester/bg/helpers.texy index a233013643..4ece019d59 100644 --- a/tester/bg/helpers.texy +++ b/tester/bg/helpers.texy @@ -119,7 +119,7 @@ Environment::setup() .[filter] Environment::setupFunctions() .[filter]{data-version:2.5} --------------------------------------------------------- -Създава глобални функции `test()`, `setUp()` и `tearDown()`, на които могат да се разделят тестовете. +Създава глобални функции `test()`, `testException()`, `setUp()` и `tearDown()`, на които могат да се разделят тестовете. ```php test('test description', function () { diff --git a/tester/bg/running-tests.texy b/tester/bg/running-tests.texy index 4fff8846a6..a45ac599a8 100644 --- a/tester/bg/running-tests.texy +++ b/tester/bg/running-tests.texy @@ -23,10 +23,10 @@ vendor/bin/tester . /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. -PHP 7.4.8 (cli) | php -n | 8 threads +PHP 8.3.2 (cli) | php -n | 8 threads ........s.......................... @@ -49,7 +49,7 @@ PHP 7.4.8 (cli) | php -n | 8 threads /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Использование: tester [параметры] [<тестовый файл> | <каталог>]... @@ -62,7 +62,7 @@ PHP 7.4.8 (cli) | php -n | 8 threads -s Показать информацию о пропущенных тестах. --stop-on-fail Остановить выполнение при первом сбое. -j Выполнять заданий параллельно (по умолчанию: 8). - -o (напр. -o junit:output.xml) + -o (напр. -o junit:output.xml) Посочете един или повече изходни формати с незадължително име на файл. -w | --watch <путь> Каталог просмотра. -i | --info Показать информацию об окружении тестов и выйти. @@ -118,11 +118,12 @@ tester -d max_execution_time=20 Тестовете се изпълняват в `` паралелни прецеси. Стойността по подразбиране е 8. Ако искаме да изпълняваме тестовете последователно, използваме стойност 1. --o .[filter] ------------------------------------------ +-o .[filter] +------------------------------------------------------- Изходен формат. По подразбиране е конзолният формат. Можете да посочите името на файла, в който ще бъде записан изходният файл (напр. `-o junit:output.xml`). Опцията `-o` може да се повтори многократно, за да се генерират няколко формата наведнъж. - `console`: същият като по подразбиране, но в този случай не се отпечатва ASCII логото +- `console-lines`: подобно на конзолата, но резултатът от всеки тест се изписва на отделен ред с повече информация - `tap`: [TAP формат, |https://en.wikipedia.org/wiki/Test_Anything_Protocol] подходящ за машинна обработка - `junit`: JUnit XML формат, подходящ и за машинна обработка - `log`: Извежда информация за хода на тестването. Всички неуспешни, пропуснати, а също и успешни тестове diff --git a/tester/cs/guide.texy b/tester/cs/guide.texy index 7c30f09214..d4781909c8 100644 --- a/tester/cs/guide.texy +++ b/tester/cs/guide.texy @@ -116,10 +116,10 @@ Výstup může vypadat takto: /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. -PHP 7.4.8 (cli) | php -n | 8 threads +PHP 8.3.2 (cli) | php -n | 8 threads ........s................F......... diff --git a/tester/cs/helpers.texy b/tester/cs/helpers.texy index 2677074240..d418974dc0 100644 --- a/tester/cs/helpers.texy +++ b/tester/cs/helpers.texy @@ -119,7 +119,7 @@ Environment::setup() .[filter] Environment::setupFunctions() .[filter]{data-version:2.5} --------------------------------------------------------- -Vytvoří globální funkce `test()`, `setUp()` a `tearDown()`, do kterých můžete členit testy. +Vytvoří globální funkce `test()`, `testException()`, `setUp()` a `tearDown()`, do kterých můžete členit testy. ```php test('popis testu', function () { diff --git a/tester/cs/running-tests.texy b/tester/cs/running-tests.texy index 574862fa20..c5b13ad249 100644 --- a/tester/cs/running-tests.texy +++ b/tester/cs/running-tests.texy @@ -23,10 +23,10 @@ Výstup může vypadat třeba takto: /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. -PHP 7.4.8 (cli) | php -n | 8 threads +PHP 8.3.2 (cli) | php -n | 8 threads ........s.......................... @@ -49,7 +49,7 @@ Přehled všech voleb příkazové řádky získáme spuštěním Testeru bez pa /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Usage: tester [options] [ | ]... @@ -62,7 +62,7 @@ Options: -s Show information about skipped tests. --stop-on-fail Stop execution upon the first failure. -j Run jobs in parallel (default: 8). - -o (e.g. -o junit:output.xml) + -o (e.g. -o junit:output.xml) Specify one or more output formats with optional file name. -w | --watch Watch directory. -i | --info Show tests environment info and exit. @@ -118,11 +118,12 @@ Tester zastaví testování u prvního selhávajícího testu. Určuje, kolik paralelních procesů s testy se spustí. Výchozí hodnota je 8. Chceme-li, aby všechny testy proběhly v sérii, použijeme hodnotu 1. --o .[filter] ------------------------------------------ +-o .[filter] +------------------------------------------------------- Nastaví formát výstupu. Výchozí je formát pro konzoli. Můžete uvést jméno souboru, do kterého se výstup zapíše (např `-o junit:output.xml`). Volbu `-o` lze zopakovat vícekrát a vygenerovat tak více formátů najednou. - `console`: shodné s výchozím formátem, ale v tomto případě se nezobrazí ASCII logo +- `console-lines`: podobné jako console, ale výsledek každého testu je uveden na samostatném řádku s dalšími informacemi - `tap`: [TAP formát |https://en.wikipedia.org/wiki/Test_Anything_Protocol] vhodný pro strojové zpracování - `junit`: XML formát JUnit, taktéž vhodný pro strojové zpracování - `log`: Výstupy průběhu testování. Všechny neúspěšné, přeskočené a také úspěšné testy diff --git a/tester/de/guide.texy b/tester/de/guide.texy index a3e2384cd0..647786a7f4 100644 --- a/tester/de/guide.texy +++ b/tester/de/guide.texy @@ -116,10 +116,10 @@ Die Ausgabe kann wie folgt aussehen: /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. -PHP 7.4.8 (cli) | php -n | 8 threads +PHP 8.3.2 (cli) | php -n | 8 threads ........s................F......... diff --git a/tester/de/helpers.texy b/tester/de/helpers.texy index 5bacb62f16..3428c3427f 100644 --- a/tester/de/helpers.texy +++ b/tester/de/helpers.texy @@ -119,7 +119,7 @@ Environment::setup() .[filter] Environment::setupFunctions() .[filter]{data-version:2.5} --------------------------------------------------------- -Erzeugt die globalen Funktionen `test()`, `setUp()` und `tearDown()`, in die Sie Tests aufteilen können. +Erzeugt die globalen Funktionen `test()`, `testException()`, `setUp()` und `tearDown()`, in die Sie Tests aufteilen können. ```php test('Testbeschreibung', function () { diff --git a/tester/de/running-tests.texy b/tester/de/running-tests.texy index 821ca8805d..67eb490415 100644 --- a/tester/de/running-tests.texy +++ b/tester/de/running-tests.texy @@ -23,10 +23,10 @@ Die Ausgabe kann wie folgt aussehen: /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. -PHP 7.4.8 (cli) | php -n | 8 threads +PHP 8.3.2 (cli) | php -n | 8 threads ........s.......................... @@ -49,7 +49,7 @@ Einen Überblick über die Kommandozeilenoptionen erhalten wir, indem wir den Te /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Usage: tester [options] [ | ]... @@ -62,7 +62,7 @@ Options: -s Show information about skipped tests. --stop-on-fail Stop execution upon the first failure. -j Run jobs in parallel (default: 8). - -o (z. B. -o junit:output.xml) + -o (z. B. -o junit:output.xml) Geben Sie ein oder mehrere Ausgabeformate mit optionalem Dateinamen an. -w | --watch Watch directory. -i | --info Show tests environment info and exit. @@ -118,11 +118,12 @@ Der Tester bricht den Test ab, sobald der erste Test fehlschlägt. Tests laufen in einem `` parallel abläuft. Der Standardwert ist 8. Wenn wir die Tests in Serie laufen lassen wollen, verwenden wir den Wert 1. --o .[filter] ------------------------------------------ +-o .[filter] +------------------------------------------------------- Ausgabeformat. Standardmäßig wird das Konsolenformat verwendet. Sie können den Namen der Datei angeben, in die die Ausgabe geschrieben werden soll (z. B. `-o junit:output.xml`). Die Option `-o` kann mehrmals wiederholt werden, um mehrere Formate auf einmal zu erzeugen. - `console`: wie Standard, aber das ASCII-Logo wird in diesem Fall nicht gedruckt +- `console-lines`: ähnlich wie die Konsole, aber das Ergebnis jedes Tests wird in einer separaten Zeile mit weiteren Informationen angezeigt - `tap`: [TAP-Format |https://en.wikipedia.org/wiki/Test_Anything_Protocol], geeignet für die maschinelle Verarbeitung - `junit`: JUnit XML-Format, auch für die maschinelle Verarbeitung geeignet - `log`: Gibt den Testfortschritt aus. Alle fehlgeschlagenen, übersprungenen und auch erfolgreichen Tests diff --git a/tester/el/guide.texy b/tester/el/guide.texy index 1209212079..184880141a 100644 --- a/tester/el/guide.texy +++ b/tester/el/guide.texy @@ -116,10 +116,10 @@ vendor/bin/tester . /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. -PHP 7.4.8 (cli) | php -n | 8 threads +PHP 8.3.2 (cli) | php -n | 8 threads ........s................F......... diff --git a/tester/el/helpers.texy b/tester/el/helpers.texy index 98e9a306d1..1a62106e61 100644 --- a/tester/el/helpers.texy +++ b/tester/el/helpers.texy @@ -119,7 +119,7 @@ Environment::setup() .[filter] Environment::setupFunctions() .[filter]{data-version:2.5} --------------------------------------------------------- -Δημιουργεί τις παγκόσμιες συναρτήσεις `test()`, `setUp()` και `tearDown()` στις οποίες μπορείτε να χωρίσετε τις δοκιμές. +Δημιουργεί τις παγκόσμιες συναρτήσεις `test()`, `testException()`, `setUp()` και `tearDown()` στις οποίες μπορείτε να χωρίσετε τις δοκιμές. ```php test('test description', function () { diff --git a/tester/el/running-tests.texy b/tester/el/running-tests.texy index 83e2214944..ae822f4283 100644 --- a/tester/el/running-tests.texy +++ b/tester/el/running-tests.texy @@ -23,10 +23,10 @@ vendor/bin/tester . /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. -PHP 7.4.8 (cli) | php -n | 8 threads +PHP 8.3.2 (cli) | php -n | 8 threads ........s.......................... @@ -49,7 +49,7 @@ PHP 7.4.8 (cli) | php -n | 8 threads /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Usage: tester [options] [ | ]... @@ -62,7 +62,7 @@ Options: -s Show information about skipped tests. --stop-on-fail Stop execution upon the first failure. -j Run jobs in parallel (default: 8). - -o (π.χ. -o junit:output.xml) + -o (π.χ. -o junit:output.xml) Καθορίστε μία ή περισσότερες μορφές εξόδου με προαιρετικό όνομα αρχείου. -w | --watch Watch directory. -i | --info Show tests environment info and exit. @@ -118,11 +118,12 @@ tester -d max_execution_time=20 Οι δοκιμές εκτελούνται σε ένα `` παράλληλες διεργασίες. Η προεπιλεγμένη τιμή είναι 8. Αν θέλουμε να εκτελούμε δοκιμές σε σειρά, χρησιμοποιούμε την τιμή 1. --o .[filter] ------------------------------------------ +-o .[filter] +------------------------------------------------------- Μορφή εξόδου. Η προεπιλογή είναι η μορφή κονσόλας. Μπορείτε να καθορίσετε το όνομα του αρχείου στο οποίο θα γραφτεί η έξοδος (π.χ. `-o junit:output.xml`). Η επιλογή `-o` μπορεί να επαναληφθεί πολλές φορές για την ταυτόχρονη παραγωγή πολλαπλών μορφών. - `console`: η ίδια με την προεπιλογή, αλλά το λογότυπο ASCII δεν εκτυπώνεται σε αυτή την περίπτωση. +- `console-lines`: παρόμοια με την κονσόλα, αλλά το αποτέλεσμα κάθε δοκιμής παρατίθεται σε ξεχωριστή γραμμή με περισσότερες πληροφορίες - `tap`: [Μορφή TAP |https://en.wikipedia.org/wiki/Test_Anything_Protocol] κατάλληλη για μηχανική επεξεργασία. - `junit`: Μορφή JUnit XML, κατάλληλη και για μηχανική επεξεργασία. - `log`: Εξάγει την πρόοδο των δοκιμών. Όλες οι αποτυχημένες, παραλειφθείσες και επιτυχημένες δοκιμές diff --git a/tester/en/guide.texy b/tester/en/guide.texy index 3e59c0a265..91fde34846 100644 --- a/tester/en/guide.texy +++ b/tester/en/guide.texy @@ -116,10 +116,10 @@ The output can look like this: /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. -PHP 7.4.8 (cli) | php -n | 8 threads +PHP 8.3.2 (cli) | php -n | 8 threads ........s................F......... diff --git a/tester/en/helpers.texy b/tester/en/helpers.texy index d6107abf65..63956a79ed 100644 --- a/tester/en/helpers.texy +++ b/tester/en/helpers.texy @@ -119,7 +119,7 @@ Environment::setup() .[filter] Environment::setupFunctions() .[filter]{data-version:2.5} --------------------------------------------------------- -Creates the global functions `test()`, `setUp()` and `tearDown()` into which you can split tests. +Creates the global functions `test()`, `testException()`, `setUp()` and `tearDown()` into which you can split tests. ```php test('test description', function () { diff --git a/tester/en/running-tests.texy b/tester/en/running-tests.texy index 1750ac6b52..a49726b70d 100644 --- a/tester/en/running-tests.texy +++ b/tester/en/running-tests.texy @@ -23,10 +23,10 @@ The output may look like: /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. -PHP 7.4.8 (cli) | php -n | 8 threads +PHP 8.3.2 (cli) | php -n | 8 threads ........s.......................... @@ -49,7 +49,7 @@ We obtain command-line options overview by running the Tester without parameters /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Usage: tester [options] [ | ]... @@ -62,7 +62,7 @@ Options: -s Show information about skipped tests. --stop-on-fail Stop execution upon the first failure. -j Run jobs in parallel (default: 8). - -o (e.g. -o junit:output.xml) + -o (e.g. -o junit:output.xml) Specify one or more output formats with optional file name. -w | --watch Watch directory. -i | --info Show tests environment info and exit. @@ -118,11 +118,12 @@ Tester stops testing upon the first failing test. Tests run in a `` parallel precesses. Default value is 8. If we wish to run tests in series, we use value 1. --o .[filter] ------------------------------------------ +-o .[filter] +------------------------------------------------------- Output format. Default is the console format. You can specify the name of the file into which the output will be written (e.g., `-o junit:output.xml`). The `-o` option can be repeated multiple times to generate multiple formats at once. - `console`: the same as default, but the ASCII logo is not printed in this case +- `console-lines`: similar to the console, but the result of each test is listed on a separate line with more information - `tap`: [TAP format |https://en.wikipedia.org/wiki/Test_Anything_Protocol] appropriate for machine processing - `junit`: JUnit XML format, appropriate for machine processing too - `log`: Outputs testing progress. All failed, skipped and also successful tests diff --git a/tester/es/guide.texy b/tester/es/guide.texy index 14a90f172e..438b62fb62 100644 --- a/tester/es/guide.texy +++ b/tester/es/guide.texy @@ -116,10 +116,10 @@ La salida puede tener este aspecto: /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. -PHP 7.4.8 (cli) | php -n | 8 threads +PHP 8.3.2 (cli) | php -n | 8 threads ........s................F......... diff --git a/tester/es/helpers.texy b/tester/es/helpers.texy index 158466bf52..8293e79f4b 100644 --- a/tester/es/helpers.texy +++ b/tester/es/helpers.texy @@ -119,7 +119,7 @@ Environment::setup() .[filter] Environment::setupFunctions() .[filter]{data-version:2.5} --------------------------------------------------------- -Crea las funciones globales `test()`, `setUp()` y `tearDown()` en las que se pueden dividir las pruebas. +Crea las funciones globales `test()`, `testException()`, `setUp()` y `tearDown()` en las que se pueden dividir las pruebas. ```php test('descripción de la prueba', function () { diff --git a/tester/es/running-tests.texy b/tester/es/running-tests.texy index bc13f7b3aa..e7add92adb 100644 --- a/tester/es/running-tests.texy +++ b/tester/es/running-tests.texy @@ -23,10 +23,10 @@ La salida puede tener el siguiente aspecto: /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. -PHP 7.4.8 (cli) | php -n | 8 threads +PHP 8.3.2 (cli) | php -n | 8 threads ........s.......................... @@ -49,7 +49,7 @@ Obtenemos una visión general de las opciones de la línea de comandos ejecutand /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Uso: tester [opciones] [ | ]... @@ -62,7 +62,7 @@ Opciones: -s Mostrar información sobre las pruebas omitidas. --stop-on-fail Detener la ejecución al primer fallo. -j Ejecutar trabajos en paralelo (por defecto: 8). - -o (por ejemplo, -o junit:output.xml) + -o (por ejemplo, -o junit:output.xml) Especifica uno o más formatos de salida con un nombre de archivo opcional. -w | --watch Directorio de vigilancia. -i | --info Mostrar información del entorno de pruebas y salir. @@ -118,11 +118,12 @@ El probador detiene la prueba al fallar la primera prueba. Las pruebas se ejecutan en `` precesos en paralelo. El valor por defecto es 8. Si deseamos ejecutar las pruebas en serie, utilizaremos el valor 1. --o .[filter] ------------------------------------------ +-o .[filter] +------------------------------------------------------- Formato de salida. Por defecto es el formato de consola. Puede especificar el nombre del archivo en el que se escribirá la salida (por ejemplo, `-o junit:output.xml`). La opción `-o` puede repetirse varias veces para generar varios formatos a la vez. - `console`: igual que por defecto, pero en este caso no se imprime el logotipo ASCII +- `console-lines`: similar a la consola, pero el resultado de cada prueba aparece en una línea separada con más información - `tap`: formato [TAP |https://en.wikipedia.org/wiki/Test_Anything_Protocol] apropiado para el procesamiento en máquina - `junit`: formato JUnit XML, apropiado también para el procesamiento en máquina - `log`: Muestra el progreso de las pruebas. Todas las pruebas fallidas, omitidas y también las exitosas diff --git a/tester/fr/guide.texy b/tester/fr/guide.texy index 07fde73948..2be1388e6b 100644 --- a/tester/fr/guide.texy +++ b/tester/fr/guide.texy @@ -116,10 +116,10 @@ La sortie peut ressembler à ceci : /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. -PHP 7.4.8 (cli) | php -n | 8 threads +PHP 8.3.2 (cli) | php -n | 8 threads ........s................F......... diff --git a/tester/fr/helpers.texy b/tester/fr/helpers.texy index 3e0ea8efe8..bfa3af317e 100644 --- a/tester/fr/helpers.texy +++ b/tester/fr/helpers.texy @@ -119,7 +119,7 @@ Environment::setup() .[filter] Environment::setupFunctions() .[filter]{data-version:2.5} --------------------------------------------------------- -Crée les fonctions globales `test()`, `setUp()` et `tearDown()` dans lesquelles vous pouvez diviser les tests. +Crée les fonctions globales `test()`, `testException()`, `setUp()` et `tearDown()` dans lesquelles vous pouvez diviser les tests. ```php test('test description', function () { diff --git a/tester/fr/running-tests.texy b/tester/fr/running-tests.texy index afcc23f843..c7cc661445 100644 --- a/tester/fr/running-tests.texy +++ b/tester/fr/running-tests.texy @@ -23,10 +23,10 @@ La sortie peut ressembler à ceci : /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. -PHP 7.4.8 (cli) | php -n | 8 threads +PHP 8.3.2 (cli) | php -n | 8 threads ........s.......................... @@ -49,7 +49,7 @@ Nous obtenons un aperçu des options de la ligne de commande en exécutant le Te /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Usage: tester [options] [ | ]... @@ -62,7 +62,7 @@ Options: -s Show information about skipped tests. --stop-on-fail Stop execution upon the first failure. -j Run jobs in parallel (default: 8). - -o (par exemple -o junit:output.xml) + -o (par exemple -o junit:output.xml) Spécifier un ou plusieurs formats de sortie avec un nom de fichier optionnel. -w | --watch Watch directory. -i | --info Show tests environment info and exit. @@ -118,11 +118,12 @@ Le testeur arrête les tests au premier échec. Les tests s'exécutent dans un `` parallèles. La valeur par défaut est 8. Si nous souhaitons exécuter les tests en série, nous utilisons la valeur 1. --o .[filter] ------------------------------------------ +-o .[filter] +------------------------------------------------------- Format de sortie. Le format par défaut est celui de la console. Vous pouvez spécifier le nom du fichier dans lequel la sortie sera écrite (par exemple, `-o junit:output.xml`). L'option `-o` peut être répétée plusieurs fois pour générer plusieurs formats à la fois. - `console`: identique à celui par défaut, mais le logo ASCII n'est pas imprimé dans ce cas +- `console-lines`: similaire à la console, mais le résultat de chaque test est listé sur une ligne séparée avec plus d'informations - `tap`: [format TAP |https://en.wikipedia.org/wiki/Test_Anything_Protocol] approprié au traitement machine - `junit`: format XML de JUnit, également approprié au traitement par machine - `log`: Affiche l'état d'avancement des tests. Tous les tests échoués, ignorés et réussis diff --git a/tester/hu/guide.texy b/tester/hu/guide.texy index 3364f06567..8048d58a88 100644 --- a/tester/hu/guide.texy +++ b/tester/hu/guide.texy @@ -116,10 +116,10 @@ A kimenet így nézhet ki: /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. -PHP 7.4.8 (cli) | php -n | 8 threads +PHP 8.3.2 (cli) | php -n | 8 threads ........s................F......... diff --git a/tester/hu/helpers.texy b/tester/hu/helpers.texy index 13e4a27c04..bf2f868a77 100644 --- a/tester/hu/helpers.texy +++ b/tester/hu/helpers.texy @@ -119,7 +119,7 @@ Environment::setup() .[filter] Environment::setupFunctions() .[filter]{data-version:2.5} --------------------------------------------------------- -Létrehozza a `test()`, `setUp()` és `tearDown()` globális függvényeket, amelyekre a teszteket feloszthatja. +Létrehozza a `test()`, `testException()`, `setUp()` és `tearDown()` globális függvényeket, amelyekre a teszteket feloszthatja. ```php test('test description', function () { diff --git a/tester/hu/running-tests.texy b/tester/hu/running-tests.texy index d618203f7a..ee1b5480a0 100644 --- a/tester/hu/running-tests.texy +++ b/tester/hu/running-tests.texy @@ -23,10 +23,10 @@ A kimenet így nézhet ki: /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. -PHP 7.4.8 (cli) | php -n | 8 threads +PHP 8.3.2 (cli) | php -n | 8 threads ........s.......................... @@ -49,7 +49,7 @@ A parancssori opciók áttekintését a Tester paraméterek nélküli vagy a `-h /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Usage: tester [options] [ | ]... @@ -62,7 +62,7 @@ Options: -s Show information about skipped tests. --stop-on-fail Stop execution upon the first failure. -j Run jobs in parallel (default: 8). - -o (pl. -o junit:output.xml) + -o (pl. -o junit:output.xml) Egy vagy több kimeneti formátum megadása opcionális fájlnévvel. -w | --watch Watch directory. -i | --info Show tests environment info and exit. @@ -118,11 +118,12 @@ A tesztelő az első sikertelen tesztnél leállítja a tesztelést. A tesztek futtatása egy `` párhuzamos előfeldolgozásban. Az alapértelmezett érték 8. Ha a teszteket sorban szeretnénk futtatni, akkor az 1 értéket használjuk. --o .[filter] ------------------------------------------ +-o .[filter] +------------------------------------------------------- Kimeneti formátum. Az alapértelmezett a konzol formátum. Megadhatja annak a fájlnak a nevét, amelybe a kimenetet írja (pl. `-o junit:output.xml`). A `-o` opciót többször is megismételhetjük, hogy egyszerre több formátumot generáljunk. - `console`: ugyanaz, mint az alapértelmezett, de az ASCII logó ebben az esetben nem kerül kiírásra. +- `console-lines`: hasonló a konzolhoz, de az egyes tesztek eredményei külön sorban, több információval szerepelnek - `tap`: gépi feldolgozásra alkalmas [TAP formátum |https://en.wikipedia.org/wiki/Test_Anything_Protocol]. - `junit`: JUnit XML formátum, gépi feldolgozásra is alkalmas. - `log`: A tesztelés előrehaladásának kimenete. Minden sikertelen, kihagyott és sikeres tesztet diff --git a/tester/it/guide.texy b/tester/it/guide.texy index 9055f6dce8..c8b830e795 100644 --- a/tester/it/guide.texy +++ b/tester/it/guide.texy @@ -116,10 +116,10 @@ L'output può essere simile a questo: /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. -PHP 7.4.8 (cli) | php -n | 8 threads +PHP 8.3.2 (cli) | php -n | 8 threads ........s................F......... diff --git a/tester/it/helpers.texy b/tester/it/helpers.texy index 2f48325d7f..24537ac55e 100644 --- a/tester/it/helpers.texy +++ b/tester/it/helpers.texy @@ -119,7 +119,7 @@ Environment::setup() .[filter] Environment::setupFunctions() .[filter]{data-version:2.5} --------------------------------------------------------- -Crea le funzioni globali `test()`, `setUp()` e `tearDown()` in cui è possibile suddividere i test. +Crea le funzioni globali `test()`, `testException()`, `setUp()` e `tearDown()` in cui è possibile suddividere i test. ```php test('test description', function () { diff --git a/tester/it/running-tests.texy b/tester/it/running-tests.texy index 2288a0f595..8e040201cb 100644 --- a/tester/it/running-tests.texy +++ b/tester/it/running-tests.texy @@ -23,10 +23,10 @@ L'output può apparire come: /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. -PHP 7.4.8 (cli) | php -n | 8 threads +PHP 8.3.2 (cli) | php -n | 8 threads ........s.......................... @@ -49,7 +49,7 @@ Otteniamo una panoramica delle opzioni da riga di comando eseguendo il Tester se /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Usage: tester [options] [ | ]... @@ -62,7 +62,7 @@ Options: -s Show information about skipped tests. --stop-on-fail Stop execution upon the first failure. -j Run jobs in parallel (default: 8). - -o (ad esempio -o junit:output.xml) + -o (ad esempio -o junit:output.xml) Specifica uno o più formati di output con un nome di file opzionale. -w | --watch Watch directory. -i | --info Show tests environment info and exit. @@ -118,11 +118,12 @@ Il tester interrompe il test al primo fallimento. I test vengono eseguiti in un `` in parallelo. Il valore predefinito è 8. Se si desidera eseguire i test in serie, si utilizza il valore 1. --o .[filter] ------------------------------------------ +-o .[filter] +------------------------------------------------------- Formato di uscita. Il formato predefinito è quello della console. È possibile specificare il nome del file in cui verrà scritto l'output (ad esempio, `-o junit:output.xml`). L'opzione `-o` può essere ripetuta più volte per generare più formati contemporaneamente. - `console`: uguale a quello predefinito, ma in questo caso il logo ASCII non viene stampato +- `console-lines`: simile alla console, ma il risultato di ogni test è elencato su una riga separata con maggiori informazioni - `tap`: [formato TAP |https://en.wikipedia.org/wiki/Test_Anything_Protocol] adatto all'elaborazione automatica - `junit`: formato XML JUnit, appropriato anche per l'elaborazione meccanica - `log`: Visualizza l'avanzamento dei test. Tutti i test falliti, saltati e anche quelli riusciti diff --git a/tester/pl/guide.texy b/tester/pl/guide.texy index 6b45f19fad..4f68adba4b 100644 --- a/tester/pl/guide.texy +++ b/tester/pl/guide.texy @@ -116,10 +116,10 @@ Dane wyjściowe mogą wyglądać tak: /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. -PHP 7.4.8 (cli) | php -n | 8 threads +PHP 8.3.2 (cli) | php -n | 8 threads ........s................F......... diff --git a/tester/pl/helpers.texy b/tester/pl/helpers.texy index 72bd8b7b52..c1bc600fb1 100644 --- a/tester/pl/helpers.texy +++ b/tester/pl/helpers.texy @@ -119,7 +119,7 @@ Environment::setup() .[filter] Environment::setupFunctions() .[filter]{data-version:2.5} --------------------------------------------------------- -Tworzy globalne funkcje `test()`, `setUp()`, i `tearDown()`, na które można podzielić swoje testy. +Tworzy globalne funkcje `test()`, `testException()`, `setUp()`, i `tearDown()`, na które można podzielić swoje testy. ```php test('popis testu', function () { diff --git a/tester/pl/running-tests.texy b/tester/pl/running-tests.texy index 9797f65a33..2fa84feefe 100644 --- a/tester/pl/running-tests.texy +++ b/tester/pl/running-tests.texy @@ -23,10 +23,10 @@ Dane wyjściowe mogą wyglądać jak: /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. -PHP 7.4.8 (cli) | php -n | 8 threads +PHP 8.3.2 (cli) | php -n | 8 threads ........s.......................... @@ -49,7 +49,7 @@ Przegląd opcji wiersza poleceń uzyskujemy uruchamiając Tester bez parametrów /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Usage: tester [options] [ | ]... @@ -62,7 +62,7 @@ Options: -s Show information about skipped tests. --stop-on-fail Stop execution upon the first failure. -j Run jobs in parallel (default: 8). - -o (np. -o junit:output.xml) + -o (np. -o junit:output.xml) Określa jeden lub więcej formatów wyjściowych z opcjonalną nazwą pliku. -w | --watch Watch directory. -i | --info Show tests environment info and exit. @@ -118,11 +118,12 @@ Tester zatrzymuje testowanie po pierwszym nieudanym teście. Testy są uruchamiane w `` równoległych procesach. Domyślna wartość to 8. Jeśli chcemy uruchamiać testy szeregowo, używamy wartości 1. --o .[filter] ------------------------------------------ +-o .[filter] +------------------------------------------------------- Format wyjścia. Domyślnie jest to format konsolowy. Można określić nazwę pliku, do którego zostaną zapisane dane wyjściowe (np. `-o junit:output.xml`). Opcja `-o` może być powtarzana wielokrotnie w celu wygenerowania wielu formatów jednocześnie. - `console`: taki sam jak domyślny, ale w tym przypadku nie jest wypisywane logo ASCII +- `console-lines`: podobny do konsoli, ale wynik każdego testu jest wyświetlany w osobnym wierszu z większą ilością informacji - `tap`: [format TAP |https://en.wikipedia.org/wiki/Test_Anything_Protocol] odpowiedni do przetwarzania maszynowego - `junit`: format JUnit XML, odpowiedni również do przetwarzania maszynowego - `log`: Wyświetla postęp testowania. Wszystkie nieudane, pominięte, a także udane testy diff --git a/tester/pt/guide.texy b/tester/pt/guide.texy index a30c297615..6f31106fc6 100644 --- a/tester/pt/guide.texy +++ b/tester/pt/guide.texy @@ -116,10 +116,10 @@ A saída pode ser assim: /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. -PHP 7.4.8 (cli) | php -n | 8 threads +PHP 8.3.2 (cli) | php -n | 8 threads ........s................F......... diff --git a/tester/pt/helpers.texy b/tester/pt/helpers.texy index 4b20d97442..9e52095a31 100644 --- a/tester/pt/helpers.texy +++ b/tester/pt/helpers.texy @@ -119,7 +119,7 @@ Environment::setup() .[filter] Environment::setupFunctions() .[filter]{data-version:2.5} --------------------------------------------------------- -Cria as funções globais `test()`, `setUp()` e `tearDown()`, nas quais é possível dividir os testes. +Cria as funções globais `test()`, `testException()`, `setUp()` e `tearDown()`, nas quais é possível dividir os testes. ```php test('test description', function () { diff --git a/tester/pt/running-tests.texy b/tester/pt/running-tests.texy index 74f8b6d440..8d06996771 100644 --- a/tester/pt/running-tests.texy +++ b/tester/pt/running-tests.texy @@ -23,10 +23,10 @@ O resultado pode ser parecido: /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. -PHP 7.4.8 (cli) | php -n | 8 threads +PHP 8.3.2 (cli) | php -n | 8 threads ........s.......................... @@ -49,7 +49,7 @@ Obtemos uma visão geral das opções de linha de comando executando o Tester se /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Usage: tester [options] [ | ]... @@ -62,7 +62,7 @@ Options: -s Show information about skipped tests. --stop-on-fail Stop execution upon the first failure. -j Run jobs in parallel (default: 8). - -o (por exemplo, -o junit:output.xml) + -o (por exemplo, -o junit:output.xml) Especifique um ou mais formatos de saída com um nome de arquivo opcional. -w | --watch Watch directory. -i | --info Show tests environment info and exit. @@ -118,11 +118,12 @@ O testador interrompe os testes após o primeiro teste reprovado. Os testes são realizados em um `` precessos paralelos. O valor padrão é 8. Se desejarmos realizar testes em série, usamos o valor 1. --o .[filter] ------------------------------------------ +-o .[filter] +------------------------------------------------------- Formato de saída. O padrão é o formato do console. Você pode especificar o nome do arquivo no qual a saída será gravada (por exemplo, `-o junit:output.xml`). A opção `-o` pode ser repetida várias vezes para gerar vários formatos de uma só vez. - `console`: o mesmo que o padrão, mas o logotipo ASCII não é impresso neste caso +- `console-lines`: semelhante ao console, mas o resultado de cada teste é listado em uma linha separada com mais informações - `tap`: [Formato TAP |https://en.wikipedia.org/wiki/Test_Anything_Protocol] apropriado para o processamento de máquinas - `junit`: formato JUnit XML, apropriado também para processamento em máquinas - `log`: Exibe o progresso do teste. Todos os testes falhos, ignorados e também os bem-sucedidos diff --git a/tester/ro/guide.texy b/tester/ro/guide.texy index ed8c9b083d..3078deac72 100644 --- a/tester/ro/guide.texy +++ b/tester/ro/guide.texy @@ -116,10 +116,10 @@ Rezultatul poate arăta astfel: /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. -PHP 7.4.8 (cli) | php -n | 8 threads +PHP 8.3.2 (cli) | php -n | 8 threads ........s................F......... diff --git a/tester/ro/helpers.texy b/tester/ro/helpers.texy index 9a53f54e34..df0565ba97 100644 --- a/tester/ro/helpers.texy +++ b/tester/ro/helpers.texy @@ -119,7 +119,7 @@ Environment::setup() .[filter] Environment::setupFunctions() .[filter]{data-version:2.5} --------------------------------------------------------- -Creează funcțiile globale `test()`, `setUp()` și `tearDown()` în care puteți împărți testele. +Creează funcțiile globale `test()`, `testException()`, `setUp()` și `tearDown()` în care puteți împărți testele. ```php test('test description', function () { diff --git a/tester/ro/running-tests.texy b/tester/ro/running-tests.texy index 93d917d6e4..788d8f03de 100644 --- a/tester/ro/running-tests.texy +++ b/tester/ro/running-tests.texy @@ -23,10 +23,10 @@ Rezultatul poate arăta astfel: /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. -PHP 7.4.8 (cli) | php -n | 8 threads +PHP 8.3.2 (cli) | php -n | 8 threads ........s.......................... @@ -49,7 +49,7 @@ Obținem prezentarea generală a opțiunilor din linia de comandă prin rularea /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Usage: tester [options] [ | ]... @@ -62,7 +62,7 @@ Options: -s Show information about skipped tests. --stop-on-fail Stop execution upon the first failure. -j Run jobs in parallel (default: 8). - -o (de exemplu, -o junit:output.xml) + -o (de exemplu, -o junit:output.xml) Specifică unul sau mai multe formate de ieșire cu nume de fișier opțional. -w | --watch Watch directory. -i | --info Show tests environment info and exit. @@ -118,11 +118,12 @@ Testerul oprește testarea la primul test eșuat. Testele se execută în `` precesiuni paralele. Valoarea implicită este 8. Dacă dorim să rulăm testele în serie, folosim valoarea 1. --o .[filter] ------------------------------------------ +-o .[filter] +------------------------------------------------------- Format de ieșire. Formatul implicit este cel de consolă. Puteți specifica numele fișierului în care va fi scrisă ieșirea (de exemplu, `-o junit:output.xml`). Opțiunea `-o` poate fi repetată de mai multe ori pentru a genera mai multe formate deodată. - `console`: la fel ca în mod implicit, dar logo-ul ASCII nu este tipărit în acest caz. +- `console-lines`: similar cu consola, dar rezultatul fiecărui test este listat pe o linie separată cu mai multe informații - `tap`: [format TAP |https://en.wikipedia.org/wiki/Test_Anything_Protocol] adecvat pentru procesarea pe mașină - `junit`: format JUnit XML, adecvat și pentru procesarea pe mașină - `log`: Afișează progresul testelor. Toate testele eșuate, sărite și, de asemenea, cele reușite diff --git a/tester/ru/guide.texy b/tester/ru/guide.texy index 789ec0cc63..532b61548e 100644 --- a/tester/ru/guide.texy +++ b/tester/ru/guide.texy @@ -116,10 +116,10 @@ vendor/bin/tester . /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. -PHP 7.4.8 (cli) | php -n | 8 threads +PHP 8.3.2 (cli) | php -n | 8 threads ........s................F......... diff --git a/tester/ru/helpers.texy b/tester/ru/helpers.texy index 87d907ec78..81f6692992 100644 --- a/tester/ru/helpers.texy +++ b/tester/ru/helpers.texy @@ -119,7 +119,7 @@ Environment::setup() .[filter] Environment::setupFunctions() .[filter]{data-version:2.5} --------------------------------------------------------- -Создает глобальные функции `test()`, `setUp()` и `tearDown()`, на которые можно разбить тесты. +Создает глобальные функции `test()`, `testException()`, `setUp()` и `tearDown()`, на которые можно разбить тесты. ```php test('описание теста', function () { diff --git a/tester/ru/running-tests.texy b/tester/ru/running-tests.texy index 9044021024..5525ed6591 100644 --- a/tester/ru/running-tests.texy +++ b/tester/ru/running-tests.texy @@ -23,10 +23,10 @@ vendor/bin/tester . /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. -PHP 7.4.8 (cli) | php -n | 8 threads +PHP 8.3.2 (cli) | php -n | 8 threads ........s.......................... @@ -49,7 +49,7 @@ PHP 7.4.8 (cli) | php -n | 8 threads /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Использование: tester [параметры] [<тестовый файл> | <каталог>]... @@ -62,7 +62,7 @@ PHP 7.4.8 (cli) | php -n | 8 threads -s Показать информацию о пропущенных тестах. --stop-on-fail Остановить выполнение при первом сбое. -j Выполнять заданий параллельно (по умолчанию: 8). - -o (например, -o junit:output.xml) + -o (например, -o junit:output.xml) Укажите один или несколько выходных форматов с необязательным именем файла. -w | --watch <путь> Каталог просмотра. -i | --info Показать информацию об окружении тестов и выйти. @@ -118,11 +118,12 @@ tester -d max_execution_time=20 Тесты запускаются в `` параллельно. Значение по умолчанию - 8. Если мы хотим запускать тесты последовательно, мы используем значение 1. --o .[filter] ------------------------------------------ +-o .[filter] +------------------------------------------------------- Формат вывода. По умолчанию используется консольный формат. Вы можете указать имя файла, в который будет записан вывод (например, `-o junit:output.xml`). Опцию `-o` можно повторить несколько раз, чтобы сгенерировать несколько форматов одновременно. - `console`: то же, что и по умолчанию, но ASCII-логотип в этом случае не печатается. +- `console-lines`: аналогично консоли, но результат каждого теста выводится в отдельной строке с дополнительной информацией - `tap`: [формат TAP |https://en.wikipedia.org/wiki/Test_Anything_Protocol], подходящий для машинной обработки - `junit`: формат JUnit XML, также подходящий для машинной обработки. - `log`: Выводит информацию о ходе тестирования. Все неудачные, пропущенные, а также успешные тесты diff --git a/tester/sl/guide.texy b/tester/sl/guide.texy index 75f55d6c7d..cfd0219356 100644 --- a/tester/sl/guide.texy +++ b/tester/sl/guide.texy @@ -116,10 +116,10 @@ Izpis je lahko videti takole: /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. -PHP 7.4.8 (cli) | php -n | 8 threads +PHP 8.3.2 (cli) | php -n | 8 threads ........s................F......... diff --git a/tester/sl/helpers.texy b/tester/sl/helpers.texy index 87c3e3ef08..2a27dcac2c 100644 --- a/tester/sl/helpers.texy +++ b/tester/sl/helpers.texy @@ -119,7 +119,7 @@ Environment::setup() .[filter] Environment::setupFunctions() .[filter]{data-version:2.5} --------------------------------------------------------- -Ustvari globalne funkcije `test()`, `setUp()` in `tearDown()`, v katere lahko razdelite teste. +Ustvari globalne funkcije `test()`, `testException()`, `setUp()` in `tearDown()`, v katere lahko razdelite teste. ```php test('test description', function () { diff --git a/tester/sl/running-tests.texy b/tester/sl/running-tests.texy index 3008c94407..61f88fe883 100644 --- a/tester/sl/running-tests.texy +++ b/tester/sl/running-tests.texy @@ -23,10 +23,10 @@ Izpis je lahko videti takole: /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. -PHP 7.4.8 (cli) | php -n | 8 threads +PHP 8.3.2 (cli) | php -n | 8 threads ........s.......................... @@ -49,7 +49,7 @@ Pregled možnosti ukazne vrstice dobimo tako, da zaženemo Tester brez parametro /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Usage: tester [options] [ | ]... @@ -62,7 +62,7 @@ Options: -s Show information about skipped tests. --stop-on-fail Stop execution upon the first failure. -j Run jobs in parallel (default: 8). - -o (npr. -o junit:output.xml) + -o (npr. -o junit:output.xml) Določite enega ali več izhodnih formatov z neobveznim imenom datoteke. -w | --watch Watch directory. -i | --info Show tests environment info and exit. @@ -118,11 +118,12 @@ Tester ustavi testiranje ob prvem neuspešnem testu. Testi se izvajajo v `` vzporednih procesih. Privzeta vrednost je 8. Če želimo teste izvajati zaporedno, uporabimo vrednost 1. --o .[filter] ------------------------------------------ +-o .[filter] +------------------------------------------------------- Izhodni format. Privzeta je konzolna oblika. Določite lahko ime datoteke, v katero se bo zapisal izpis (npr. `-o junit:output.xml`). Možnost `-o` lahko večkrat ponovite, da ustvarite več formatov naenkrat. - `console`: enako kot privzeto, vendar se v tem primeru logotip ASCII ne izpiše. +- `console-lines`: podobno kot v konzoli, vendar je rezultat vsakega testa naveden v ločeni vrstici z več informacijami - `tap`: [format TAP, |https://en.wikipedia.org/wiki/Test_Anything_Protocol] primeren za strojno obdelavo - `junit`: format JUnit XML, primeren tudi za strojno obdelavo - `log`: Izpis poteka testiranja. Vsi neuspešni, preskočeni in tudi uspešni testi diff --git a/tester/tr/guide.texy b/tester/tr/guide.texy index faf21f3233..402f2f9184 100644 --- a/tester/tr/guide.texy +++ b/tester/tr/guide.texy @@ -116,10 +116,10 @@ Tamamlanan her test için, çalıştırıcı ilerlemeyi göstermek için bir kar /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. -PHP 7.4.8 (cli) | php -n | 8 threads +PHP 8.3.2 (cli) | php -n | 8 threads ........s................F......... diff --git a/tester/tr/helpers.texy b/tester/tr/helpers.texy index 7c53678321..67c2100649 100644 --- a/tester/tr/helpers.texy +++ b/tester/tr/helpers.texy @@ -119,7 +119,7 @@ Environment::setup() .[filter] Environment::setupFunctions() .[filter]{data-version:2.5} --------------------------------------------------------- -Testleri bölebileceğiniz `test()`, `setUp()` ve `tearDown()` global fonksiyonlarını oluşturur. +Testleri bölebileceğiniz `test()`, `testException()`, `setUp()` ve `tearDown()` global fonksiyonlarını oluşturur. ```php test('test açıklaması', function () { diff --git a/tester/tr/running-tests.texy b/tester/tr/running-tests.texy index fe795109c5..38b67a826e 100644 --- a/tester/tr/running-tests.texy +++ b/tester/tr/running-tests.texy @@ -23,10 +23,10 @@ Daha sonra testleri yürütecektir. Tamamlanan her test için, koşucu ilerlemey /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. -PHP 7.4.8 (cli) | php -n | 8 threads +PHP 8.3.2 (cli) | php -n | 8 threads ........s.......................... @@ -49,7 +49,7 @@ Tester'ı parametresiz veya `-h` seçeneği ile çalıştırarak komut satırı /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Usage: tester [options] [ | ]... @@ -62,7 +62,7 @@ Options: -s Show information about skipped tests. --stop-on-fail Stop execution upon the first failure. -j Run jobs in parallel (default: 8). - -o (örneğin -o junit:output.xml) + -o (örneğin -o junit:output.xml) İsteğe bağlı dosya adıyla birlikte bir veya daha fazla çıktı biçimi belirtin. -w | --watch Watch directory. -i | --info Show tests environment info and exit. @@ -118,11 +118,12 @@ Test cihazı ilk başarısız testte testi durdurur. Testler bir `` paralel ön işlemler. Varsayılan değer 8'dir. Testleri seri olarak çalıştırmak istiyorsak 1 değerini kullanırız. --o .[filter] ------------------------------------------ +-o .[filter] +------------------------------------------------------- Çıktı biçimi. Varsayılan biçim konsol biçimidir. Çıktının içine yazılacağı dosyanın adını belirtebilirsiniz (örneğin, `-o junit:output.xml`). Aynı anda birden fazla format oluşturmak için `-o` seçeneği birden fazla kez tekrarlanabilir. - `console`: varsayılan ile aynı, ancak ASCII logosu bu durumda yazdırılmaz +- `console-lines`: konsola benzer, ancak her testin sonucu daha fazla bilgi ile ayrı bir satırda listelenir - `tap`: Makine işlemesi için uygun [TAP formatı |https://en.wikipedia.org/wiki/Test_Anything_Protocol] - `junit`: JUnit XML formatı, makine işlemesi için de uygun - `log`: Test ilerlemesini çıktılar. Tüm başarısız, atlanmış ve ayrıca başarılı testler diff --git a/tester/uk/guide.texy b/tester/uk/guide.texy index 336f833c8b..9b52c9c76f 100644 --- a/tester/uk/guide.texy +++ b/tester/uk/guide.texy @@ -116,10 +116,10 @@ vendor/bin/tester . /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. -PHP 7.4.8 (cli) | php -n | 8 threads +PHP 8.3.2 (cli) | php -n | 8 threads ........s................F......... diff --git a/tester/uk/helpers.texy b/tester/uk/helpers.texy index 397dc430d4..d39955e840 100644 --- a/tester/uk/helpers.texy +++ b/tester/uk/helpers.texy @@ -119,7 +119,7 @@ Environment::setup() .[filter] Environment::setupFunctions() .[filter]{data-version:2.5} --------------------------------------------------------- -Створює глобальні функції `test()`, `setUp()` і `tearDown()`, на які можна розбити тести. +Створює глобальні функції `test()`, `testException()`, `setUp()` і `tearDown()`, на які можна розбити тести. ```php test('опис тесту', function () { diff --git a/tester/uk/running-tests.texy b/tester/uk/running-tests.texy index 3b9ca8bdbc..a3b07f972d 100644 --- a/tester/uk/running-tests.texy +++ b/tester/uk/running-tests.texy @@ -23,10 +23,10 @@ vendor/bin/tester . /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. -PHP 7.4.8 (cli) | php -n | 8 threads +PHP 8.3.2 (cli) | php -n | 8 threads ........s.......................... @@ -49,7 +49,7 @@ PHP 7.4.8 (cli) | php -n | 8 threads /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.3.3 + |_| \___ /___) |_| \___ |_|_\ v2.5.2 Использование: tester [параметры] [<тестовый файл> | <каталог>]... @@ -62,7 +62,7 @@ PHP 7.4.8 (cli) | php -n | 8 threads -s Показать информацию о пропущенных тестах. --stop-on-fail Остановить выполнение при первом сбое. -j Выполнять заданий параллельно (по умолчанию: 8). - -o (наприклад, -o junit:output.xml) + -o (наприклад, -o junit:output.xml) Вкажіть один або декілька форматів виводу з необов'язковим ім'ям файлу. -w | --watch <путь> Каталог просмотра. -i | --info Показать информацию об окружении тестов и выйти. @@ -118,11 +118,12 @@ tester -d max_execution_time=20 Тести виконуються в `` паралельними прецесіями. Значення за замовчуванням 8. Якщо ми хочемо запускати тести послідовно, ми використовуємо значення 1. --o .[filter] ------------------------------------------ +-o .[filter] +------------------------------------------------------- Формат виводу. За замовчуванням використовується формат консолі. Ви можете вказати назву файлу, до якого буде записано вивід (наприклад, `-o junit:output.xml`). Параметр `-o` можна повторити декілька разів, щоб згенерувати одразу декілька форматів. - `console`: те саме, що і за замовчуванням, але у цьому випадку не виводиться ASCII-логотип +- `console-lines`: аналогічно консолі, але результат кожного тесту виводиться в окремому рядку з додатковою інформацією - `tap`: [формат TAP |https://en.wikipedia.org/wiki/Test_Anything_Protocol], придатний для машинної обробки - `junit`: формат JUnit XML, також придатний для машинної обробки - `log`: Прогрес тестування вихідних даних. Всі невдалі, пропущені та успішні тести From 63f10b1329731288b59a4b82ee1ec7ffedb65e55 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 30 Jan 2024 19:16:04 +0100 Subject: [PATCH 049/137] nette/http 3.2.4 --- http/bg/request.texy | 16 +++++++++++----- http/cs/request.texy | 16 +++++++++++----- http/de/request.texy | 16 +++++++++++----- http/el/request.texy | 16 +++++++++++----- http/en/request.texy | 16 +++++++++++----- http/es/request.texy | 16 +++++++++++----- http/fr/request.texy | 16 +++++++++++----- http/hu/request.texy | 16 +++++++++++----- http/it/request.texy | 16 +++++++++++----- http/pl/request.texy | 16 +++++++++++----- http/pt/request.texy | 16 +++++++++++----- http/ro/request.texy | 16 +++++++++++----- http/ru/request.texy | 16 +++++++++++----- http/sl/request.texy | 16 +++++++++++----- http/tr/request.texy | 16 +++++++++++----- http/uk/request.texy | 16 +++++++++++----- 16 files changed, 176 insertions(+), 80 deletions(-) diff --git a/http/bg/request.texy b/http/bg/request.texy index 44fd5475f7..af83021db4 100644 --- a/http/bg/request.texy +++ b/http/bg/request.texy @@ -141,11 +141,6 @@ echo $headers['Content-Type']; ``` -getReferer(): ?Nette\Http\UrlImmutable .[method] ------------------------------------------------- -От кой URL адрес е дошъл потребителят? Внимавайте, това изобщо не е надеждно. - - isSecured(): bool .[method] --------------------------- Криптирана ли е връзката (HTTPS)? Може да се наложи да конфигурирате [прокси сървър |configuration#HTTP-Proxy], за да работи правилно. @@ -357,6 +352,17 @@ getSanitizedName(): string .[method] ------------------------------------ Връща обработено име на файл. Той съдържа само ASCII символи. `[a-zA-Z0-9.-]`. Ако името не съдържа такива знаци, се връща символът 'unknown'. Ако файлът е JPEG, PNG, GIF или WebP изображение, се връща правилното разширение на файла. +.[caution] +Изисква разширение на PHP `fileinfo`. + + +getSuggestedExtension(): ?string .[method]{data-version:3.2.4} +-------------------------------------------------------------- +Връща съответното разширение на файла (без точка), съответстващо на открития тип MIME. + +.[caution] +Изисква PHP разширение `fileinfo`. + getUntrustedFullPath(): string .[method] ---------------------------------------- diff --git a/http/cs/request.texy b/http/cs/request.texy index 6a23793c3f..85288d438b 100644 --- a/http/cs/request.texy +++ b/http/cs/request.texy @@ -141,11 +141,6 @@ echo $headers['Content-Type']; ``` -getReferer(): ?Nette\Http\UrlImmutable .[method] ------------------------------------------------- -Z jaké URL uživatel přišel? Pozor, není vůbec spolehlivé. - - isSecured(): bool .[method] --------------------------- Je spojení šifrované (HTTPS)? Pro správnou funkčnost může být potřeba [nastavit proxy|configuration#HTTP proxy]. @@ -357,6 +352,17 @@ getSanitizedName(): string .[method] ------------------------------------ Vrací sanitizovaný název souboru. Obsahuje pouze ASCII znaky `[a-zA-Z0-9.-]`. Pokud název takové znaky neobsahuje, vrátí `'unknown'`. Pokud je soubor obrázek ve formátu JPEG, PNG, GIF, WebP nebo AVIF, vrátí i správnou příponu. +.[caution] +Vyžaduje PHP rozšíření `fileinfo`. + + +getSuggestedExtension(): ?string .[method]{data-version:3.2.4} +-------------------------------------------------------------- +Vrací vhodnou příponu souboru (bez tečky) odpovídající zjištěnému MIME typu. + +.[caution] +Vyžaduje PHP rozšíření `fileinfo`. + getUntrustedFullPath(): string .[method] ---------------------------------------- diff --git a/http/de/request.texy b/http/de/request.texy index b93dbdde68..1e8e33d006 100644 --- a/http/de/request.texy +++ b/http/de/request.texy @@ -141,11 +141,6 @@ echo $headers['Content-Type']; ``` -getReferer(): ?Nette\Http\UrlImmutable .[method] ------------------------------------------------- -Von welcher URL kam der Benutzer? Vorsicht, diese Angabe ist nicht zuverlässig. - - isSecured(): bool .[method] --------------------------- Ist die Verbindung verschlüsselt (HTTPS)? Möglicherweise müssen Sie [einen Proxy ein |configuration#HTTP proxy] richten, damit die Verbindung funktioniert. @@ -357,6 +352,17 @@ getSanitizedName(): string .[method] ------------------------------------ Gibt den bereinigten Dateinamen zurück. Er enthält nur ASCII-Zeichen `[a-zA-Z0-9.-]`. Enthält der Name keine solchen Zeichen, wird "unbekannt" zurückgegeben. Wenn die Datei ein JPEG-, PNG-, GIF- oder WebP-Bild ist, wird die korrekte Dateierweiterung zurückgegeben. +.[caution] +Erfordert die PHP-Erweiterung `fileinfo`. + + +getSuggestedExtension(): ?string .[method]{data-version:3.2.4} +-------------------------------------------------------------- +Gibt die entsprechende Dateierweiterung (ohne Punkt) zurück, die dem erkannten MIME-Typ entspricht. + +.[caution] +Erfordert die PHP-Erweiterung `fileinfo`. + getUntrustedFullPath(): string .[method] ---------------------------------------- diff --git a/http/el/request.texy b/http/el/request.texy index 5b215f84c1..e94a107acf 100644 --- a/http/el/request.texy +++ b/http/el/request.texy @@ -141,11 +141,6 @@ echo $headers['Content-Type']; ``` -getReferer(): ?Nette\Http\UrlImmutable .[method] ------------------------------------------------- -Από ποια διεύθυνση URL ήρθε ο χρήστης; Προσοχή, δεν είναι καθόλου αξιόπιστο. - - isSecured(): bool .[method] --------------------------- Είναι η σύνδεση κρυπτογραφημένη (HTTPS); Ενδέχεται να χρειαστεί να [ρυθμίσετε έναν διακομιστή μεσολάβησης |configuration#HTTP proxy] για τη σωστή λειτουργία. @@ -357,6 +352,17 @@ getSanitizedName(): string .[method] ------------------------------------ Επιστρέφει το καθαρισμένο όνομα αρχείου. Περιέχει μόνο χαρακτήρες ASCII `[a-zA-Z0-9.-]`. Εάν το όνομα δεν περιέχει τέτοιους χαρακτήρες, επιστρέφει 'unknown'. Εάν το αρχείο είναι εικόνα JPEG, PNG, GIF ή WebP, επιστρέφει τη σωστή επέκταση αρχείου. +.[caution] +Απαιτεί την επέκταση PHP `fileinfo`. + + +getSuggestedExtension(): ?string .[method]{data-version:3.2.4} +-------------------------------------------------------------- +Επιστρέφει την κατάλληλη επέκταση αρχείου (χωρίς την τελεία) που αντιστοιχεί στον τύπο MIME που εντοπίστηκε. + +.[caution] +Απαιτεί την επέκταση PHP `fileinfo`. + getUntrustedFullPath(): string .[method] ---------------------------------------- diff --git a/http/en/request.texy b/http/en/request.texy index 080b6d54ff..f03cecc27d 100644 --- a/http/en/request.texy +++ b/http/en/request.texy @@ -141,11 +141,6 @@ echo $headers['Content-Type']; ``` -getReferer(): ?Nette\Http\UrlImmutable .[method] ------------------------------------------------- -What URL did the user come from? Beware, it is not reliable at all. - - isSecured(): bool .[method] --------------------------- Is the connection encrypted (HTTPS)? You may need to [set up a proxy|configuration#HTTP proxy] for proper functionality. @@ -357,6 +352,17 @@ getSanitizedName(): string .[method] ------------------------------------ Returns the sanitized file name. It contains only ASCII characters `[a-zA-Z0-9.-]`. If the name does not contain such characters, it returns 'unknown'. If the file is JPEG, PNG, GIF, WebP or AVIF image, it returns the correct file extension. +.[caution] +Requires PHP extension `fileinfo`. + + +getSuggestedExtension(): ?string .[method]{data-version:3.2.4} +-------------------------------------------------------------- +Returns the appropriate file extension (without the period) corresponding to the detected MIME type. + +.[caution] +Requires PHP extension `fileinfo`. + getUntrustedFullPath(): string .[method] ---------------------------------------- diff --git a/http/es/request.texy b/http/es/request.texy index 99f1351f48..fb7771dee1 100644 --- a/http/es/request.texy +++ b/http/es/request.texy @@ -141,11 +141,6 @@ echo $headers['Content-Type']; ``` -getReferer(): ?Nette\Http\UrlImmutable .[method] ------------------------------------------------- -¿De qué URL procede el usuario? Cuidado, no es nada fiable. - - isSecured(): bool .[method] --------------------------- ¿Está cifrada la conexión (HTTPS)? Es posible que tenga que [configurar un proxy |configuration#HTTP proxy] para que funcione correctamente. @@ -357,6 +352,17 @@ getSanitizedName(): string .[method] ------------------------------------ Devuelve el nombre de archivo desinfectado. Sólo contiene caracteres ASCII `[a-zA-Z0-9.-]`. Si el nombre no contiene tales caracteres, devuelve 'desconocido'. Si el archivo es una imagen JPEG, PNG, GIF o WebP, devuelve la extensión de archivo correcta. +.[caution] +Requiere la extensión PHP `fileinfo`. + + +getSuggestedExtension(): ?string .[method]{data-version:3.2.4} +-------------------------------------------------------------- +Devuelve la extensión de archivo apropiada (sin el punto) correspondiente al tipo MIME detectado. + +.[caution] +Requiere la extensión PHP `fileinfo`. + getUntrustedFullPath(): string .[method] ---------------------------------------- diff --git a/http/fr/request.texy b/http/fr/request.texy index 8f6dc7b848..125664222d 100644 --- a/http/fr/request.texy +++ b/http/fr/request.texy @@ -141,11 +141,6 @@ echo $headers['Content-Type']; ``` -getReferer(): ?Nette\Http\UrlImmutable .[method] ------------------------------------------------- -De quelle URL l'utilisateur provient-il ? Attention, ce n'est pas du tout fiable. - - isSecured(): bool .[method] --------------------------- La connexion est-elle cryptée (HTTPS) ? Vous devrez peut-être configurer [un proxy |configuration#HTTP proxy] pour une bonne fonctionnalité. @@ -357,6 +352,17 @@ getSanitizedName(): string .[method] ------------------------------------ Renvoie le nom de fichier aseptisé. Il ne contient que des caractères ASCII `[a-zA-Z0-9.-]`. Si le nom ne contient pas de tels caractères, il renvoie "inconnu". Si le fichier est une image JPEG, PNG, GIF ou WebP, il renvoie l'extension de fichier correcte. +.[caution] +Requiert l'extension PHP `fileinfo`. + + +getSuggestedExtension(): ?string .[method]{data-version:3.2.4} +-------------------------------------------------------------- +Renvoie l'extension de fichier appropriée (sans le point) correspondant au type MIME détecté. + +.[caution] +Requiert l'extension PHP `fileinfo`. + getUntrustedFullPath(): string .[method] ---------------------------------------- diff --git a/http/hu/request.texy b/http/hu/request.texy index e8e9a3931c..7a40baee92 100644 --- a/http/hu/request.texy +++ b/http/hu/request.texy @@ -141,11 +141,6 @@ echo $headers['Content-Type']; ``` -getReferer(): ?Nette\Http\UrlImmutable .[method] ------------------------------------------------- -Milyen URL-ről érkezett a felhasználó? Vigyázat, egyáltalán nem megbízható. - - isSecured(): bool .[method] --------------------------- A kapcsolat titkosított (HTTPS)? Lehet, hogy a megfelelő működéshez [proxy-t |configuration#HTTP proxy] kell beállítania. @@ -357,6 +352,17 @@ getSanitizedName(): string .[method] ------------------------------------ Visszaadja a szanált fájlnevet. Csak ASCII karaktereket tartalmaz. `[a-zA-Z0-9.-]`. Ha a név nem tartalmaz ilyen karaktereket, akkor az 'unknown' értéket adja vissza. Ha a fájl JPEG, PNG, GIF vagy WebP kép, akkor a megfelelő fájlkiterjesztést adja vissza. +.[caution] +PHP kiterjesztés szükséges `fileinfo`. + + +getSuggestedExtension(): ?string .[method]{data-version:3.2.4} +-------------------------------------------------------------- +Visszaadja az észlelt MIME-típusnak megfelelő fájlkiterjesztést (pont nélkül). + +.[caution] +PHP-bővítményt igényel `fileinfo`. + getUntrustedFullPath(): string .[method] ---------------------------------------- diff --git a/http/it/request.texy b/http/it/request.texy index c76f283b0f..131da30e8c 100644 --- a/http/it/request.texy +++ b/http/it/request.texy @@ -141,11 +141,6 @@ echo $headers['Content-Type']; ``` -getReferer(): ?Nette\Http\UrlImmutable .[method] ------------------------------------------------- -Da quale URL proviene l'utente? Attenzione, non è affatto affidabile. - - isSecured(): bool .[method] --------------------------- La connessione è criptata (HTTPS)? Potrebbe essere necessario [impostare un proxy |configuration#HTTP proxy] per una corretta funzionalità. @@ -357,6 +352,17 @@ getSanitizedName(): string .[method] ------------------------------------ Restituisce il nome del file sanificato. Contiene solo caratteri ASCII `[a-zA-Z0-9.-]`. Se il nome non contiene tali caratteri, restituisce "unknown". Se il file è un'immagine JPEG, PNG, GIF o WebP, restituisce l'estensione corretta. +.[caution] +Richiede l'estensione PHP `fileinfo`. + + +getSuggestedExtension(): ?string .[method]{data-version:3.2.4} +-------------------------------------------------------------- +Restituisce l'estensione di file appropriata (senza il punto) corrispondente al tipo MIME rilevato. + +.[caution] +Richiede l'estensione PHP `fileinfo`. + getUntrustedFullPath(): string .[method] ---------------------------------------- diff --git a/http/pl/request.texy b/http/pl/request.texy index c8d899a45f..62985edae7 100644 --- a/http/pl/request.texy +++ b/http/pl/request.texy @@ -141,11 +141,6 @@ echo $headers['Content-Type']; ``` -getReferer(): ?Nette\Http\UrlImmutable .[method] ------------------------------------------------- -Z jakiego adresu URL przyszedł użytkownik? Uważaj, w ogóle nie jest niezawodny. - - isSecured(): bool .[method] --------------------------- Czy połączenie jest szyfrowane (HTTPS)? Może być konieczne skonfigurowanie [proxy |configuration#HTTP-Proxy] dla prawidłowej funkcjonalności. @@ -357,6 +352,17 @@ getSanitizedName(): string .[method] ------------------------------------ Zwraca oczyszczoną nazwę pliku. Zawiera tylko znaki ASCII `[a-zA-Z0-9.-]`. Jeśli nazwa nie zawiera takich znaków, zwraca `'unknown'`. Jeśli plik jest obrazem JPEG, PNG, GIF lub WebP, zwraca również prawidłowe rozszerzenie. +.[caution] +Wymaga rozszerzenia PHP `fileinfo`. + + +getSuggestedExtension(): ?string .[method]{data-version:3.2.4} +-------------------------------------------------------------- +Zwraca odpowiednie rozszerzenie pliku (bez kropki) odpowiadające wykrytemu typowi MIME. + +.[caution] +Wymaga rozszerzenia PHP `fileinfo`. + getUntrustedFullPath(): string .[method] ---------------------------------------- diff --git a/http/pt/request.texy b/http/pt/request.texy index 7e36306737..f9de701c9b 100644 --- a/http/pt/request.texy +++ b/http/pt/request.texy @@ -141,11 +141,6 @@ echo $headers['Content-Type']; ``` -getReferer(): ?Nette\Http\UrlImmutable .[method] ------------------------------------------------- -De que URL o usuário veio? Cuidado, ela não é confiável em absoluto. - - isSecured(): bool .[method] --------------------------- A conexão é criptografada (HTTPS)? Talvez seja necessário [configurar um proxy |configuration#HTTP proxy] para uma funcionalidade adequada. @@ -357,6 +352,17 @@ getSanitizedName(): string .[method] ------------------------------------ Devolve o nome do arquivo higienizado. Contém apenas caracteres ASCII `[a-zA-Z0-9.-]`. Se o nome não contiver tais caracteres, ele retorna "desconhecido". Se o arquivo for JPEG, PNG, GIF, ou imagem WebP, ele retorna a extensão correta do arquivo. +.[caution] +Requer a extensão PHP `fileinfo`. + + +getSuggestedExtension(): ?string .[method]{data-version:3.2.4} +-------------------------------------------------------------- +Retorna a extensão de arquivo apropriada (sem o ponto) correspondente ao tipo MIME detectado. + +.[caution] +Requer a extensão PHP `fileinfo`. + getUntrustedFullPath(): string .[method] ---------------------------------------- diff --git a/http/ro/request.texy b/http/ro/request.texy index 9579a906de..3755a1a2fa 100644 --- a/http/ro/request.texy +++ b/http/ro/request.texy @@ -141,11 +141,6 @@ echo $headers['Content-Type']; ``` -getReferer(): ?Nette\Http\UrlImmutable .[method] ------------------------------------------------- -De la ce URL a venit utilizatorul? Atenție, nu este deloc de încredere. - - isSecured(): bool .[method] --------------------------- Conexiunea este criptată (HTTPS)? Este posibil să fie necesar să configurați [un proxy |configuration#HTTP proxy] pentru o funcționalitate corespunzătoare. @@ -357,6 +352,17 @@ getSanitizedName(): string .[method] ------------------------------------ Returnează numele de fișier curățat. Acesta conține numai caractere ASCII `[a-zA-Z0-9.-]`. Dacă numele nu conține astfel de caractere, se returnează "necunoscut". Dacă fișierul este o imagine JPEG, PNG, GIF sau WebP, se returnează extensia corectă a fișierului. +.[caution] +Necesită extensia PHP `fileinfo`. + + +getSuggestedExtension(): ?string .[method]{data-version:3.2.4} +-------------------------------------------------------------- +Returnează extensia de fișier corespunzătoare (fără punct) care corespunde tipului MIME detectat. + +.[caution] +Necesită extensia PHP `fileinfo`. + getUntrustedFullPath(): string .[method] ---------------------------------------- diff --git a/http/ru/request.texy b/http/ru/request.texy index ed5afba54d..bfb99c35d8 100644 --- a/http/ru/request.texy +++ b/http/ru/request.texy @@ -141,11 +141,6 @@ echo $headers['Content-Type']; ``` -getReferer(): ?Nette\Http\UrlImmutable .[method] ------------------------------------------------- -С какого URL пришел пользователь? Остерегайтесь, это совсем не надежно. - - isSecured(): bool .[method] --------------------------- Зашифровано ли соединение (HTTPS)? Возможно, вам потребуется настроить [прокси-сервер |configuration#HTTP-Proxy] для правильной работы. @@ -357,6 +352,17 @@ getSanitizedName(): string .[method] ------------------------------------ Возвращает санированное имя файла. Оно содержит только символы ASCII `[a-zA-Z0-9.-]`. Если имя не содержит таких символов, возвращается 'unknown'. Если файл является изображением JPEG, PNG, GIF или WebP, возвращается правильное расширение файла. +.[caution] +Требуется расширение PHP `fileinfo`. + + +getSuggestedExtension(): ?string .[method]{data-version:3.2.4} +-------------------------------------------------------------- +Возвращает соответствующее расширение файла (без точки), соответствующее обнаруженному MIME-типу. + +.[caution] +Требуется расширение PHP `fileinfo`. + getUntrustedFullPath(): string .[method] ---------------------------------------- diff --git a/http/sl/request.texy b/http/sl/request.texy index 6198c956f8..8a6348a2a0 100644 --- a/http/sl/request.texy +++ b/http/sl/request.texy @@ -141,11 +141,6 @@ echo $headers['Content-Type']; ``` -getReferer(): ?Nette\Http\UrlImmutable .[method] ------------------------------------------------- -S katerega naslova URL je prišel uporabnik? Pazite, ni zanesljivo. - - isSecured(): bool .[method] --------------------------- Ali je povezava šifrirana (HTTPS)? Za pravilno delovanje boste morda morali nastaviti [posrednika |configuration#HTTP proxy]. @@ -357,6 +352,17 @@ getSanitizedName(): string .[method] ------------------------------------ Vrne prečiščeno ime datoteke. Vsebuje samo znake ASCII `[a-zA-Z0-9.-]`. Če ime ne vsebuje takih znakov, vrne 'unknown'. Če je datoteka slika JPEG, PNG, GIF ali WebP, vrne pravilno končnico datoteke. +.[caution] +Zahteva razširitev PHP `fileinfo`. + + +getSuggestedExtension(): ?string .[method]{data-version:3.2.4} +-------------------------------------------------------------- +Vrne ustrezno razširitev datoteke (brez pike), ki ustreza zaznani vrsti MIME. + +.[caution] +Zahteva razširitev PHP `fileinfo`. + getUntrustedFullPath(): string .[method] ---------------------------------------- diff --git a/http/tr/request.texy b/http/tr/request.texy index 75192ba3e4..fef7aa407c 100644 --- a/http/tr/request.texy +++ b/http/tr/request.texy @@ -141,11 +141,6 @@ echo $headers['Content-Type']; ``` -getReferer(): ?Nette\Http\UrlImmutable .[method] ------------------------------------------------- -Kullanıcı hangi URL'den geldi? Dikkat edin, hiç güvenilir değil. - - isSecured(): bool .[method] --------------------------- Bağlantı şifreli mi (HTTPS)? Düzgün işlevsellik için [bir proxy ayarlamanız |configuration#HTTP proxy] gerekebilir. @@ -357,6 +352,17 @@ getSanitizedName(): string .[method] ------------------------------------ Temizlenmiş dosya adını döndürür. Yalnızca ASCII karakterleri içerir `[a-zA-Z0-9.-]`. Ad bu tür karakterler içermiyorsa, 'bilinmeyen' döndürür. Dosya JPEG, PNG, GIF veya WebP görüntüsüyse, doğru dosya uzantısını döndürür. +.[caution] +PHP uzantısı gerektirir `fileinfo`. + + +getSuggestedExtension(): ?string .[method]{data-version:3.2.4} +-------------------------------------------------------------- +Algılanan MIME türüne karşılık gelen uygun dosya uzantısını (nokta olmadan) döndürür. + +.[caution] +PHP uzantısı gerektirir `fileinfo`. + getUntrustedFullPath(): string .[method] ---------------------------------------- diff --git a/http/uk/request.texy b/http/uk/request.texy index f35c32a2fe..f6ea8a2a27 100644 --- a/http/uk/request.texy +++ b/http/uk/request.texy @@ -141,11 +141,6 @@ echo $headers['Content-Type']; ``` -getReferer(): ?Nette\Http\UrlImmutable .[method] ------------------------------------------------- -З якого URL прийшов користувач? Остерігайтеся, це зовсім не надійно. - - isSecured(): bool .[method] --------------------------- Чи зашифровано з'єднання (HTTPS)? Можливо, вам буде потрібно налаштувати [проксі-сервер |configuration#HTTP-Proxy] для правильної роботи. @@ -357,6 +352,17 @@ getSanitizedName(): string .[method] ------------------------------------ Повертає саніроване ім'я файлу. Воно містить тільки символи ASCII `[a-zA-Z0-9.-]`. Якщо ім'я не містить таких символів, повертається 'unknown'. Якщо файл є зображенням JPEG, PNG, GIF або WebP, повертається правильне розширення файлу. +.[caution] +Потрібне розширення PHP `fileinfo`. + + +getSuggestedExtension(): ?string .[method]{data-version:3.2.4} +-------------------------------------------------------------- +Повертає відповідне розширення файлу (без крапки), що відповідає виявленому MIME-типу. + +.[caution] +Вимагає розширення PHP `fileinfo`. + getUntrustedFullPath(): string .[method] ---------------------------------------- From fdecd474d09151e3b6e8f9b743857c7fdacb706c Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 8 Feb 2024 22:34:35 +0100 Subject: [PATCH 050/137] nette/application 3.2 --- application/bg/@home.texy | 1 + application/cs/@home.texy | 1 + application/de/@home.texy | 1 + application/el/@home.texy | 1 + application/en/@home.texy | 1 + application/es/@home.texy | 1 + application/fr/@home.texy | 1 + application/hu/@home.texy | 1 + application/it/@home.texy | 1 + application/pl/@home.texy | 1 + application/pt/@home.texy | 1 + application/ro/@home.texy | 1 + application/ru/@home.texy | 1 + application/sl/@home.texy | 1 + application/tr/@home.texy | 1 + application/uk/@home.texy | 1 + 16 files changed, 16 insertions(+) diff --git a/application/bg/@home.texy b/application/bg/@home.texy index 64999ca151..341c43ef6e 100644 --- a/application/bg/@home.texy +++ b/application/bg/@home.texy @@ -29,6 +29,7 @@ composer require nette/application | версия на пакета | съвместима версия на PHP |-----------------------|----------------------- | Nette Application 4.0 | PHP 8.1 – 8.3 +| Nette Application 3.2 | PHP 8.1 – 8.3 | 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 diff --git a/application/cs/@home.texy b/application/cs/@home.texy index 7ff66ca955..57c24db0a2 100644 --- a/application/cs/@home.texy +++ b/application/cs/@home.texy @@ -29,6 +29,7 @@ composer require nette/application | verze | kompatibilní s PHP |-----------|------------------- | Nette Application 4.0 | PHP 8.1 – 8.3 +| Nette Application 3.2 | PHP 8.1 – 8.3 | 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 diff --git a/application/de/@home.texy b/application/de/@home.texy index de23a839b0..078fe84ca4 100644 --- a/application/de/@home.texy +++ b/application/de/@home.texy @@ -29,6 +29,7 @@ composer require nette/application | Version | kompatibel mit PHP |-----------|------------------- | Nette Application 4.0 | PHP 8.1 – 8.3 +| Nette Application 3.2 | PHP 8.1 – 8.3 | Nette Application 3.1 | PHP 7.2 – 8.3 | Nette Anwendung 3.0 | PHP 7.1 - 8.0 | Nette-Anwendung 2.4 | PHP 5.6 - 8.0 diff --git a/application/el/@home.texy b/application/el/@home.texy index 1c9fac4c70..9a733fd102 100644 --- a/application/el/@home.texy +++ b/application/el/@home.texy @@ -29,6 +29,7 @@ composer require nette/application | έκδοση | συμβατό με PHP |-----------|------------------- | Nette Application 4.0 | PHP 8.1 – 8.3 +| Nette Application 3.2 | PHP 8.1 – 8.3 | 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 diff --git a/application/en/@home.texy b/application/en/@home.texy index c1e758424a..0892ae2d2d 100644 --- a/application/en/@home.texy +++ b/application/en/@home.texy @@ -29,6 +29,7 @@ composer require nette/application | version | compatible with PHP |-----------|------------------- | Nette Application 4.0 | PHP 8.1 – 8.3 +| Nette Application 3.2 | PHP 8.1 – 8.3 | 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 diff --git a/application/es/@home.texy b/application/es/@home.texy index 13adb46b5c..0777da2986 100644 --- a/application/es/@home.texy +++ b/application/es/@home.texy @@ -29,6 +29,7 @@ composer require nette/application | versión | compatible con PHP |-----------|------------------- | Nette Application 4.0 | PHP 8.1 – 8.3 +| Nette Application 3.2 | PHP 8.1 – 8.3 | Nette Application 3.1 | PHP 7.2 – 8.3 | Aplicación Nette 3.0 | PHP 7.1 - 8.0 | Aplicación Nette 2.4 | PHP 5.6 - 8.0 diff --git a/application/fr/@home.texy b/application/fr/@home.texy index 8afc742343..9117a6be9c 100644 --- a/application/fr/@home.texy +++ b/application/fr/@home.texy @@ -29,6 +29,7 @@ composer require nette/application | version | compatible avec PHP |-----------|------------------- | Nette Application 4.0 | PHP 8.1 – 8.3 +| Nette Application 3.2 | PHP 8.1 – 8.3 | 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 diff --git a/application/hu/@home.texy b/application/hu/@home.texy index 53ef396602..f49e983b61 100644 --- a/application/hu/@home.texy +++ b/application/hu/@home.texy @@ -29,6 +29,7 @@ composer require nette/application | verzió | kompatibilis a PHP-vel |-----------|------------------- | Nette Application 4.0 | PHP 8.1 – 8.3 +| Nette Application 3.2 | PHP 8.1 – 8.3 | Nette Application 3.1 | PHP 7.2 – 8.3 | Nette alkalmazás 3.0 | PHP 7.1 - 8.0 | Nette Application 2.4 | PHP 5.6 - 8.0 diff --git a/application/it/@home.texy b/application/it/@home.texy index 038c8e4f9f..b747c11f9f 100644 --- a/application/it/@home.texy +++ b/application/it/@home.texy @@ -29,6 +29,7 @@ composer require nette/application | versione | compatibile con PHP |-----------|------------------- | Nette Application 4.0 | PHP 8.1 – 8.3 +| Nette Application 3.2 | PHP 8.1 – 8.3 | Nette Application 3.1 | PHP 7.2 – 8.3 | Applicazione Nette 3.0 | PHP 7.1 - 8.0 | Applicazione Nette 2.4 | PHP 5.6 - 8.0 diff --git a/application/pl/@home.texy b/application/pl/@home.texy index 34e9b68599..8d3e67e939 100644 --- a/application/pl/@home.texy +++ b/application/pl/@home.texy @@ -29,6 +29,7 @@ composer require nette/application | wersja zgodna z PHP |-----------|------------------- | Nette Application 4.0 | PHP 8.1 – 8.3 +| Nette Application 3.2 | PHP 8.1 – 8.3 | 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 diff --git a/application/pt/@home.texy b/application/pt/@home.texy index e343ac2d4c..de531925ab 100644 --- a/application/pt/@home.texy +++ b/application/pt/@home.texy @@ -29,6 +29,7 @@ composer require nette/application | versão | compatível com PHP |-----------|------------------- | Nette Application 4.0 | PHP 8.1 – 8.3 +| Nette Application 3.2 | PHP 8.1 – 8.3 | Nette Application 3.1 | PHP 7.2 – 8.3 | Aplicativo Nette 3.0 | PHP 7.1 - 8.0 | Aplicação Nette 2.4 | PHP 5.6 - 8.0 diff --git a/application/ro/@home.texy b/application/ro/@home.texy index 09746df1db..5dfe0522dc 100644 --- a/application/ro/@home.texy +++ b/application/ro/@home.texy @@ -29,6 +29,7 @@ composer require nette/application | versiune | compatibil cu PHP |-----------|------------------- | Nette Application 4.0 | PHP 8.1 – 8.3 +| Nette Application 3.2 | PHP 8.1 – 8.3 | 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 diff --git a/application/ru/@home.texy b/application/ru/@home.texy index 82c69a7d04..4b38017f75 100644 --- a/application/ru/@home.texy +++ b/application/ru/@home.texy @@ -29,6 +29,7 @@ composer require nette/application | версия пакета | совместимая версия PHP |-----------------------|----------------------- | Nette Application 4.0 | PHP 8.1 – 8.3 +| Nette Application 3.2 | PHP 8.1 – 8.3 | 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 diff --git a/application/sl/@home.texy b/application/sl/@home.texy index 0d7d2f3cf2..bb639d5c54 100644 --- a/application/sl/@home.texy +++ b/application/sl/@home.texy @@ -29,6 +29,7 @@ composer require nette/application | različica | združljivo s PHP |-----------|------------------- | Nette Application 4.0 | PHP 8.1 – 8.3 +| Nette Application 3.2 | PHP 8.1 – 8.3 | 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 diff --git a/application/tr/@home.texy b/application/tr/@home.texy index dbf1d64801..89c807617b 100644 --- a/application/tr/@home.texy +++ b/application/tr/@home.texy @@ -29,6 +29,7 @@ composer require nette/application | sürüm | PHP ile uyumlu |-----------|------------------- | Nette Application 4.0 | PHP 8.1 – 8.3 +| Nette Application 3.2 | PHP 8.1 – 8.3 | Nette Application 3.1 | PHP 7.2 – 8.3 | Nette Uygulama 3.0 | PHP 7.1 - 8.0 | Nette Uygulama 2.4 | PHP 5.6 - 8.0 diff --git a/application/uk/@home.texy b/application/uk/@home.texy index 0040712998..fcc2f61317 100644 --- a/application/uk/@home.texy +++ b/application/uk/@home.texy @@ -29,6 +29,7 @@ composer require nette/application | версія пакета | сумісна версія PHP |-----------------------|----------------------- | Nette Application 4.0 | PHP 8.1 – 8.3 +| Nette Application 3.2 | PHP 8.1 – 8.3 | 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 From d38b3cfac19d6a0f578842b7046a549a88a5f6c1 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 8 Feb 2024 22:47:13 +0100 Subject: [PATCH 051/137] nette/component-model 3.1.0 --- component-model/bg/@home.texy | 16 ++++++---------- component-model/cs/@home.texy | 16 ++++++---------- component-model/de/@home.texy | 16 ++++++---------- component-model/el/@home.texy | 16 ++++++---------- component-model/en/@home.texy | 16 ++++++---------- component-model/es/@home.texy | 16 ++++++---------- component-model/fr/@home.texy | 16 ++++++---------- component-model/hu/@home.texy | 16 ++++++---------- component-model/it/@home.texy | 16 ++++++---------- component-model/meta.json | 2 +- component-model/pl/@home.texy | 16 ++++++---------- component-model/pt/@home.texy | 16 ++++++---------- component-model/ro/@home.texy | 16 ++++++---------- component-model/ru/@home.texy | 16 ++++++---------- component-model/sl/@home.texy | 16 ++++++---------- component-model/tr/@home.texy | 16 ++++++---------- component-model/uk/@home.texy | 16 ++++++---------- 17 files changed, 97 insertions(+), 161 deletions(-) diff --git a/component-model/bg/@home.texy b/component-model/bg/@home.texy index 133570acc4..824df10749 100644 --- a/component-model/bg/@home.texy +++ b/component-model/bg/@home.texy @@ -30,18 +30,14 @@ getComponent(string $name): ?Component .[method] Връща компонент. Опитът за извикване на недефиниран дъщерен компонент води до извикване на factory [createComponent($name |api:Nette\ComponentModel\Container::createComponent()]). Методът `createComponent($name)` извиква метода `createComponent` в текущия компонент и предава името на компонента като параметър. След това създаденият компонент се предава на текущия компонент като негов дъщерен компонент. Наричаме тези фабрики за компоненти, като те могат да бъдат реализирани в класове, наследени от `Container`. -Итерация над подчинени компоненти .[#toc-iterating-over-children] ------------------------------------------------------------------ +getComponents(): array .[method] +-------------------------------- +Връща преките наследници като масив. Ключовете съдържат имената на тези компоненти. Забележка: във версия 3.0.x методът връщаше итератор вместо масив, като първият му параметър определяше дали да се итерира през компонентите в дълбочина, а вторият представляваше филтър на типа. Тези параметри са отпаднали. -Методът [getComponents($deep = false, $type = null |api:Nette\ComponentModel\Container::getComponents()] ) се използва за итерация. Първият параметър определя дали компонентите да се итерират в дълбочина (или рекурсивно). Ако се използва `true`, се итерират не само всички негови дъщерни компоненти, но и всички деца на неговите дъщерни компоненти и т.н. Вторият параметър служи за допълнителен филтър по клас или интерфейс. -```php -foreach ($form->getComponents(true, Nette\Forms\IControl::class) as $control) { - if (!$control->getRules()->validate()) { - // ... - } -} -``` +getComponentTree(): array .[method]{data-version:3.1.0} +------------------------------------------------------- +Връща цялата йерархия от компоненти, включително всички вложени дъщерни компоненти, като индексиран масив. Търсенето се извършва първо в дълбочина. Мониторинг на предците .[#toc-monitoring-of-ancestors] diff --git a/component-model/cs/@home.texy b/component-model/cs/@home.texy index 28e3d11fe5..1a80e31100 100644 --- a/component-model/cs/@home.texy +++ b/component-model/cs/@home.texy @@ -30,18 +30,14 @@ getComponent(string $name): ?Component .[method] Vrací komponentu. Při pokusu o získání nedefinovaného potomka je zavolána továrna `createComponent($name)`. Metoda `createComponent($name)` zavolá v aktuální komponentě metodu `createComponent` a jako parametr jí předá název komponenty. Vytvořená komponenta je poté přidána do aktuální komponenty jako její potomek. Těmto metodám říkáme továrny na komponenty a mohou je implementovat potomci třídy `Container`. -Iterování nad potomky ---------------------- +getComponents(): array .[method] +-------------------------------- +Vrací přímé potomky jako pole. Klíče obsahují názvy těchto komponent. Poznámka: ve verzi 3.0.x metoda namísto pole vracela iterátor a její první parametr určoval, zda se mají komponenty procházet do hloubky, a druhý představoval typový filtr. Tyto parametry jsou deprecated. -K iterování slouží metoda [getComponents($deep = false, $type = null)|api:Nette\ComponentModel\Container::getComponents()]. První parametr určuje, zda se mají komponenty procházet do hloubky (neboli rekurzivně). S hodnotou `true` tedy nejen projde všechny komponenty, jichž je rodičem, ale také potomky svých potomků atd. Druhý parametr slouží jako volitelný filtr podle tříd nebo rozhraní. -```php -foreach ($form->getComponents(true, Nette\Forms\IControl::class) as $control) { - if (!$control->getRules()->validate()) { - // ... - } -} -``` +getComponentTree(): array .[method]{data-version:3.1.0} +------------------------------------------------------- +Získá celou hierarchii komponent včetně všech vnořených podřízených komponent jako indexované pole. Prohledávání jde nejprve do hloubky. Monitorování předků diff --git a/component-model/de/@home.texy b/component-model/de/@home.texy index 55372b2be6..01bbd76959 100644 --- a/component-model/de/@home.texy +++ b/component-model/de/@home.texy @@ -30,18 +30,14 @@ getComponent(string $name): ?Component .[method] Gibt eine Komponente zurück. Der Versuch, ein undefiniertes Kind aufzurufen, führt zum Aufruf der Fabrik [createComponent($name) |api:Nette\ComponentModel\Container::createComponent()]. Die Methode `createComponent($name)` ruft die Methode `createComponent` in der aktuellen Komponente auf und übergibt den Namen der Komponente als Parameter. Die erstellte Komponente wird dann an die aktuelle Komponente als ihr Kind übergeben. Wir nennen diese Komponentenfabriken, sie können in von `Container` geerbten Klassen implementiert werden. -Iteration über Kinder .[#toc-iterating-over-children] ------------------------------------------------------ +getComponents(): array .[method] +-------------------------------- +Gibt direkte Nachkommen als Array zurück. Die Schlüssel enthalten die Namen dieser Komponenten. Hinweis: In Version 3.0.x gab die Methode einen Iterator statt eines Arrays zurück. Der erste Parameter gab an, ob durch die Komponenten in der Tiefe iteriert werden sollte, und der zweite Parameter stellte einen Typfilter dar. Diese Parameter sind veraltet. -Die Methode [getComponents($deep = false, $type = null) |api:Nette\ComponentModel\Container::getComponents()] wird zur Iteration verwendet. Der erste Parameter gibt an, ob die Komponenten in der Tiefe (oder rekursiv) durchlaufen werden sollen. Bei `true` werden nicht nur alle untergeordneten Komponenten durchlaufen, sondern auch alle untergeordneten Komponenten der untergeordneten Komponenten, usw. Der zweite Parameter dient als optionaler Filter nach Klasse oder Schnittstelle. -```php -foreach ($form->getComponents(true, Nette\Forms\IControl::class) as $control) { - if (!$control->getRules()->validate()) { - // ... - } -} -``` +getComponentTree(): array .[method]{data-version:3.1.0} +------------------------------------------------------- +Gibt die gesamte Hierarchie der Komponenten, einschließlich aller verschachtelten untergeordneten Komponenten, als indiziertes Array zurück. Die Suche geht zunächst in die Tiefe. Überwachung der Vorfahren .[#toc-monitoring-of-ancestors] diff --git a/component-model/el/@home.texy b/component-model/el/@home.texy index d26b6d5527..7a347e617f 100644 --- a/component-model/el/@home.texy +++ b/component-model/el/@home.texy @@ -30,18 +30,14 @@ getComponent(string $name): ?Component .[method] Επιστρέφει ένα συστατικό. Η απόπειρα κλήσης απροσδιόριστου παιδιού προκαλεί κλήση του εργοστασίου [createComponent($name) |api:Nette\ComponentModel\Container::createComponent()]. Η μέθοδος `createComponent($name)` καλεί τη μέθοδο `createComponent` στο τρέχον συστατικό και περνά το όνομα του συστατικού ως παράμετρο. Το συστατικό που δημιουργήθηκε περνάει στη συνέχεια στο τρέχον συστατικό ως παιδί του. Ονομάζουμε αυτά τα εργοστάσια συστατικών, μπορούν να υλοποιηθούν σε κλάσεις που κληρονομούνται από το `Container`. -Επανάληψη σε παιδιά .[#toc-iterating-over-children] ---------------------------------------------------- +getComponents(): array .[method] +-------------------------------- +Επιστρέφει τους άμεσους απογόνους ως πίνακα. Τα κλειδιά περιέχουν τα ονόματα αυτών των στοιχείων. Σημείωση: στην έκδοση 3.0.x, η μέθοδος επέστρεφε έναν επαναλήπτη αντί για έναν πίνακα, και η πρώτη παράμετρος όριζε αν θα επαναλαμβάνονταν τα συστατικά σε βάθος και η δεύτερη αντιπροσώπευε ένα φίλτρο τύπου. Αυτές οι παράμετροι έχουν καταργηθεί. -Η μέθοδος [getComponents($deep = false, $type = null) |api:Nette\ComponentModel\Container::getComponents()] χρησιμοποιείται για την επανάληψη. Η πρώτη παράμετρος καθορίζει αν θα διατρέξει τα συστατικά σε βάθος (ή αναδρομικά). Με την `true`, δεν επαναλαμβάνει μόνο όλα τα παιδιά της, αλλά και όλα τα παιδιά των παιδιών της, κ.λπ. Η δεύτερη παράμετρος εξυπηρετεί ως προαιρετικό φίλτρο ανά κλάση ή διεπαφή. -```php -foreach ($form->getComponents(true, Nette\Forms\IControl::class) as $control) { - if (!$control->getRules()->validate()) { - // ... - } -} -``` +getComponentTree(): array .[method]{data-version:3.1.0} +------------------------------------------------------- +Επιστρέφει ολόκληρη την ιεραρχία των στοιχείων, συμπεριλαμβανομένων όλων των φωλιασμένων θυγατρικών στοιχείων ως πίνακα με ευρετήριο. Η αναζήτηση γίνεται πρώτα σε βάθος. Παρακολούθηση των προγόνων .[#toc-monitoring-of-ancestors] diff --git a/component-model/en/@home.texy b/component-model/en/@home.texy index 3ae5c4a808..1fa81fe327 100644 --- a/component-model/en/@home.texy +++ b/component-model/en/@home.texy @@ -30,18 +30,14 @@ getComponent(string $name): ?Component .[method] Returns a component. Attempt to call undefined child causes invoking of factory [createComponent($name)|api:Nette\ComponentModel\Container::createComponent()]. Method `createComponent($name)` invokes method `createComponent` in current component and it passes name of the component as a parameter. Created component is then passed to current component as its child. We call theese component factories, they can be implemented in classes inherited from `Container`. -Iterating over Children ------------------------ +getComponents(): array .[method] +-------------------------------- +Returns direct descendants as an array. The keys contain the names of these components. Note: in version 3.0.x, the method returned an iterator instead of an array, and its first parameter specified whether to iterate through the components in depth, and the second represented a type filter. These parameters are deprecated. -The [getComponents($deep = false, $type = null) |api:Nette\ComponentModel\Container::getComponents()] method is used for iteration. The first parameter specifies whether to traverse the components in depth (or recursively). With `true`, it not only iterates all its children, but also all children of its children, etc. Second parameter serves as an optional filter by class or interface. -```php -foreach ($form->getComponents(true, Nette\Forms\IControl::class) as $control) { - if (!$control->getRules()->validate()) { - // ... - } -} -``` +getComponentTree(): array .[method]{data-version:3.1.0} +------------------------------------------------------- +Returns the entire hierarchy of components, including all nested child components as indexed array. The search goes in depth first. Monitoring of Ancestors diff --git a/component-model/es/@home.texy b/component-model/es/@home.texy index 8e315b6f16..1c66c6b1ee 100644 --- a/component-model/es/@home.texy +++ b/component-model/es/@home.texy @@ -30,18 +30,14 @@ getComponent(string $name): ?Component .[method] Devuelve un componente. El intento de llamar a un hijo no definido provoca la invocación de la fábrica [createComponent($nombre) |api:Nette\ComponentModel\Container::createComponent()]. El método `createComponent($name)` invoca el método `createComponent` en el componente actual y pasa el nombre del componente como parámetro. El componente creado se pasa al componente actual como hijo. Llamamos a estas fábricas de componentes, pueden ser implementadas en clases heredadas de `Container`. -Iterando sobre hijos .[#toc-iterating-over-children] ----------------------------------------------------- +getComponents(): array .[method] +-------------------------------- +Devuelve los descendientes directos como una matriz. Las claves contienen los nombres de estos componentes. Nota: en la versión 3.0.x, el método devolvía un iterador en lugar de un array, y su primer parámetro especificaba si iterar a través de los componentes en profundidad, y el segundo representaba un filtro de tipo. Estos parámetros están obsoletos. -El método [getComponents($deep = false, $type = null) |api:Nette\ComponentModel\Container::getComponents()] se utiliza para la iteración. El primer parámetro especifica si se recorren los componentes en profundidad (o recursivamente). Con `true`, no sólo itera todos sus hijos, sino también todos los hijos de sus hijos, etc. El segundo parámetro sirve como filtro opcional por clase o interfaz. -```php -foreach ($form->getComponents(true, Nette\Forms\IControl::class) as $control) { - if (!$control->getRules()->validate()) { - // ... - } -} -``` +getComponentTree(): array .[method]{data-version:3.1.0} +------------------------------------------------------- +Devuelve toda la jerarquía de componentes, incluidos todos los componentes hijos anidados como matriz indexada. La búsqueda va primero en profundidad. Supervisión de antepasados .[#toc-monitoring-of-ancestors] diff --git a/component-model/fr/@home.texy b/component-model/fr/@home.texy index 2b03e9e9cb..7cd636b62a 100644 --- a/component-model/fr/@home.texy +++ b/component-model/fr/@home.texy @@ -30,18 +30,14 @@ getComponent(string $name): ?Component .[method] Renvoie un composant. La tentative d'appeler un enfant non défini entraîne l'invocation de la fabrique [createComponent($name) |api:Nette\ComponentModel\Container::createComponent()]. La méthode `createComponent($name)` invoque la méthode `createComponent` dans le composant courant et passe le nom du composant comme paramètre. Le composant créé est ensuite transmis au composant courant en tant que son enfant. Nous appelons ces usines de composants, elles peuvent être implémentées dans des classes héritées de `Container`. -Itération sur les enfants .[#toc-iterating-over-children] ---------------------------------------------------------- +getComponents(): array .[method] +-------------------------------- +Renvoie les descendants directs sous la forme d'un tableau. Les clés contiennent les noms de ces composants. Note : dans la version 3.0.x, la méthode renvoyait un itérateur au lieu d'un tableau, et son premier paramètre spécifiait s'il fallait itérer à travers les composants en profondeur, et le second représentait un filtre de type. Ces paramètres sont obsolètes. -La méthode [getComponents($deep = false, $type = null) |api:Nette\ComponentModel\Container::getComponents()] est utilisée pour l'itération. Le premier paramètre indique s'il faut parcourir les composants en profondeur (ou de manière récursive). Avec `true`, l'itération porte non seulement sur tous ses enfants, mais aussi sur tous les enfants de ses enfants, etc. Le deuxième paramètre sert de filtre optionnel par classe ou interface. -```php -foreach ($form->getComponents(true, Nette\Forms\IControl::class) as $control) { - if (!$control->getRules()->validate()) { - // ... - } -} -``` +getComponentTree(): array .[method]{data-version:3.1.0} +------------------------------------------------------- +Renvoie toute la hiérarchie des composants, y compris tous les composants enfants imbriqués, sous la forme d'un tableau indexé. La recherche se fait d'abord en profondeur. Surveillance des ancêtres .[#toc-monitoring-of-ancestors] diff --git a/component-model/hu/@home.texy b/component-model/hu/@home.texy index 6614800ff1..3ece462081 100644 --- a/component-model/hu/@home.texy +++ b/component-model/hu/@home.texy @@ -30,18 +30,14 @@ getComponent(string $name): ?Component .[method] Visszaad egy komponenst. A nem definiált gyermek hívásának kísérlete a factory [createComponent($name) |api:Nette\ComponentModel\Container::createComponent()] meghívását okozza. A `createComponent($name)` metódus meghívja a metódust `createComponent` az aktuális komponensben, és paraméterként átadja a komponens nevét. A létrehozott komponens ezután átadásra kerül az aktuális komponensnek, mint annak gyermeke. Ezeket a komponens gyáraknak nevezzük, a `Container`-tól örökölt osztályokban implementálhatók. -Iterálás a gyermekeken .[#toc-iterating-over-children] ------------------------------------------------------- +getComponents(): array .[method] +-------------------------------- +Közvetlen leszármazottakat ad vissza tömbként. A kulcsok ezen komponensek nevét tartalmazzák. Megjegyzés: a 3.0.x verzióban a módszer tömb helyett egy iterátort adott vissza, és az első paramétere megadta, hogy a komponenseket mélységben iterálja-e, a második pedig egy típusszűrőt jelentett. Ezek a paraméterek elavultak. -Az iterációhoz a [getComponents($deep = false, $type = null) |api:Nette\ComponentModel\Container::getComponents()] metódust használjuk. Az első paraméter megadja, hogy a komponensek mélységben (vagy rekurzívan) legyenek-e végigjárva. A `true` esetén nem csak az összes gyermekét iterálja, hanem a gyermekeinek összes gyermekét is, stb. A második paraméter kiszolgál, mint opcionális szűrő osztály vagy interfész szerint. -```php -foreach ($form->getComponents(true, Nette\Forms\IControl::class) as $control) { - if (!$control->getRules()->validate()) { - // ... - } -} -``` +getComponentTree(): array .[method]{data-version:3.1.0} +------------------------------------------------------- +Visszaadja a komponensek teljes hierarchiáját, beleértve az összes beágyazott gyermekkomponenst indexelt tömbként. A keresés először a mélységben történik. Az ősök figyelése .[#toc-monitoring-of-ancestors] diff --git a/component-model/it/@home.texy b/component-model/it/@home.texy index aec7bd942c..32ef2a8213 100644 --- a/component-model/it/@home.texy +++ b/component-model/it/@home.texy @@ -30,18 +30,14 @@ getComponent(string $name): ?Component .[method] Restituisce un componente. Il tentativo di chiamare un figlio non definito causa l'invocazione del factory [createComponent($nome) |api:Nette\ComponentModel\Container::createComponent()]. Il metodo `createComponent($name)` invoca il metodo `createComponent` nel componente corrente e passa il nome del componente come parametro. Il componente creato viene quindi passato al componente corrente come suo figlio. Questi factory di componenti possono essere implementati in classi ereditate da `Container`. -Iterazione sui figli .[#toc-iterating-over-children] ----------------------------------------------------- +getComponents(): array .[method] +-------------------------------- +Restituisce i discendenti diretti come array. Le chiavi contengono i nomi dei componenti. Nota: nella versione 3.0.x, il metodo restituiva un iteratore invece di un array e il primo parametro specificava se iterare i componenti in profondità e il secondo rappresentava un filtro di tipo. Questi parametri sono deprecati. -Il metodo [getComponents($deep = false, $type = null) |api:Nette\ComponentModel\Container::getComponents()] è usato per l'iterazione. Il primo parametro specifica se si deve attraversare i componenti in profondità (o in modo ricorsivo). Con `true`, non solo vengono iterati tutti i suoi figli, ma anche tutti i figli dei suoi figli, ecc. Il secondo parametro serve come filtro opzionale per classe o interfaccia. -```php -foreach ($form->getComponents(true, Nette\Forms\IControl::class) as $control) { - if (!$control->getRules()->validate()) { - // ... - } -} -``` +getComponentTree(): array .[method]{data-version:3.1.0} +------------------------------------------------------- +Restituisce l'intera gerarchia di componenti, compresi tutti i componenti figli annidati, come array indicizzato. La ricerca va prima in profondità. Monitoraggio degli antenati .[#toc-monitoring-of-ancestors] diff --git a/component-model/meta.json b/component-model/meta.json index b4b89b8c38..245d650e59 100644 --- a/component-model/meta.json +++ b/component-model/meta.json @@ -1,5 +1,5 @@ { - "version": "4.0", + "version": "3.x", "repo": "nette/component-model", "composer": "nette/component-model" } diff --git a/component-model/pl/@home.texy b/component-model/pl/@home.texy index 54dab24b99..7cb67547b1 100644 --- a/component-model/pl/@home.texy +++ b/component-model/pl/@home.texy @@ -30,18 +30,14 @@ getComponent(string $name): ?Component .[method] Zwraca element. Podczas próby uzyskania niezdefiniowanego dziecka wywoływana jest fabryka `createComponent($name)`. Metoda `createComponent($name)` wywołuje metodę w bieżącym komponencie `createComponent` i przekazuje nazwę komponentu jako parametr. Utworzony komponent jest następnie dodawany do bieżącego komponentu jako jego dziecko. Metody te nazywane są fabrykami komponentów i mogą być implementowane przez potomków klasy `Container`. -Iterowanie po potomkach .[#toc-iterovani-nad-potomky] ------------------------------------------------------ +getComponents(): array .[method] +-------------------------------- +Zwraca bezpośrednich potomków jako tablicę. Klucze zawierają nazwy tych komponentów. Uwaga: w wersji 3.0.x metoda zwracała iterator zamiast tablicy, a jej pierwszy parametr określał, czy iterować przez komponenty w głąb, a drugi reprezentował filtr typu. Te parametry są przestarzałe. -Do iteracji służy metoda [getComponents($deep = false, $type = null) |api:Nette\ComponentModel\Container::getComponents()]. Pierwszy parametr określa, czy przeglądać elementy w głębi (lub rekurencyjnie). Tak więc, z wartością `true`, nie tylko przemierza wszystkie komponenty, których jest rodzicem, ale także dzieci swoich dzieci, itd. Drugi parametr służy jako opcjonalny filtr według klasy lub interfejsu. -```php -foreach ($form->getComponents(true, Nette\Forms\IControl::class) as $control) { - if (!$control->getRules()->validate()) { - // ... - } -} -``` +getComponentTree(): array .[method]{data-version:3.1.0} +------------------------------------------------------- +Zwraca całą hierarchię komponentów, w tym wszystkie zagnieżdżone komponenty podrzędne, jako indeksowaną tablicę. Wyszukiwanie odbywa się najpierw w głąb. Monitorowanie przodków .[#toc-monitoring-of-ancestors] diff --git a/component-model/pt/@home.texy b/component-model/pt/@home.texy index 5782d43f3c..3aeb6d2e47 100644 --- a/component-model/pt/@home.texy +++ b/component-model/pt/@home.texy @@ -30,18 +30,14 @@ getComponent(string $name): ?Component .[method] Devolve um componente. Tentativa de chamar de criança indefinida causa invocação de fábrica [criarComponente($nome) |api:Nette\ComponentModel\Container::createComponent()]. Método `createComponent($name)` invoca método `createComponent` no componente atual e ele passa o nome do componente como parâmetro. O componente criado é então passado para o componente atual como seu filho. Chamamos essas fábricas de componentes, elas podem ser implementadas em classes herdadas de `Container`. -Iterando sobre as crianças .[#toc-iterating-over-children] ----------------------------------------------------------- +getComponents(): array .[method] +-------------------------------- +Retorna os descendentes diretos como uma matriz. As chaves contêm os nomes desses componentes. Observação: na versão 3.0.x, o método retornava um iterador em vez de uma matriz, e seu primeiro parâmetro especificava se deveria iterar pelos componentes em profundidade, e o segundo representava um filtro de tipo. Esses parâmetros estão obsoletos. -O método [getComponents($deep = falso, $type = nulo) |api:Nette\ComponentModel\Container::getComponents()] é usado para iteração. O primeiro parâmetro especifica se os componentes devem ser percorridos em profundidade (ou recursivamente). Com `true`, ele não só itera todos os seus filhos, mas também todos os filhos de seus filhos, etc. Segundo parâmetro servidores como um filtro opcional por classe ou interface. -```php -foreach ($form->getComponents(true, Nette\Forms\IControl::class) as $control) { - if (!$control->getRules()->validate()) { - // ... - } -} -``` +getComponentTree(): array .[method]{data-version:3.1.0} +------------------------------------------------------- +Retorna toda a hierarquia de componentes, inclusive todos os componentes filhos aninhados, como uma matriz indexada. A pesquisa é feita primeiro em profundidade. Monitoramento de Ancestrais .[#toc-monitoring-of-ancestors] diff --git a/component-model/ro/@home.texy b/component-model/ro/@home.texy index e2f31f4fa1..c028879630 100644 --- a/component-model/ro/@home.texy +++ b/component-model/ro/@home.texy @@ -30,18 +30,14 @@ getComponent(string $name): ?Component .[method] Returnează o componentă. Încercarea de a apela un copil nedefinit determină invocarea fabricii [createComponent($name) |api:Nette\ComponentModel\Container::createComponent()]. Metoda `createComponent($name)` invocă metoda `createComponent` în componenta curentă și transmite numele componentei ca parametru. Componenta creată este apoi transmisă componentei curente ca fiind copilul său. Numim aceste fabrici de componente, ele pot fi implementate în clase moștenite de la `Container`. -Iterarea peste copii .[#toc-iterating-over-children] ----------------------------------------------------- +getComponents(): array .[method] +-------------------------------- +Returnează descendenții direcți sub formă de matrice. Cheile conțin numele acestor componente. Notă: în versiunea 3.0.x, metoda returnează un iterator în loc de un tablou, iar primul parametru specifica dacă trebuie să se parcurgă componentele în profunzime, iar al doilea reprezenta un filtru de tip. Acești parametri sunt depreciați. -Metoda [getComponents($deep = false, $type = null) |api:Nette\ComponentModel\Container::getComponents()] este utilizată pentru iterație. Primul parametru specifică dacă se parcurge componentele în profunzime (sau recursiv). Cu `true`, nu numai că se iteră toți copiii săi, ci și toți copiii copiilor săi, etc. Al doilea parametru servește ca filtru opțional în funcție de clasă sau interfață. -```php -foreach ($form->getComponents(true, Nette\Forms\IControl::class) as $control) { - if (!$control->getRules()->validate()) { - // ... - } -} -``` +getComponentTree(): array .[method]{data-version:3.1.0} +------------------------------------------------------- +Returnează întreaga ierarhie de componente, inclusiv toate componentele copil imbricate, sub formă de matrice indexată. Căutarea se face mai întâi în profunzime. Monitorizarea strămoșilor .[#toc-monitoring-of-ancestors] diff --git a/component-model/ru/@home.texy b/component-model/ru/@home.texy index 1e7b97e436..94c2dd3ec8 100644 --- a/component-model/ru/@home.texy +++ b/component-model/ru/@home.texy @@ -30,18 +30,14 @@ getComponent(string $name): ?Component .[method] Возвращает компонент. Попытка вызова неопределенного дочернего компонента приводит к вызову фабрики [createComponent($name) |api:Nette\ComponentModel\Container::createComponent()]. Метод `createComponent($name)` вызывает метод `createComponent` в текущем компоненте и передает имя компонента в качестве параметра. Созданный компонент затем передается текущему компоненту как его дочерний компонент. Мы называем эти фабрики компонентов, они могут быть реализованы в классах, унаследованных от `Container`. -Итерация над дочерними компонентами .[#toc-iterating-over-children] -------------------------------------------------------------------- +getComponents(): array .[method] +-------------------------------- +Возвращает прямых потомков в виде массива. Ключи содержат имена этих компонентов. Примечание: в версии 3.0.x метод возвращал итератор вместо массива, а его первый параметр указывал, нужно ли выполнять глубокий итерационный просмотр компонентов, а второй представлял собой фильтр типов. Эти параметры устарели. -Метод [getComponents($deep = false, $type = null) |api:Nette\ComponentModel\Container::getComponents()] используется для итерации. Первый параметр определяет, следует ли обходить компоненты в глубину (или рекурсивно). При использовании `true` итерируется не только все его дочерние компоненты, но и все дочерние компоненты его дочерних компонентов и т.д. Второй параметр служит дополнительным фильтром по классу или интерфейсу. -```php -foreach ($form->getComponents(true, Nette\Forms\IControl::class) as $control) { - if (!$control->getRules()->validate()) { - // ... - } -} -``` +getComponentTree(): array .[method]{data-version:3.1.0} +------------------------------------------------------- +Возвращает всю иерархию компонентов, включая все вложенные дочерние компоненты, в виде индексированного массива. Поиск идет сначала в глубину. Мониторинг предков .[#toc-monitoring-of-ancestors] diff --git a/component-model/sl/@home.texy b/component-model/sl/@home.texy index 6577d3b5b4..56fb7db0ae 100644 --- a/component-model/sl/@home.texy +++ b/component-model/sl/@home.texy @@ -30,18 +30,14 @@ getComponent(string $name): ?Component .[method] Vrne komponento. Poskus klica nedefiniranega otroka povzroči klic tovarne [createComponent($name |api:Nette\ComponentModel\Container::createComponent()]). Metoda `createComponent($name)` prikliče metodo `createComponent` v trenutni komponenti in ji kot parameter posreduje ime komponente. Ustvarjena komponenta se nato posreduje trenutni komponenti kot njen otrok. Te tovarne komponent imenujemo tovarne komponent, ki jih lahko implementiramo v razredih, podedovanih iz `Container`. -Iteriranje nad otroki .[#toc-iterating-over-children] ------------------------------------------------------ +getComponents(): array .[method] +-------------------------------- +Vrne neposredne potomce kot polje. Ključi vsebujejo imena teh komponent. Opomba: v različici 3.0.x je metoda namesto polja vrnila iterator, njen prvi parameter pa je določal, ali naj se komponente iterira po globini, drugi pa je predstavljal filter tipa. Ta parametra sta zastarela. -Metoda [getComponents($deep = false, $type = null |api:Nette\ComponentModel\Container::getComponents()] ) se uporablja za iteracijo. Prvi parameter določa, ali naj se komponente preletijo po globini (ali rekurzivno). Pri `true` se ne iterira le po vseh njegovih otrocih, temveč tudi po vseh otrocih njegovih otrok itd. Drugi parameter služi kot izbirni filter po razredu ali vmesniku. -```php -foreach ($form->getComponents(true, Nette\Forms\IControl::class) as $control) { - if (!$control->getRules()->validate()) { - // ... - } -} -``` +getComponentTree(): array .[method]{data-version:3.1.0} +------------------------------------------------------- +Vrne celotno hierarhijo komponent, vključno z vsemi ugnezdenimi podrejenimi komponentami, kot indeksirano polje. Iskanje gre najprej v globino. Spremljanje prednikov .[#toc-monitoring-of-ancestors] diff --git a/component-model/tr/@home.texy b/component-model/tr/@home.texy index 799cbbd8e9..c8bfafb8d7 100644 --- a/component-model/tr/@home.texy +++ b/component-model/tr/@home.texy @@ -30,18 +30,14 @@ getComponent(string $name): ?Component .[method] Bir bileşen döndürür. Tanımsız alt öğeyi çağırma girişimi, [createComponent($name) |api:Nette\ComponentModel\Container::createComponent()] fabrikasının çağrılmasına neden olur. Yöntem `createComponent($name)` yöntemi çağırır `createComponent` ve bileşenin adını bir parametre olarak geçirir. Oluşturulan bileşen daha sonra mevcut bileşene çocuğu olarak aktarılır. Bunlara bileşen fabrikaları diyoruz, `Container` adresinden miras alınan sınıflarda uygulanabilirler. -Çocuklar üzerinde yineleme .[#toc-iterating-over-children] ----------------------------------------------------------- +getComponents(): array .[method] +-------------------------------- +Doğrudan torunları bir dizi olarak döndürür. Anahtarlar bu bileşenlerin adlarını içerir. Not: 3.0.x sürümünde, yöntem bir dizi yerine bir yineleyici döndürüyordu ve ilk parametresi bileşenler arasında derinlemesine yineleme yapılıp yapılmayacağını belirtiyordu, ikincisi ise bir tür filtresini temsil ediyordu. Bu parametreler kullanımdan kaldırılmıştır. -[getComponents($deep = false, $type = null) |api:Nette\ComponentModel\Container::getComponents()] yöntemi yineleme için kullanılır. İlk parametre, bileşenlerin derinlemesine (veya özyinelemeli olarak) dolaşılıp dolaşılmayacağını belirtir. `true` ile, yalnızca tüm çocuklarını değil, aynı zamanda çocuklarının tüm çocuklarını vb. yineler. İkinci parametre, sınıf veya arayüze göre isteğe bağlı bir filtre olarak sunucular. -```php -foreach ($form->getComponents(true, Nette\Forms\IControl::class) as $control) { - if (!$control->getRules()->validate()) { - // ... - } -} -``` +getComponentTree(): array .[method]{data-version:3.1.0} +------------------------------------------------------- +İç içe geçmiş tüm alt bileşenler de dahil olmak üzere tüm bileşen hiyerarşisini dizinlenmiş dizi olarak döndürür. Arama önce derinlemesine yapılır. Ataların İzlenmesi .[#toc-monitoring-of-ancestors] diff --git a/component-model/uk/@home.texy b/component-model/uk/@home.texy index 0a5621f301..4d69dd5ba6 100644 --- a/component-model/uk/@home.texy +++ b/component-model/uk/@home.texy @@ -30,18 +30,14 @@ getComponent(string $name): ?Component .[method] Повертає компонент. Спроба викликати невизначений дочірній компонент призводить до виклику фабричного [createComponent($name |api:Nette\ComponentModel\Container::createComponent()]). Метод `createComponent($name)` викликає метод `createComponent` в поточному компоненті і передає йому ім'я компонента як параметр. Створений компонент потім передається поточному компоненту як його дочірній компонент. Ми називаємо ці фабрики компонентів фабриками, вони можуть бути реалізовані в класах, успадкованих від `Container`. -Ітерація над дочірніми компонентами .[#toc-iterating-over-children] -------------------------------------------------------------------- +getComponents(): array .[method] +-------------------------------- +Повертає прямих нащадків у вигляді масиву. Ключі містять імена цих компонентів. Примітка: у версії 3.0.x метод повертав ітератор замість масиву, і його перший параметр вказував, чи потрібно перебирати компоненти вглиб, а другий представляв собою фільтр типу. Ці параметри застаріли. -Для ітерації використовується метод [getComponents($deep = false, $type = null |api:Nette\ComponentModel\Container::getComponents()] ). Перший параметр вказує, чи потрібно обходити компоненти вглиб (або рекурсивно). У випадку з `true` ітерація відбувається не лише по всіх дочірніх компонентах, але й по всіх дочірніх компонентах і т.д. Другий параметр слугує додатковим фільтром за класом або інтерфейсом. -```php -foreach ($form->getComponents(true, Nette\Forms\IControl::class) as $control) { - if (!$control->getRules()->validate()) { - // ... - } -} -``` +getComponentTree(): array .[method]{data-version:3.1.0} +------------------------------------------------------- +Повертає всю ієрархію компонентів, включаючи всі вкладені дочірні компоненти у вигляді індексованого масиву. Спочатку пошук йде вглиб. Моніторинг предків .[#toc-monitoring-of-ancestors] From a55e9c7af862e8fe333f73938c6d8857965c62d1 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 12 Feb 2024 22:19:05 +0100 Subject: [PATCH 052/137] nette/di 3.2 --- dependency-injection/bg/configuration.texy | 1 + dependency-injection/bg/factory.texy | 24 ++++++++++++++-------- dependency-injection/bg/services.texy | 7 +++++++ dependency-injection/cs/configuration.texy | 1 + dependency-injection/cs/factory.texy | 24 ++++++++++++++-------- dependency-injection/cs/services.texy | 7 +++++++ dependency-injection/de/configuration.texy | 1 + dependency-injection/de/factory.texy | 24 ++++++++++++++-------- dependency-injection/de/services.texy | 7 +++++++ dependency-injection/el/configuration.texy | 1 + dependency-injection/el/factory.texy | 24 ++++++++++++++-------- dependency-injection/el/services.texy | 7 +++++++ dependency-injection/en/configuration.texy | 1 + dependency-injection/en/factory.texy | 24 ++++++++++++++-------- dependency-injection/en/services.texy | 7 +++++++ dependency-injection/es/configuration.texy | 1 + dependency-injection/es/factory.texy | 24 ++++++++++++++-------- dependency-injection/es/services.texy | 7 +++++++ dependency-injection/fr/configuration.texy | 1 + dependency-injection/fr/factory.texy | 24 ++++++++++++++-------- dependency-injection/fr/services.texy | 7 +++++++ dependency-injection/hu/configuration.texy | 1 + dependency-injection/hu/factory.texy | 24 ++++++++++++++-------- dependency-injection/hu/services.texy | 7 +++++++ dependency-injection/it/configuration.texy | 1 + dependency-injection/it/factory.texy | 24 ++++++++++++++-------- dependency-injection/it/services.texy | 7 +++++++ dependency-injection/ja/configuration.texy | 1 + dependency-injection/ja/factory.texy | 24 ++++++++++++++-------- dependency-injection/ja/services.texy | 7 +++++++ dependency-injection/pl/configuration.texy | 1 + dependency-injection/pl/factory.texy | 24 ++++++++++++++-------- dependency-injection/pl/services.texy | 7 +++++++ dependency-injection/pt/configuration.texy | 1 + dependency-injection/pt/factory.texy | 24 ++++++++++++++-------- dependency-injection/pt/services.texy | 7 +++++++ dependency-injection/ro/configuration.texy | 1 + dependency-injection/ro/factory.texy | 24 ++++++++++++++-------- dependency-injection/ro/services.texy | 7 +++++++ dependency-injection/ru/configuration.texy | 1 + dependency-injection/ru/factory.texy | 24 ++++++++++++++-------- dependency-injection/ru/services.texy | 7 +++++++ dependency-injection/sl/configuration.texy | 1 + dependency-injection/sl/factory.texy | 24 ++++++++++++++-------- dependency-injection/sl/services.texy | 7 +++++++ dependency-injection/tr/configuration.texy | 1 + dependency-injection/tr/factory.texy | 24 ++++++++++++++-------- dependency-injection/tr/services.texy | 7 +++++++ dependency-injection/uk/configuration.texy | 1 + dependency-injection/uk/factory.texy | 24 ++++++++++++++-------- dependency-injection/uk/services.texy | 7 +++++++ 51 files changed, 391 insertions(+), 153 deletions(-) diff --git a/dependency-injection/bg/configuration.texy b/dependency-injection/bg/configuration.texy index 632d2f7f8c..b9ff04bf42 100644 --- a/dependency-injection/bg/configuration.texy +++ b/dependency-injection/bg/configuration.texy @@ -228,6 +228,7 @@ search: search: - in: %appDir% exclude: +файлове: ... classes: ... extends: ... implements: ... diff --git a/dependency-injection/bg/factory.texy b/dependency-injection/bg/factory.texy index d08862320c..43699fde67 100644 --- a/dependency-injection/bg/factory.texy +++ b/dependency-injection/bg/factory.texy @@ -170,39 +170,45 @@ services: interface MultiFactory { function createArticle(): Article; - function createFoo(): Model\Foo; function getDb(): PDO; } ``` Така че вместо да предадем няколко генерирани фабрики и аксесори, ще предадем друга сложна фабрика, която може да прави повече. -Алтернативно, вместо няколко метода, можем да използваме параметрите `create()` и `get()`: +Вместо това можете да използвате `get()` с параметър вместо няколко метода: ```php interface MultiFactoryAlt { - function create($name); function get($name): PDO; } ``` -Тогава `MultiFactory::createArticle()` прави същото като `MultiFactoryAlt::create('article')`. Алтернативният запис обаче има недостатъка, че не е ясно кои стойности поддържа `$name` и не е логически възможно да се разграничат различните стойности на връщане за различните `$name` в интерфейса. +В този случай `MultiFactory::getArticle()` прави същото, което и `MultiFactoryAlt::get('article')`. Алтернативният синтаксис обаче има няколко недостатъка. Не е ясно кои стойности на `$name` се поддържат, а типът на връщане не може да бъде посочен в интерфейса, когато се използват няколко различни стойности на `$name`. Определение за списък .[#toc-definition-with-a-list] ---------------------------------------------------- -И как да дефинираме множество фабрики в конфигурацията? Ще създадем три услуги за създаване/извличане и след това самата фабрика: +Този начин може да се използва за дефиниране на множество фабрики в конфигурацията: .{data-version:3.2.0} + +```neon +services: + - MultiFactory( + article: Article # defines createArticle() + db: PDO(%dsn%, %user%, %password%) # defines getDb() + ) +``` + +Или в дефиницията на фабриката можем да се позовем на съществуващи услуги с помощта на референция: ```neon services: article: Article - - Model\Foo - PDO(%dsn%, %user%, %password%) - MultiFactory( - article: @article # createArticle() - foo: @Model\Foo # createFoo() - db: @\PDO # getDb() + article: @article # defines createArticle() + db: @\PDO # defines getDb() ) ``` diff --git a/dependency-injection/bg/services.texy b/dependency-injection/bg/services.texy index 4a706d4a28..4092d43fdf 100644 --- a/dependency-injection/bg/services.texy +++ b/dependency-injection/bg/services.texy @@ -249,6 +249,13 @@ Collator::create(%locale%) @Nette\Database\Connection ``` +Използвайте синтаксис на първокласни извиквания: .{data-version:3.2.0} + +```neon +# creating a callback, equivalent to [@user, logout] +@user::logout(...) +``` + Използвайте константи: ```neon diff --git a/dependency-injection/cs/configuration.texy b/dependency-injection/cs/configuration.texy index 6381fe31dd..4b80e78339 100644 --- a/dependency-injection/cs/configuration.texy +++ b/dependency-injection/cs/configuration.texy @@ -228,6 +228,7 @@ Lze definovat i vylučující pravidla, tj. masky názvu třídy nebo dědičné search: - in: %appDir% exclude: + files: ... classes: ... extends: ... implements: ... diff --git a/dependency-injection/cs/factory.texy b/dependency-injection/cs/factory.texy index 1398077e88..082f32d37e 100644 --- a/dependency-injection/cs/factory.texy +++ b/dependency-injection/cs/factory.texy @@ -170,39 +170,45 @@ Naše továrny a accessory uměly zatím vždy vyrábět nebo vracet jen jeden o interface MultiFactory { function createArticle(): Article; - function createFoo(): Model\Foo; function getDb(): PDO; } ``` Takže místo toho, abych si předávali několik generovaných továren a accessorů, předáme jednu komplexnější továrnu, která toho umí víc. -Alternativně lze místo několika metod použít `create()` a `get()` s parameterem: +Alternativně lze místo několika metod použít `get()` s parameterem: ```php interface MultiFactoryAlt { - function create($name); function get($name): PDO; } ``` -Pak platí, že `MultiFactory::createArticle()` dělá totéž jako `MultiFactoryAlt::create('article')`. Nicméně alternativní zápis má tu nevýhodu, že není zřejmé, jaké hodnoty `$name` jsou podporované a logicky také nelze v rozhraní odlišit různé návratové hodnoty pro různé `$name`. +Pak platí, že `MultiFactory::getArticle()` dělá totéž jako `MultiFactoryAlt::get('article')`. Nicméně alternativní zápis má tu nevýhodu, že není zřejmé, jaké hodnoty `$name` jsou podporované a logicky také nelze v rozhraní odlišit různé návratové hodnoty pro různé `$name`. Definice seznamem ----------------- -A jak definovat vícenásobnou továrnu v konfiguraci? Vytvoříme tři služby, které bude vytvářet/vracet, a potom samotnou továrnu: +Tímto způsobem lze definovat vícenásobnou továrnu v konfiguraci: .{data-version:3.2.0} + +```neon +services: + - MultiFactory( + article: Article # definuje createArticle() + db: PDO(%dsn%, %user%, %password%) # definuje getDb() + ) +``` + +Nebo se můžeme v definici továrny odkázat na existující služby pomocí reference: ```neon services: article: Article - - Model\Foo - PDO(%dsn%, %user%, %password%) - MultiFactory( - article: @article # createArticle() - foo: @Model\Foo # createFoo() - db: @\PDO # getDb() + article: @article # definuje createArticle() + db: @\PDO # definuje getDb() ) ``` diff --git a/dependency-injection/cs/services.texy b/dependency-injection/cs/services.texy index d01aacec4e..1a6d98c136 100644 --- a/dependency-injection/cs/services.texy +++ b/dependency-injection/cs/services.texy @@ -249,6 +249,13 @@ Odkazovat se na služby buď jejich jménem nebo pomocí typu: @Nette\Database\Connection ``` +Používat first-class callable syntax: .{data-version:3.2.0} + +```neon +# vytvoření callbacku, obdoba [@user, logout] +@user::logout(...) +``` + Používat konstanty: ```neon diff --git a/dependency-injection/de/configuration.texy b/dependency-injection/de/configuration.texy index 1667c365d3..d8fd5fbb37 100644 --- a/dependency-injection/de/configuration.texy +++ b/dependency-injection/de/configuration.texy @@ -228,6 +228,7 @@ Sie können auch negative Regeln definieren, z. B. Klassennamensmasken oder Vorf search: - in: %appDir% exclude: +Dateien: ... classes: ... extends: ... implements: ... diff --git a/dependency-injection/de/factory.texy b/dependency-injection/de/factory.texy index e0381a449d..c5ea50f342 100644 --- a/dependency-injection/de/factory.texy +++ b/dependency-injection/de/factory.texy @@ -170,39 +170,45 @@ Bisher konnten die Fabriken und Accessoren nur ein einziges Objekt erstellen ode interface MultiFactory { function createArticle(): Article; - function createFoo(): Model\Foo; function getDb(): PDO; } ``` Anstatt mehrere generierte Fabriken und Accessoren zu übergeben, können Sie nur eine komplexe Multifabrik übergeben. -Alternativ können Sie auch `create()` und `get()` mit einem Parameter anstelle mehrerer Methoden verwenden: +Alternativ können Sie auch `get()` mit einem Parameter anstelle von mehreren Methoden verwenden: ```php interface MultiFactoryAlt { - function create($name); function get($name): PDO; } ``` -In diesem Fall bewirkt `MultiFactory::createArticle()` das Gleiche wie `MultiFactoryAlt::create('article')`. Die alternative Syntax hat jedoch einige Nachteile. Es ist nicht klar, welche `$name` Werte unterstützt werden und der Rückgabetyp kann nicht in der Schnittstelle angegeben werden, wenn mehrere verschiedene `$name` Werte verwendet werden. +In diesem Fall bewirkt `MultiFactory::getArticle()` dasselbe wie `MultiFactoryAlt::get('article')`. Die alternative Syntax hat jedoch einige Nachteile. Es ist nicht klar, welche `$name` Werte unterstützt werden, und der Rückgabetyp kann nicht in der Schnittstelle angegeben werden, wenn mehrere verschiedene `$name` Werte verwendet werden. Definition mit einer Liste .[#toc-definition-with-a-list] --------------------------------------------------------- -Wie definieren Sie eine Multifabrik in Ihrer Konfiguration? Lassen Sie uns drei Dienste erstellen, die von der Multifabrik zurückgegeben werden, und die Multifabrik selbst: +Auf diese Weise können Sie in der Konfiguration eine Mehrfachfabrik definieren: .{data-version:3.2.0} + +```neon +services: + - MultiFactory( + article: Article # defines createArticle() + db: PDO(%dsn%, %user%, %password%) # defines getDb() + ) +``` + +Oder wir können in der Fabrikdefinition auf bestehende Dienste mit einer Referenz verweisen: ```neon services: article: Article - - Model\Foo - PDO(%dsn%, %user%, %password%) - MultiFactory( - article: @article # createArticle() - foo: @Model\Foo # createFoo() - db: @\PDO # getDb() + article: @article # defines createArticle() + db: @\PDO # defines getDb() ) ``` diff --git a/dependency-injection/de/services.texy b/dependency-injection/de/services.texy index 5268e28378..a02717a802 100644 --- a/dependency-injection/de/services.texy +++ b/dependency-injection/de/services.texy @@ -249,6 +249,13 @@ Beziehen Sie sich auf Dienste entweder durch ihren Namen oder durch ihren Typ: @Nette\Database\Connection ``` +Verwenden Sie die Syntax von First-Class Callables: .{data-version:3.2.0} + +```neon +# creating a callback, equivalent to [@user, logout] +@user::logout(...) +``` + Verwenden Sie Konstanten: ```neon diff --git a/dependency-injection/el/configuration.texy b/dependency-injection/el/configuration.texy index 6eb46f33c4..b99ecbbcf9 100644 --- a/dependency-injection/el/configuration.texy +++ b/dependency-injection/el/configuration.texy @@ -228,6 +228,7 @@ search: search: - in: %appDir% exclude: +αρχεία: ... classes: ... extends: ... implements: ... diff --git a/dependency-injection/el/factory.texy b/dependency-injection/el/factory.texy index cb608707a4..ae2f1951f0 100644 --- a/dependency-injection/el/factory.texy +++ b/dependency-injection/el/factory.texy @@ -170,39 +170,45 @@ Multifactory/Accessor .[#toc-multifactory-accessor] interface MultiFactory { function createArticle(): Article; - function createFoo(): Model\Foo; function getDb(): PDO; } ``` Αντί να περνάτε πολλαπλά παραγόμενα εργοστάσια και accessors, μπορείτε να περνάτε μόνο ένα σύνθετο multifactory. -Εναλλακτικά, μπορείτε να χρησιμοποιήσετε τις διευθύνσεις `create()` και `get()` με μια παράμετρο αντί για πολλαπλές μεθόδους: +Εναλλακτικά, μπορείτε να χρησιμοποιήσετε το `get()` με μια παράμετρο αντί για πολλαπλές μεθόδους: ```php interface MultiFactoryAlt { - function create($name); function get($name): PDO; } ``` -Στην περίπτωση αυτή, η `MultiFactory::createArticle()` κάνει το ίδιο πράγμα με την `MultiFactoryAlt::create('article')`. Ωστόσο, η εναλλακτική σύνταξη έχει μερικά μειονεκτήματα. Δεν είναι σαφές ποιες τιμές `$name` υποστηρίζονται και ο τύπος επιστροφής δεν μπορεί να καθοριστεί στη διεπαφή όταν χρησιμοποιούνται πολλαπλές διαφορετικές τιμές `$name`. +Σε αυτή την περίπτωση, το `MultiFactory::getArticle()` κάνει το ίδιο πράγμα με το `MultiFactoryAlt::get('article')`. Ωστόσο, η εναλλακτική σύνταξη έχει μερικά μειονεκτήματα. Δεν είναι σαφές ποιες τιμές `$name` υποστηρίζονται και ο τύπος επιστροφής δεν μπορεί να καθοριστεί στη διεπαφή όταν χρησιμοποιούνται πολλές διαφορετικές τιμές `$name`. Ορισμός με λίστα .[#toc-definition-with-a-list] ----------------------------------------------- -Πώς να ορίσετε ένα multifactory στη διαμόρφωσή σας; Ας δημιουργήσουμε τρεις υπηρεσίες που θα επιστρέφονται από το multifactory, καθώς και το ίδιο το multifactory: +Αυτός ο τρόπος μπορεί να χρησιμοποιηθεί για τον ορισμό ενός πολλαπλού εργοστασίου στη διαμόρφωση: .{data-version:3.2.0} + +```neon +services: + - MultiFactory( + article: Article # defines createArticle() + db: PDO(%dsn%, %user%, %password%) # defines getDb() + ) +``` + +Ή, στον ορισμό του εργοστασίου, μπορούμε να αναφερθούμε σε υπάρχουσες υπηρεσίες χρησιμοποιώντας μια αναφορά: ```neon services: article: Article - - Model\Foo - PDO(%dsn%, %user%, %password%) - MultiFactory( - article: @article # createArticle() - foo: @Model\Foo # createFoo() - db: @\PDO # getDb() + article: @article # defines createArticle() + db: @\PDO # defines getDb() ) ``` diff --git a/dependency-injection/el/services.texy b/dependency-injection/el/services.texy index 2d958a373c..81c7740e4e 100644 --- a/dependency-injection/el/services.texy +++ b/dependency-injection/el/services.texy @@ -249,6 +249,13 @@ Collator::create(%locale%) @Nette\Database\Connection ``` +Χρησιμοποιήστε σύνταξη πρώτης κατηγορίας callable: .{data-version:3.2.0} + +```neon +# creating a callback, equivalent to [@user, logout] +@user::logout(...) +``` + Χρήση σταθερών: ```neon diff --git a/dependency-injection/en/configuration.texy b/dependency-injection/en/configuration.texy index 2f956842bc..4400910043 100644 --- a/dependency-injection/en/configuration.texy +++ b/dependency-injection/en/configuration.texy @@ -228,6 +228,7 @@ You can also define negative rules, ie class name masks or ancestors and if they search: - in: %appDir% exclude: + files: ... classes: ... extends: ... implements: ... diff --git a/dependency-injection/en/factory.texy b/dependency-injection/en/factory.texy index daf99d3f3f..e96c7c385c 100644 --- a/dependency-injection/en/factory.texy +++ b/dependency-injection/en/factory.texy @@ -170,39 +170,45 @@ So far, the factories and accessors could only create or return just one object. interface MultiFactory { function createArticle(): Article; - function createFoo(): Model\Foo; function getDb(): PDO; } ``` Instead of passing multiple generated factories and accessors, you can pass just one complex multifactory. -Alternatively, you can use `create()` and `get()` with a parameter instead of multiple methods: +Alternatively, you can use `get()` with a parameter instead of multiple methods: ```php interface MultiFactoryAlt { - function create($name); function get($name): PDO; } ``` -In this case, `MultiFactory::createArticle()` does the same thing as `MultiFactoryAlt::create('article')`. However, the alternative syntax has a few disadvantages. It's not clear which `$name` values are supported and the return type cannot be specified in the interface when using multiple different `$name` values. +In this case, `MultiFactory::getArticle()` does the same thing as `MultiFactoryAlt::get('article')`. However, the alternative syntax has a few disadvantages. It's not clear which `$name` values are supported and the return type cannot be specified in the interface when using multiple different `$name` values. Definition with a List ---------------------- -Hos to define a multifactory in your configuration? Let's create three services which will be returned by the multifactory, and the multifactory itself: +This way can be used to define a multiple factory in the configuration: .{data-version:3.2.0} + +```neon +services: + - MultiFactory( + article: Article # defines createArticle() + db: PDO(%dsn%, %user%, %password%) # defines getDb() + ) +``` + +Or, in the factory definition, we can refer to existing services using a reference: ```neon services: article: Article - - Model\Foo - PDO(%dsn%, %user%, %password%) - MultiFactory( - article: @article # createArticle() - foo: @Model\Foo # createFoo() - db: @\PDO # getDb() + article: @article # defines createArticle() + db: @\PDO # defines getDb() ) ``` diff --git a/dependency-injection/en/services.texy b/dependency-injection/en/services.texy index 32fac58212..d1f30a9613 100644 --- a/dependency-injection/en/services.texy +++ b/dependency-injection/en/services.texy @@ -249,6 +249,13 @@ Refer to services either by their name or by type: @Nette\Database\Connection ``` +Use first-class callable syntax: .{data-version:3.2.0} + +```neon +# creating a callback, equivalent to [@user, logout] +@user::logout(...) +``` + Use constants: ```neon diff --git a/dependency-injection/es/configuration.texy b/dependency-injection/es/configuration.texy index ee2c113acb..ae0b652501 100644 --- a/dependency-injection/es/configuration.texy +++ b/dependency-injection/es/configuration.texy @@ -228,6 +228,7 @@ También se pueden definir reglas negativas, es decir, máscaras de nombres de c search: - in: %appDir% exclude: +archivos: ... classes: ... extends: ... implements: ... diff --git a/dependency-injection/es/factory.texy b/dependency-injection/es/factory.texy index 29891ce0a5..4e6151853f 100644 --- a/dependency-injection/es/factory.texy +++ b/dependency-injection/es/factory.texy @@ -170,39 +170,45 @@ Hasta ahora, los factories (fábricas) y los accessors sólo podían crear o dev interface MultiFactory { function createArticle(): Article; - function createFoo(): Model\Foo; function getDb(): PDO; } ``` En lugar de pasar múltiples fábricas y accessors generados, puedes pasar un único multifactory complejo. -Alternativamente, puedes usar `create()` y `get()` con un parámetro en lugar de múltiples métodos: +También puede utilizar `get()` con un parámetro en lugar de varios métodos: ```php interface MultiFactoryAlt { - function create($name); function get($name): PDO; } ``` -En este caso, `MultiFactory::createArticle()` hace lo mismo que `MultiFactoryAlt::create('article')`. Sin embargo, la sintaxis alternativa tiene algunas desventajas. No está claro qué valores de `$name` están soportados y el tipo de retorno no puede especificarse en la interfaz cuando se utilizan múltiples valores diferentes de `$name`. +En este caso, `MultiFactory::getArticle()` hace lo mismo que `MultiFactoryAlt::get('article')`. Sin embargo, la sintaxis alternativa tiene algunas desventajas. No está claro qué valores de `$name` son compatibles y el tipo de retorno no se puede especificar en la interfaz cuando se utilizan varios valores diferentes de `$name`. Definición con una lista .[#toc-definition-with-a-list] ------------------------------------------------------- -¿Cómo definir un multifactory en tu configuración? Vamos a crear tres servicios que serán devueltos por el multifactory, y el propio multifactory: +De esta forma se puede definir una fábrica múltiple en la configuración: .{data-version:3.2.0} + +```neon +services: + - MultiFactory( + article: Article # defines createArticle() + db: PDO(%dsn%, %user%, %password%) # defines getDb() + ) +``` + +O bien, en la definición de la fábrica, podemos hacer referencia a los servicios existentes utilizando una referencia: ```neon services: article: Article - - Model\Foo - PDO(%dsn%, %user%, %password%) - MultiFactory( - article: @article # createArticle() - foo: @Model\Foo # createFoo() - db: @\PDO # getDb() + article: @article # defines createArticle() + db: @\PDO # defines getDb() ) ``` diff --git a/dependency-injection/es/services.texy b/dependency-injection/es/services.texy index 44176f808f..2eec71a83b 100644 --- a/dependency-injection/es/services.texy +++ b/dependency-injection/es/services.texy @@ -249,6 +249,13 @@ Referirse a los servicios por su nombre o por su tipo: @Nette\Database\Connection ``` +Utilizar sintaxis de llamada de primera clase: .{data-version:3.2.0} + +```neon +# creating a callback, equivalent to [@user, logout] +@user::logout(...) +``` + Utilizar constantes: ```neon diff --git a/dependency-injection/fr/configuration.texy b/dependency-injection/fr/configuration.texy index c6142b5867..1970ea21e7 100644 --- a/dependency-injection/fr/configuration.texy +++ b/dependency-injection/fr/configuration.texy @@ -228,6 +228,7 @@ Vous pouvez également définir des règles négatives, c'est-à-dire des masque search: - in: %appDir% exclude: +fichiers : ... classes: ... extends: ... implements: ... diff --git a/dependency-injection/fr/factory.texy b/dependency-injection/fr/factory.texy index a57c5fa1da..7c49950361 100644 --- a/dependency-injection/fr/factory.texy +++ b/dependency-injection/fr/factory.texy @@ -170,39 +170,45 @@ Jusqu'à présent, les fabriques et les accesseurs ne pouvaient créer ou renvoy interface MultiFactory { function createArticle(): Article; - function createFoo(): Model\Foo; function getDb(): PDO; } ``` Au lieu de passer plusieurs fabriques et accesseurs générés, vous pouvez passer une seule multifactory complexe. -Vous pouvez également utiliser `create()` et `get()` avec un paramètre au lieu de plusieurs méthodes : +Vous pouvez également utiliser `get()` avec un paramètre au lieu de plusieurs méthodes : ```php interface MultiFactoryAlt { - function create($name); function get($name): PDO; } ``` -Dans ce cas, `MultiFactory::createArticle()` fait la même chose que `MultiFactoryAlt::create('article')`. Toutefois, cette syntaxe alternative présente quelques inconvénients. On ne sait pas clairement quelles valeurs de `$name` sont prises en charge et le type de retour ne peut pas être spécifié dans l'interface lorsqu'on utilise plusieurs valeurs différentes de `$name`. +Dans ce cas, `MultiFactory::getArticle()` fait la même chose que `MultiFactoryAlt::get('article')`. Cependant, la syntaxe alternative présente quelques inconvénients. Les valeurs `$name` prises en charge ne sont pas claires et le type de retour ne peut pas être spécifié dans l'interface en cas d'utilisation de plusieurs valeurs `$name` différentes. Définition avec une liste .[#toc-definition-with-a-list] -------------------------------------------------------- -Comment définir un multifactory dans votre configuration ? Créons trois services qui seront retournés par le multifactory, et le multifactory lui-même : +Cette méthode peut être utilisée pour définir une usine multiple dans la configuration : .{data-version:3.2.0} + +```neon +services: + - MultiFactory( + article: Article # defines createArticle() + db: PDO(%dsn%, %user%, %password%) # defines getDb() + ) +``` + +Ou bien, dans la définition de la fabrique, nous pouvons nous référer à des services existants en utilisant une référence : ```neon services: article: Article - - Model\Foo - PDO(%dsn%, %user%, %password%) - MultiFactory( - article: @article # createArticle() - foo: @Model\Foo # createFoo() - db: @\PDO # getDb() + article: @article # defines createArticle() + db: @\PDO # defines getDb() ) ``` diff --git a/dependency-injection/fr/services.texy b/dependency-injection/fr/services.texy index 0e9e312fbf..ecfd61ae7a 100644 --- a/dependency-injection/fr/services.texy +++ b/dependency-injection/fr/services.texy @@ -249,6 +249,13 @@ Faire référence aux services soit par leur nom, soit par leur type : @Nette\Database\Connection ``` +Utiliser une syntaxe d'appel de première classe : .{data-version:3.2.0} + +```neon +# creating a callback, equivalent to [@user, logout] +@user::logout(...) +``` + Utiliser des constantes : ```neon diff --git a/dependency-injection/hu/configuration.texy b/dependency-injection/hu/configuration.texy index 3b883fe631..ed9aa0144e 100644 --- a/dependency-injection/hu/configuration.texy +++ b/dependency-injection/hu/configuration.texy @@ -228,6 +228,7 @@ Meghatározhatunk negatív szabályokat is, azaz osztálynév maszkokat vagy ős search: - in: %appDir% exclude: +fájlok: ... classes: ... extends: ... implements: ... diff --git a/dependency-injection/hu/factory.texy b/dependency-injection/hu/factory.texy index 1929e3e8ec..438effdcc6 100644 --- a/dependency-injection/hu/factory.texy +++ b/dependency-injection/hu/factory.texy @@ -170,39 +170,45 @@ Eddig a factories és accessorok csak egy objektumot tudtak létrehozni vagy vis interface MultiFactory { function createArticle(): Article; - function createFoo(): Model\Foo; function getDb(): PDO; } ``` Ahelyett, hogy több generált gyárat és accessort adna át, csak egy összetett multifactory-t adhat át. -Alternatívaként több metódus helyett használhatja a `create()` és a `get()` egy paramétert: +Alternatívaként használhatja a `get()` címet is egy paraméterrel, több metódus helyett: ```php interface MultiFactoryAlt { - function create($name); function get($name): PDO; } ``` -Ebben az esetben a `MultiFactory::createArticle()` ugyanazt teszi, mint a `MultiFactoryAlt::create('article')`. Az alternatív szintaxisnak azonban van néhány hátránya. Nem egyértelmű, hogy mely `$name` értékek támogatottak, és több különböző `$name` érték használata esetén a visszatérési típus nem adható meg az interfészben. +Ebben az esetben a `MultiFactory::getArticle()` ugyanazt teszi, mint a `MultiFactoryAlt::get('article')`. Az alternatív szintaxisnak azonban van néhány hátránya. Nem egyértelmű, hogy mely `$name` értékek támogatottak, és a visszatérési típus nem adható meg az interfészben, ha több különböző `$name` értéket használunk. Definíció listával .[#toc-definition-with-a-list] ------------------------------------------------- -Hos definiálni egy multifactory-t a konfigurációban? Hozzunk létre három szolgáltatást, amelyeket a multifactory fog visszaadni, és magát a multifactory-t: +Így több gyárat lehet definiálni a konfigurációban: .{data-version:3.2.0} + +```neon +services: + - MultiFactory( + article: Article # defines createArticle() + db: PDO(%dsn%, %user%, %password%) # defines getDb() + ) +``` + +Vagy a gyár definíciójában hivatkozással hivatkozhatunk meglévő szolgáltatásokra: ```neon services: article: Article - - Model\Foo - PDO(%dsn%, %user%, %password%) - MultiFactory( - article: @article # createArticle() - foo: @Model\Foo # createFoo() - db: @\PDO # getDb() + article: @article # defines createArticle() + db: @\PDO # defines getDb() ) ``` diff --git a/dependency-injection/hu/services.texy b/dependency-injection/hu/services.texy index 3b933b1ab5..50fb688c91 100644 --- a/dependency-injection/hu/services.texy +++ b/dependency-injection/hu/services.texy @@ -249,6 +249,13 @@ A szolgáltatásokra a nevük vagy a típusuk alapján hivatkozhatunk: @Nette\Database\Connection ``` +Első osztályú hívható szintaxis használata: .{data-version:3.2.0} + +```neon +# creating a callback, equivalent to [@user, logout] +@user::logout(...) +``` + Konstanciák használata: ```neon diff --git a/dependency-injection/it/configuration.texy b/dependency-injection/it/configuration.texy index 4307f5c7ad..628d6a3bc0 100644 --- a/dependency-injection/it/configuration.texy +++ b/dependency-injection/it/configuration.texy @@ -228,6 +228,7 @@ Si possono anche definire regole negative, cioè maschere di nomi di classi o an search: - in: %appDir% exclude: +file: ... classes: ... extends: ... implements: ... diff --git a/dependency-injection/it/factory.texy b/dependency-injection/it/factory.texy index d2645a41ed..8eafe7bbc9 100644 --- a/dependency-injection/it/factory.texy +++ b/dependency-injection/it/factory.texy @@ -170,39 +170,45 @@ Finora, i factory e gli accessor potevano creare o restituire un solo oggetto. interface MultiFactory { function createArticle(): Article; - function createFoo(): Model\Foo; function getDb(): PDO; } ``` Invece di passare più factory e accessor generati, si può passare un solo multifactory complesso. -In alternativa, si possono usare `create()` e `get()` con un parametro, invece di più metodi: +In alternativa, si può usare `get()` con un parametro invece di più metodi: ```php interface MultiFactoryAlt { - function create($name); function get($name): PDO; } ``` -In questo caso, `MultiFactory::createArticle()` fa la stessa cosa di `MultiFactoryAlt::create('article')`. Tuttavia, la sintassi alternativa presenta alcuni svantaggi. Non è chiaro quali valori di `$name` siano supportati e il tipo di ritorno non può essere specificato nell'interfaccia quando si usano più valori diversi di `$name`. +In questo caso, `MultiFactory::getArticle()` fa la stessa cosa di `MultiFactoryAlt::get('article')`. Tuttavia, la sintassi alternativa presenta alcuni svantaggi. Non è chiaro quali valori di `$name` siano supportati e il tipo di ritorno non può essere specificato nell'interfaccia quando si usano più valori diversi di `$name`. Definizione con un elenco .[#toc-definition-with-a-list] -------------------------------------------------------- -Come definire una multifactory nella propria configurazione? Creiamo tre servizi che saranno restituiti dalla multifactory e la multifactory stessa: +Questo modo può essere usato per definire una fabbrica multipla nella configurazione: .{data-version:3.2.0} + +```neon +services: + - MultiFactory( + article: Article # defines createArticle() + db: PDO(%dsn%, %user%, %password%) # defines getDb() + ) +``` + +Oppure, nella definizione del factory, si può fare riferimento a servizi esistenti usando un riferimento: ```neon services: article: Article - - Model\Foo - PDO(%dsn%, %user%, %password%) - MultiFactory( - article: @article # createArticle() - foo: @Model\Foo # createFoo() - db: @\PDO # getDb() + article: @article # defines createArticle() + db: @\PDO # defines getDb() ) ``` diff --git a/dependency-injection/it/services.texy b/dependency-injection/it/services.texy index bf2d53ce0a..d445cbeb8d 100644 --- a/dependency-injection/it/services.texy +++ b/dependency-injection/it/services.texy @@ -249,6 +249,13 @@ Fare riferimento ai servizi con il loro nome o con il loro tipo: @Nette\Database\Connection ``` +Usare la sintassi dei callable di prima classe: .{data-version:3.2.0} + +```neon +# creating a callback, equivalent to [@user, logout] +@user::logout(...) +``` + Utilizzare le costanti: ```neon diff --git a/dependency-injection/ja/configuration.texy b/dependency-injection/ja/configuration.texy index a5e0019136..a6417023d2 100644 --- a/dependency-injection/ja/configuration.texy +++ b/dependency-injection/ja/configuration.texy @@ -228,6 +228,7 @@ search: search: - in: %appDir% exclude: +ファイル: ... classes: ... extends: ... implements: ... diff --git a/dependency-injection/ja/factory.texy b/dependency-injection/ja/factory.texy index 726203ee1b..80d8064a3c 100644 --- a/dependency-injection/ja/factory.texy +++ b/dependency-injection/ja/factory.texy @@ -170,39 +170,45 @@ services: interface MultiFactory { function createArticle(): Article; - function createFoo(): Model\Foo; function getDb(): PDO; } ``` 生成された複数のファクトリーとアクセッサを渡す代わりに、複雑なマルチファクトリーを1つだけ渡すことができます。 -あるいは、複数のメソッドの代わりに、パラメータで`create()` と`get()` を使うこともできます。 +あるいは、複数のメソッドの代わりに、`get()` をパラメータ付きで使うこともできる: ```php interface MultiFactoryAlt { - function create($name); function get($name): PDO; } ``` -この場合、`MultiFactory::createArticle()` は`MultiFactoryAlt::create('article')` と同じことをします。 しかし、この代替構文にはいくつかの欠点があります。どの`$name` の値がサポートされているかは不明ですし、複数の異なる`$name` の値を使用する場合、インターフェースで戻り値の型を指定することができません。 +この場合、`MultiFactory::getArticle()` は`MultiFactoryAlt::get('article')` と同じことをする。 しかし、この代替構文にはいくつかの欠点がある。どの`$name` 値がサポートされているのかが明確でないことと、複数の異なる`$name` 値を使用する場合、インターフェイスで戻り値の型を指定できないことである。 リストを使った定義 .[#toc-definition-with-a-list] ---------------------------------------- -マルチファクトリーを構成で定義する方法は?マルチファクトリーから返される3つのサービスと、マルチファクトリーそのものを作成してみましょう。 +この方法は、コンフィギュレーションで複数のファクトリーを定義するのに使える:.{data-version:3.2.0} + +```neon +services: + - MultiFactory( + article: Article # defines createArticle() + db: PDO(%dsn%, %user%, %password%) # defines getDb() + ) +``` + +あるいは、ファクトリーの定義で、参照を使用して既存のサービスを参照できます: ```neon services: article: Article - - Model\Foo - PDO(%dsn%, %user%, %password%) - MultiFactory( - article: @article # createArticle() - foo: @Model\Foo # createFoo() - db: @\PDO # getDb() + article: @article # defines createArticle() + db: @\PDO # defines getDb() ) ``` diff --git a/dependency-injection/ja/services.texy b/dependency-injection/ja/services.texy index 83bc008621..1f8dcf2e30 100644 --- a/dependency-injection/ja/services.texy +++ b/dependency-injection/ja/services.texy @@ -249,6 +249,13 @@ Collator::create(%locale%) @Nette\Database\Connection ``` +ファーストクラスの callable 構文を使用する:.{data-version:3.2.0} + +```neon +# creating a callback, equivalent to [@user, logout] +@user::logout(...) +``` + 定数を使用する: ```neon diff --git a/dependency-injection/pl/configuration.texy b/dependency-injection/pl/configuration.texy index d40613b4ca..f3ed899ede 100644 --- a/dependency-injection/pl/configuration.texy +++ b/dependency-injection/pl/configuration.texy @@ -228,6 +228,7 @@ Można również zdefiniować reguły wykluczenia, czyli maski nazw klas lub dzi search: - in: %appDir% exclude: +pliki: ... classes: ... extends: ... implements: ... diff --git a/dependency-injection/pl/factory.texy b/dependency-injection/pl/factory.texy index 6a55c713ca..1658beda00 100644 --- a/dependency-injection/pl/factory.texy +++ b/dependency-injection/pl/factory.texy @@ -170,39 +170,45 @@ Dotychczas nasze fabryki i accessory były w stanie wyprodukować lub zwrócić interface MultiFactory { function createArticle(): Article; - function createFoo(): Model\Foo; function getDb(): PDO; } ``` Więc zamiast przekazywać kilka wygenerowanych fabryk i accessorów, przekazujemy jedną bardziej złożoną fabrykę, która może zrobić więcej. -Alternatywnie, zamiast korzystać z wielu metod, możemy użyć `create()` i `get()` z parametrem: +Alternatywnie można użyć `get()` z parametrem zamiast wielu metod: ```php interface MultiFactoryAlt { - function create($name); function get($name): PDO; } ``` -Następnie `MultiFactory::createArticle()` robi to samo, co `MultiFactoryAlt::create('article')`. Jednak alternatywna notacja ma tę wadę, że nie jest oczywiste, jakie wartości `$name` są obsługiwane, a logicznie nie jest również możliwe wyróżnienie różnych wartości zwrotnych dla różnych `$name` w interfejsie. +W tym przypadku `MultiFactory::getArticle()` robi to samo, co `MultiFactoryAlt::get('article')`. Alternatywna składnia ma jednak kilka wad. Nie jest jasne, które wartości `$name` są obsługiwane, a typ zwracany nie może być określony w interfejsie, gdy używanych jest wiele różnych wartości `$name`. Definicja według listy .[#toc-definition-with-a-list] ----------------------------------------------------- -I jak zdefiniować wiele fabryk w konfiguracji? Tworzymy trzy serwisy, które będą tworzyć/zwracać, a następnie samą fabrykę: +W ten sposób można zdefiniować wiele fabryk w konfiguracji: .{data-version:3.2.0} + +```neon +services: + - MultiFactory( + article: Article # defines createArticle() + db: PDO(%dsn%, %user%, %password%) # defines getDb() + ) +``` + +Lub w definicji fabryki możemy odwołać się do istniejących usług za pomocą referencji: ```neon services: article: Article - - Model\Foo - PDO(%dsn%, %user%, %password%) - MultiFactory( - article: @article # createArticle() - foo: @Model\Foo # createFoo() - db: @\PDO # getDb() + article: @article # defines createArticle() + db: @\PDO # defines getDb() ) ``` diff --git a/dependency-injection/pl/services.texy b/dependency-injection/pl/services.texy index 330962ebf9..1b0fdd1521 100644 --- a/dependency-injection/pl/services.texy +++ b/dependency-injection/pl/services.texy @@ -249,6 +249,13 @@ Odnosić się do usług poprzez ich nazwę lub typ: @Nette\Database\Connection ``` +Używaj składni wywoływalnej pierwszej klasy: .{data-version:3.2.0} + +```neon +# creating a callback, equivalent to [@user, logout] +@user::logout(...) +``` + Użyj stałych: ```neon diff --git a/dependency-injection/pt/configuration.texy b/dependency-injection/pt/configuration.texy index 985378810e..eab09bb9dc 100644 --- a/dependency-injection/pt/configuration.texy +++ b/dependency-injection/pt/configuration.texy @@ -228,6 +228,7 @@ Você também pode definir regras negativas, ou seja, máscaras de nome de class search: - in: %appDir% exclude: +arquivos: ... classes: ... extends: ... implements: ... diff --git a/dependency-injection/pt/factory.texy b/dependency-injection/pt/factory.texy index 4ded195f1e..785b1ea569 100644 --- a/dependency-injection/pt/factory.texy +++ b/dependency-injection/pt/factory.texy @@ -170,39 +170,45 @@ Até agora, as fábricas e os acessores só podiam criar ou devolver um único o interface MultiFactory { function createArticle(): Article; - function createFoo(): Model\Foo; function getDb(): PDO; } ``` Em vez de passar por múltiplas fábricas e acessores gerados, você pode passar apenas por uma complexa multifábrica. -Alternativamente, você pode usar `create()` e `get()` com um parâmetro ao invés de múltiplos métodos: +Como alternativa, você pode usar `get()` com um parâmetro em vez de vários métodos: ```php interface MultiFactoryAlt { - function create($name); function get($name): PDO; } ``` -Neste caso, `MultiFactory::createArticle()` faz a mesma coisa que `MultiFactoryAlt::create('article')`. No entanto, a sintaxe alternativa tem algumas desvantagens. Não está claro quais valores `$name` são suportados e o tipo de retorno não pode ser especificado na interface quando se utiliza vários valores diferentes do `$name`. +Nesse caso, `MultiFactory::getArticle()` faz a mesma coisa que `MultiFactoryAlt::get('article')`. Entretanto, a sintaxe alternativa tem algumas desvantagens. Não está claro quais valores de `$name` são compatíveis e o tipo de retorno não pode ser especificado na interface ao usar vários valores diferentes de `$name`. Definição com uma lista .[#toc-definition-with-a-list] ------------------------------------------------------ -Hos para definir uma multifábrica em sua configuração? Vamos criar três serviços que serão devolvidos pela multifábrica, e a própria multifábrica: +Essa maneira pode ser usada para definir uma fábrica múltipla na configuração: .{data-version:3.2.0} + +```neon +services: + - MultiFactory( + article: Article # defines createArticle() + db: PDO(%dsn%, %user%, %password%) # defines getDb() + ) +``` + +Ou, na definição da fábrica, podemos nos referir aos serviços existentes usando uma referência: ```neon services: article: Article - - Model\Foo - PDO(%dsn%, %user%, %password%) - MultiFactory( - article: @article # createArticle() - foo: @Model\Foo # createFoo() - db: @\PDO # getDb() + article: @article # defines createArticle() + db: @\PDO # defines getDb() ) ``` diff --git a/dependency-injection/pt/services.texy b/dependency-injection/pt/services.texy index 7949e54b43..40971b24e2 100644 --- a/dependency-injection/pt/services.texy +++ b/dependency-injection/pt/services.texy @@ -249,6 +249,13 @@ Referir-se aos serviços pelo nome ou pelo tipo: @Nette\Database\Connection ``` +Use a sintaxe chamável de primeira classe: .{data-version:3.2.0} + +```neon +# creating a callback, equivalent to [@user, logout] +@user::logout(...) +``` + Usar constantes: ```neon diff --git a/dependency-injection/ro/configuration.texy b/dependency-injection/ro/configuration.texy index eedc191b10..92e4c59ecd 100644 --- a/dependency-injection/ro/configuration.texy +++ b/dependency-injection/ro/configuration.texy @@ -228,6 +228,7 @@ De asemenea, se pot defini reguli negative, adică măști de nume de clasă sau search: - in: %appDir% exclude: +fișiere: ... classes: ... extends: ... implements: ... diff --git a/dependency-injection/ro/factory.texy b/dependency-injection/ro/factory.texy index 6fb2fa2fea..25a1475f01 100644 --- a/dependency-injection/ro/factory.texy +++ b/dependency-injection/ro/factory.texy @@ -170,39 +170,45 @@ Până acum, fabricile și accesorii puteau crea sau returna doar un singur obie interface MultiFactory { function createArticle(): Article; - function createFoo(): Model\Foo; function getDb(): PDO; } ``` În loc să transmiteți mai multe fabrici și accesori generați, puteți transmite doar o singură multifactorie complexă. -Alternativ, puteți utiliza `create()` și `get()` cu un parametru în loc de mai multe metode: +Alternativ, puteți utiliza `get()` cu un parametru în loc de mai multe metode: ```php interface MultiFactoryAlt { - function create($name); function get($name): PDO; } ``` -În acest caz, `MultiFactory::createArticle()` face același lucru ca și `MultiFactoryAlt::create('article')`. Cu toate acestea, sintaxa alternativă are câteva dezavantaje. Nu este clar ce valori `$name` sunt acceptate, iar tipul de returnare nu poate fi specificat în interfață atunci când se utilizează mai multe valori `$name` diferite. +În acest caz, `MultiFactory::getArticle()` face același lucru ca și `MultiFactoryAlt::get('article')`. Cu toate acestea, sintaxa alternativă are câteva dezavantaje. Nu este clar ce valori `$name` sunt acceptate, iar tipul de returnare nu poate fi specificat în interfață atunci când se utilizează mai multe valori `$name` diferite. Definiție cu o listă .[#toc-definition-with-a-list] --------------------------------------------------- -Hos pentru a defini un multifactory în configurația dvs. Să creăm trei servicii care vor fi returnate de către multifactory și multifactory însuși: +Acest mod poate fi utilizat pentru a defini o fabrică multiplă în configurație: .{data-version:3.2.0} + +```neon +services: + - MultiFactory( + article: Article # defines createArticle() + db: PDO(%dsn%, %user%, %password%) # defines getDb() + ) +``` + +Sau, în definiția fabricii, putem face referire la serviciile existente folosind o referință: ```neon services: article: Article - - Model\Foo - PDO(%dsn%, %user%, %password%) - MultiFactory( - article: @article # createArticle() - foo: @Model\Foo # createFoo() - db: @\PDO # getDb() + article: @article # defines createArticle() + db: @\PDO # defines getDb() ) ``` diff --git a/dependency-injection/ro/services.texy b/dependency-injection/ro/services.texy index 5332833006..eeb0218375 100644 --- a/dependency-injection/ro/services.texy +++ b/dependency-injection/ro/services.texy @@ -249,6 +249,13 @@ Faceți referire la servicii fie prin numele lor, fie prin tipul lor: @Nette\Database\Connection ``` +Folosiți sintaxa de primă clasă a elementelor apelabile: .{data-version:3.2.0} + +```neon +# creating a callback, equivalent to [@user, logout] +@user::logout(...) +``` + Utilizați constante: ```neon diff --git a/dependency-injection/ru/configuration.texy b/dependency-injection/ru/configuration.texy index 4527e1e6b5..6fc86f0476 100644 --- a/dependency-injection/ru/configuration.texy +++ b/dependency-injection/ru/configuration.texy @@ -228,6 +228,7 @@ search: search: - in: %appDir% exclude: +файлы: ... classes: ... extends: ... implements: ... diff --git a/dependency-injection/ru/factory.texy b/dependency-injection/ru/factory.texy index 315896a1e7..ebe578c30c 100644 --- a/dependency-injection/ru/factory.texy +++ b/dependency-injection/ru/factory.texy @@ -170,39 +170,45 @@ services: interface MultiFactory { function createArticle(): Article; - function createFoo(): Model\Foo; function getDb(): PDO; } ``` Поэтому вместо того, чтобы передавать несколько сгенерированных фабрик и аксессоров, мы собираемся передать ещё одну сложную фабрику, которая может делать больше. -Как вариант, вместо нескольких методов можно использовать параметры `create()` и `get()`: +В качестве альтернативы можно использовать `get()` с параметром вместо нескольких методов: ```php interface MultiFactoryAlt { - function create($name); function get($name): PDO; } ``` -Затем `MultiFactory::createArticle()` делает то же самое, что и `MultiFactoryAlt::create('article')`. Однако альтернативная нотация имеет тот недостаток, что неясно, какие значения `$name` поддерживаются, и логически невозможно различить разные возвращаемые значения для разных `$name` в интерфейсе. +В этом случае `MultiFactory::getArticle()` делает то же самое, что и `MultiFactoryAlt::get('article')`. Однако альтернативный синтаксис имеет несколько недостатков. Неясно, какие значения `$name` поддерживаются, и нельзя указать тип возврата в интерфейсе при использовании нескольких различных значений `$name`. Определение списка .[#toc-definition-with-a-list] ------------------------------------------------- -А как определить множественную фабрику в конфигурации? Мы создадим три сервиса, которые будут создавать/возвращать, а затем и саму фабрику: +Этот способ можно использовать для определения нескольких фабрик в конфигурации: .{data-version:3.2.0} + +```neon +services: + - MultiFactory( + article: Article # defines createArticle() + db: PDO(%dsn%, %user%, %password%) # defines getDb() + ) +``` + +Или в определении фабрики мы можем ссылаться на существующие сервисы с помощью ссылки: ```neon services: article: Article - - Model\Foo - PDO(%dsn%, %user%, %password%) - MultiFactory( - article: @article # createArticle() - foo: @Model\Foo # createFoo() - db: @\PDO # getDb() + article: @article # defines createArticle() + db: @\PDO # defines getDb() ) ``` diff --git a/dependency-injection/ru/services.texy b/dependency-injection/ru/services.texy index 93be5ce8ef..4d3b112eab 100644 --- a/dependency-injection/ru/services.texy +++ b/dependency-injection/ru/services.texy @@ -249,6 +249,13 @@ Collator::create(%locale%) @Nette\Database\Connection ``` +Используйте синтаксис первоклассных вызываемых элементов: .{data-version:3.2.0} + +```neon +# creating a callback, equivalent to [@user, logout] +@user::logout(...) +``` + Использовать константы: ```neon diff --git a/dependency-injection/sl/configuration.texy b/dependency-injection/sl/configuration.texy index 80b2c5e1b5..5ab5cf0e50 100644 --- a/dependency-injection/sl/configuration.texy +++ b/dependency-injection/sl/configuration.texy @@ -228,6 +228,7 @@ Določite lahko tudi negativna pravila, tj. maske imen razredov ali prednikov, i search: - in: %appDir% exclude: +datoteke: ... classes: ... extends: ... implements: ... diff --git a/dependency-injection/sl/factory.texy b/dependency-injection/sl/factory.texy index e13c164e8e..9c7a9dcb45 100644 --- a/dependency-injection/sl/factory.texy +++ b/dependency-injection/sl/factory.texy @@ -170,39 +170,45 @@ Do zdaj so lahko tovarne in dostopniki ustvarili ali vrnili samo en predmet. Ust interface MultiFactory { function createArticle(): Article; - function createFoo(): Model\Foo; function getDb(): PDO; } ``` Namesto več ustvarjenih tovarn in dostopov lahko posredujete samo eno kompleksno večfazno tovarno. -Namesto več metod lahko uporabite tudi `create()` in `get()` s parametrom: +Namesto več metod lahko uporabite tudi `get()` s parametrom: ```php interface MultiFactoryAlt { - function create($name); function get($name): PDO; } ``` -V tem primeru `MultiFactory::createArticle()` naredi isto kot `MultiFactoryAlt::create('article')`. Vendar ima alternativna sintaksa nekaj pomanjkljivosti. Ni jasno, katere vrednosti `$name` so podprte, v vmesniku pa ni mogoče določiti tipa vrnitve, če uporabljate več različnih vrednosti `$name`. +V tem primeru `MultiFactory::getArticle()` naredi isto kot `MultiFactoryAlt::get('article')`. Vendar ima alternativna sintaksa nekaj pomanjkljivosti. Ni jasno, katere vrednosti `$name` so podprte, v vmesniku pa ni mogoče določiti tipa vrnitve pri uporabi več različnih vrednosti `$name`. Opredelitev s seznamom .[#toc-definition-with-a-list] ----------------------------------------------------- -Hos opredeliti večpredstavnostno zbirko v svoji konfiguraciji? Ustvarimo tri storitve, ki jih bo vrnila večfazarnica, in samo večfazarnico: +Na ta način lahko v konfiguraciji določite več tovarn: .{data-version:3.2.0} + +```neon +services: + - MultiFactory( + article: Article # defines createArticle() + db: PDO(%dsn%, %user%, %password%) # defines getDb() + ) +``` + +Lahko pa se v definiciji tovarne sklicujemo na obstoječe storitve s pomočjo reference: ```neon services: article: Article - - Model\Foo - PDO(%dsn%, %user%, %password%) - MultiFactory( - article: @article # createArticle() - foo: @Model\Foo # createFoo() - db: @\PDO # getDb() + article: @article # defines createArticle() + db: @\PDO # defines getDb() ) ``` diff --git a/dependency-injection/sl/services.texy b/dependency-injection/sl/services.texy index d13e9b3505..c62d1ef123 100644 --- a/dependency-injection/sl/services.texy +++ b/dependency-injection/sl/services.texy @@ -249,6 +249,13 @@ Na storitve se lahko sklicujemo po imenu ali vrsti: @Nette\Database\Connection ``` +Uporabite sintakso prvega razreda za klicanje: .{data-version:3.2.0} + +```neon +# creating a callback, equivalent to [@user, logout] +@user::logout(...) +``` + Uporabite konstante: ```neon diff --git a/dependency-injection/tr/configuration.texy b/dependency-injection/tr/configuration.texy index 7d25ced52a..03cc7541d7 100644 --- a/dependency-injection/tr/configuration.texy +++ b/dependency-injection/tr/configuration.texy @@ -228,6 +228,7 @@ Ayrıca negatif kurallar da tanımlayabilirsiniz, yani sınıf adı maskeleri ve search: - in: %appDir% exclude: +dosyalar: ... classes: ... extends: ... implements: ... diff --git a/dependency-injection/tr/factory.texy b/dependency-injection/tr/factory.texy index b9552dc9e2..26bd3c9ab1 100644 --- a/dependency-injection/tr/factory.texy +++ b/dependency-injection/tr/factory.texy @@ -170,39 +170,45 @@ Multifactory/Accessor .[#toc-multifactory-accessor] interface MultiFactory { function createArticle(): Article; - function createFoo(): Model\Foo; function getDb(): PDO; } ``` Birden fazla oluşturulmuş fabrika ve erişimci geçirmek yerine, yalnızca bir karmaşık çoklu fabrika geçirebilirsiniz. -Alternatif olarak, birden fazla yöntem yerine bir parametre ile `create()` ve `get()` adreslerini kullanabilirsiniz: +Alternatif olarak, birden fazla yöntem yerine bir parametre ile `get()` adresini kullanabilirsiniz: ```php interface MultiFactoryAlt { - function create($name); function get($name): PDO; } ``` -Bu durumda, `MultiFactory::createArticle()`, `MultiFactoryAlt::create('article')` ile aynı şeyi yapar. Ancak, alternatif sözdiziminin birkaç dezavantajı vardır. Hangi `$name` değerlerinin desteklendiği açık değildir ve birden fazla farklı `$name` değeri kullanıldığında dönüş türü arayüzde belirtilemez. +Bu durumda, `MultiFactory::getArticle()`, `MultiFactoryAlt::get('article')` ile aynı şeyi yapar. Ancak, alternatif sözdiziminin birkaç dezavantajı vardır. Hangi `$name` değerlerinin desteklendiği açık değildir ve birden fazla farklı `$name` değeri kullanıldığında dönüş türü arayüzde belirtilemez. Liste ile Tanımlama .[#toc-definition-with-a-list] -------------------------------------------------- -Yapılandırmanızda bir multifactory tanımlamak için ne yapmalısınız? Multifactory tarafından döndürülecek üç servis ve multifactory'nin kendisini oluşturalım: +Bu yol, yapılandırmada birden fazla fabrika tanımlamak için kullanılabilir: .{data-version:3.2.0} + +```neon +services: + - MultiFactory( + article: Article # defines createArticle() + db: PDO(%dsn%, %user%, %password%) # defines getDb() + ) +``` + +Veya fabrika tanımında, bir referans kullanarak mevcut hizmetlere atıfta bulunabiliriz: ```neon services: article: Article - - Model\Foo - PDO(%dsn%, %user%, %password%) - MultiFactory( - article: @article # createArticle() - foo: @Model\Foo # createFoo() - db: @\PDO # getDb() + article: @article # defines createArticle() + db: @\PDO # defines getDb() ) ``` diff --git a/dependency-injection/tr/services.texy b/dependency-injection/tr/services.texy index f93c888647..d12eee4856 100644 --- a/dependency-injection/tr/services.texy +++ b/dependency-injection/tr/services.texy @@ -249,6 +249,13 @@ Hizmetlere ya adlarıyla ya da türlerine göre atıfta bulunun: @Nette\Database\Connection ``` +Birinci sınıf çağrılabilir sözdizimi kullanın: .{data-version:3.2.0} + +```neon +# creating a callback, equivalent to [@user, logout] +@user::logout(...) +``` + Sabitleri kullanın: ```neon diff --git a/dependency-injection/uk/configuration.texy b/dependency-injection/uk/configuration.texy index cf5a5c700e..47b57a328e 100644 --- a/dependency-injection/uk/configuration.texy +++ b/dependency-injection/uk/configuration.texy @@ -228,6 +228,7 @@ search: search: - in: %appDir% exclude: +файли: ... classes: ... extends: ... implements: ... diff --git a/dependency-injection/uk/factory.texy b/dependency-injection/uk/factory.texy index e4f50df1e7..b3dd17aa8e 100644 --- a/dependency-injection/uk/factory.texy +++ b/dependency-injection/uk/factory.texy @@ -170,39 +170,45 @@ services: interface MultiFactory { function createArticle(): Article; - function createFoo(): Model\Foo; function getDb(): PDO; } ``` Тому замість того, щоб передавати кілька згенерованих фабрик і аксесорів, ми збираємося передати ще одну складну фабрику, яка може робити більше. -Як варіант, замість кількох методів можна використовувати параметри `create()` і `get()`: +Крім того, ви можете використовувати `get()` з параметром замість декількох методів: ```php interface MultiFactoryAlt { - function create($name); function get($name): PDO; } ``` -Потім `MultiFactory::createArticle()` робить те саме, що і `MultiFactoryAlt::create('article')`. Однак альтернативна нотація має той недолік, що незрозуміло, які значення `$name` підтримуються, і логічно неможливо розрізнити різні значення, що повертаються, для різних `$name` в інтерфейсі. +У цьому випадку `MultiFactory::getArticle()` робить те ж саме, що і `MultiFactoryAlt::get('article')`. Однак альтернативний синтаксис має кілька недоліків. Незрозуміло, які значення `$name` підтримуються, і неможливо вказати тип повернення в інтерфейсі при використанні декількох різних значень `$name`. Визначення списку .[#toc-definition-with-a-list] ------------------------------------------------ -А як визначити множинну фабрику в конфігурації? Ми створимо три сервіси, які будуть створювати/повертати, а потім і саму фабрику: +Цей спосіб можна використовувати для визначення декількох фабрик у конфігурації: .{data-version:3.2.0} + +```neon +services: + - MultiFactory( + article: Article # defines createArticle() + db: PDO(%dsn%, %user%, %password%) # defines getDb() + ) +``` + +Або у визначенні фабрики ми можемо посилатися на існуючі сервіси за допомогою посилання: ```neon services: article: Article - - Model\Foo - PDO(%dsn%, %user%, %password%) - MultiFactory( - article: @article # createArticle() - foo: @Model\Foo # createFoo() - db: @\PDO # getDb() + article: @article # defines createArticle() + db: @\PDO # defines getDb() ) ``` diff --git a/dependency-injection/uk/services.texy b/dependency-injection/uk/services.texy index 9578919b3d..496bed2785 100644 --- a/dependency-injection/uk/services.texy +++ b/dependency-injection/uk/services.texy @@ -249,6 +249,13 @@ Collator::create(%locale%) @Nette\Database\Connection ``` +Використовуйте першокласний синтаксис викликів: .{data-version:3.2.0} + +```neon +# creating a callback, equivalent to [@user, logout] +@user::logout(...) +``` + Використовуйте константи: ```neon From 62cf75424ff017691cb13f0cc3da8040da887eaa Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sat, 2 Mar 2024 15:36:49 +0100 Subject: [PATCH 053/137] added utils/upgrading --- utils/cs/@home.texy | 3 +++ utils/cs/upgrading.texy | 32 ++++++++++++++++++++++++++++++++ utils/en/@home.texy | 3 +++ utils/en/upgrading.texy | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 70 insertions(+) create mode 100644 utils/cs/upgrading.texy create mode 100644 utils/en/upgrading.texy diff --git a/utils/cs/@home.texy b/utils/cs/@home.texy index 4afd52488a..5dbdc24034 100644 --- a/utils/cs/@home.texy +++ b/utils/cs/@home.texy @@ -41,3 +41,6 @@ composer require nette/utils | Nette Utils 2.5 | PHP 5.6 – 8.0 Platí pro poslední patch verze. + + +Pokud aktualizujte balíček na novější verzi, podívejte se na stránku [upgrade|upgrading]. diff --git a/utils/cs/upgrading.texy b/utils/cs/upgrading.texy new file mode 100644 index 0000000000..3a3d1f69e7 --- /dev/null +++ b/utils/cs/upgrading.texy @@ -0,0 +1,32 @@ +Upgrade +******* + + +Přechod z verze 3.x na 4.0 +========================== + +Minimální požadovaná verze PHP je 8.0. + +Třída `Nette\Utils\Reflection` poskytovala metody pro práci s typy `getParameterType()`, `getPropertyType()` a `getReturnType()`. Metody vznikly v době, kdy PHP nemělo union, intersection nebo nejnovější disjunctive normal form typy, se kterými už nefungují a nahradila je [třída Type |utils:type]. Od verze 4.0 jsou tyto metody odstraněné. + +Metoda `Nette\Utils\Reflection::getParameterDefaultValue()` je deprecated, protože nativní `ReflectionParameter::getDefaultValue()` už funguje správně. + +Zrušená je proměnná `Nette\Utils\Html::$xhtml`. + + +Finder +------ + +Finder se přestěhoval do balíčku `nette/utils`, původní odstraňte: + +```shell +composer remove nette/finder +``` + +Na Linuxu se nově chová v režimu case-sensitive. + +V předchozí verzi platilo, že metody `exclude()` a `filter()` fungovaly jinak, když byly zavolány **před** `from()` resp. `in()` a **po** ní. Tohle už neplatí, `exclude()` a `filter()` fungují vždy stejně. Dřívější `filter()` volaný *až po* nahradila nová metoda `descentFilter()`. + +Finder již neimplementuje rozhraní Countable. + +Řetězec začínající lomítkem ve `Finder::findFiles('/f*')` se nově považuje za absolutní cestu, je potřeba ho nahradit např. za `Finder::findFiles('./f*')`. diff --git a/utils/en/@home.texy b/utils/en/@home.texy index a46e587848..9e59fa504c 100644 --- a/utils/en/@home.texy +++ b/utils/en/@home.texy @@ -41,3 +41,6 @@ composer require nette/utils | Nette Utils 2.5 | PHP 5.6 – 8.0 Applies to the latest patch versions. + + +If you are upgrading to a newer version, see the [upgrading] page. diff --git a/utils/en/upgrading.texy b/utils/en/upgrading.texy new file mode 100644 index 0000000000..ada24a4ebf --- /dev/null +++ b/utils/en/upgrading.texy @@ -0,0 +1,32 @@ +Upgrading +********* + + +Migrating from 3.x to 4.0 +========================= + +Minimum required PHP version is 8.0. + +The `Nette\Utils\Reflection` class provided methods `getParameterType()`, `getPropertyType()` and `getReturnType()` for working with the types. These methods were created when PHP didn't have union, intersection or the newest disjunctive normal form types, which they no longer work with and were replaced by the [Type class |utils:type]. As of version 4.0, these methods have been removed. + +The method `Nette\Utils\Reflection::getParameterDefaultValue()` is deprecated because the native `ReflectionParameter::getDefaultValue()` already works correctly. + +The `Nette\Utils\Html::$xhtml` variable is removed. + + +Finder +------ + +Finder has moved to the `nette/utils` package, remove the original package: + +```shell +composer remove nette/finder +``` + +On Linux, it now behaves in case-sensitive mode. + +In the previous version, the `exclude()` and `filter()` methods worked differently when called **before** `from()` and `in()` respectively, and **after** it. This is no longer the case, `exclude()` and `filter()` always work the same. The former `filter()` called *before* has been replaced by the new `descentFilter()` method. + +The Finder no longer implements the Countable interface. + +A string starting with a slash in `Finder::findFiles('/f*')` is now considered an absolute path, it should be replaced with e.g. `Finder::findFiles('./f*')`. From 160b668972174d8993ae1bfcdc8cf1ca6c4a358f Mon Sep 17 00:00:00 2001 From: nextMJ <77353838+nextMJ@users.noreply.github.com> Date: Sun, 18 Feb 2024 00:51:49 +0100 Subject: [PATCH 054/137] typo --- forms/bg/validation.texy | 2 +- forms/cs/validation.texy | 2 +- forms/de/validation.texy | 2 +- forms/el/validation.texy | 2 +- forms/en/validation.texy | 2 +- forms/es/validation.texy | 2 +- forms/fr/validation.texy | 2 +- forms/hu/validation.texy | 2 +- forms/it/validation.texy | 2 +- forms/pl/validation.texy | 2 +- forms/pt/validation.texy | 2 +- forms/ro/validation.texy | 2 +- forms/ru/validation.texy | 2 +- forms/sl/validation.texy | 2 +- forms/tr/validation.texy | 2 +- forms/uk/validation.texy | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/forms/bg/validation.texy b/forms/bg/validation.texy index d3a09980ef..d4085c16d3 100644 --- a/forms/bg/validation.texy +++ b/forms/bg/validation.texy @@ -77,7 +77,7 @@ Nette се предлага с редица предварително дефи Следните правила могат да се използват и за контроли `addUpload()`, `addMultiUpload()`: -| `MaxFileSize` | максимален размер на файла | `int` +| `MaxFileSize` | максимален размер на файла в байтове | `int` | `MimeType` | Тип MIME, приема заместващи символи (`'video/*'`) | `string\|string[]` | `Image` | изтегленият файл е JPEG, PNG, GIF, WebP | - | `Pattern` | името на файла отговаря на регулярен израз | `string` diff --git a/forms/cs/validation.texy b/forms/cs/validation.texy index 33d16f924e..141771580c 100644 --- a/forms/cs/validation.texy +++ b/forms/cs/validation.texy @@ -77,7 +77,7 @@ Upload souborů U prvků `addUpload()`, `addMultiUpload()` lze použít i následující pravidla: -| `MaxFileSize` | maximální velikost souboru | `int` +| `MaxFileSize` | maximální velikost souboru v bajtech | `int` | `MimeType` | MIME type, povoleny zástupné znaky (`'video/*'`) | `string\|string[]` | `Image` | obrázek JPEG, PNG, GIF, WebP, AVIF | - | `Pattern` | jméno souboru vyhovuje regulárnímu výrazu | `string` diff --git a/forms/de/validation.texy b/forms/de/validation.texy index 016aea76a3..e16896ab75 100644 --- a/forms/de/validation.texy +++ b/forms/de/validation.texy @@ -77,7 +77,7 @@ Datei hochladen Für die Steuerelemente `addUpload()`, `addMultiUpload()` können auch die folgenden Regeln verwendet werden: -| `MaxFileSize` | maximale Dateigröße | `int` +| `MaxFileSize` | Maximale Dateigröße in Bytes | `int` | `MimeType` | MIME-Typ, akzeptiert Wildcards (`'video/*'`) | `string\|string[]` | `Image` | hochgeladene Datei ist JPEG, PNG, GIF, WebP | - | `Pattern` | Dateiname entspricht regulärem Ausdruck | `string` diff --git a/forms/el/validation.texy b/forms/el/validation.texy index 1123027e75..b7d2b6edbf 100644 --- a/forms/el/validation.texy +++ b/forms/el/validation.texy @@ -77,7 +77,7 @@ $form->addPassword('password', 'Password:') Για τους ελέγχους `addUpload()`, `addMultiUpload()` μπορούν επίσης να χρησιμοποιηθούν οι ακόλουθοι κανόνες: -| `MaxFileSize` | μέγιστο μέγεθος αρχείου | `int` +| `MaxFileSize` | μέγιστο μέγεθος αρχείου σε bytes | `int` | `MimeType` | τύπος MIME, δέχεται μπαλαντέρ (`'video/*'`) | `string\|string[]` | `Image` | το ανεβασμένο αρχείο είναι JPEG, PNG, GIF, WebP | - | `Pattern` | το όνομα του αρχείου ταιριάζει με κανονική έκφραση | `string` diff --git a/forms/en/validation.texy b/forms/en/validation.texy index 308f5fb1a9..512de98cb5 100644 --- a/forms/en/validation.texy +++ b/forms/en/validation.texy @@ -77,7 +77,7 @@ File Upload For controls `addUpload()`, `addMultiUpload()` the following rules can also be used: -| `MaxFileSize` | maximal file size | `int` +| `MaxFileSize` | maximal file size in bytes | `int` | `MimeType` | MIME type, accepts wildcards (`'video/*'`) | `string\|string[]` | `Image` | uploaded file is JPEG, PNG, GIF, WebP, AVIF | - | `Pattern` | file name matches regular expression | `string` diff --git a/forms/es/validation.texy b/forms/es/validation.texy index 9cca587c43..12662509fb 100644 --- a/forms/es/validation.texy +++ b/forms/es/validation.texy @@ -77,7 +77,7 @@ Carga de archivos Para los controles `addUpload()`, `addMultiUpload()` también se pueden utilizar las siguientes reglas: -| `MaxFileSize` | tamaño máximo del archivo | `int` +| `MaxFileSize` | tamaño máximo del archivo en bytes | `int` | `MimeType` | tipo de MIME, acepta comodines (`'video/*'`) | `string\|string[]` | `Image` | el archivo cargado es JPEG, PNG, GIF, WebP | - | `Pattern` | nombre de archivo coincide con expresión regular | `string` diff --git a/forms/fr/validation.texy b/forms/fr/validation.texy index 9f0931173c..178ff39e23 100644 --- a/forms/fr/validation.texy +++ b/forms/fr/validation.texy @@ -77,7 +77,7 @@ Téléchargement de fichiers Pour les contrôles `addUpload()`, `addMultiUpload()`, les règles suivantes peuvent également être utilisées : -| `MaxFileSize` | taille maximale du fichier | `int` +| `MaxFileSize` | taille maximale du fichier en octets | `int` `MimeType` | type MIME, accepte les caractères génériques (`'video/*'`) | type MIME, accepte les caractères génériques ( ) | type MIME, accepte les caractères génériques ( ) `string\|string[]` | `Image` | le fichier téléchargé est un JPEG, PNG, GIF, WebP | - | `Pattern` | le nom du fichier correspond à une expression régulière | `string` diff --git a/forms/hu/validation.texy b/forms/hu/validation.texy index 915425c223..6fa2d6c956 100644 --- a/forms/hu/validation.texy +++ b/forms/hu/validation.texy @@ -77,7 +77,7 @@ Fájl feltöltés A `addUpload()`, `addMultiUpload()` vezérlőkre a következő szabályok is alkalmazhatók: -| `MaxFileSize` | maximális fájlméret | `int` +| `MaxFileSize` | maximális fájlméret bájtban | `int` | `MimeType` | MIME-típus, elfogadja a helyettesítő karaktereket (`'video/*'`) | `string\|string[]` | `Image` | a feltöltött fájl JPEG, PNG, GIF, WebP | - | `Pattern` | a fájl neve megfelel a reguláris kifejezésnek | `string` diff --git a/forms/it/validation.texy b/forms/it/validation.texy index 0fedfe4e62..f76a59636c 100644 --- a/forms/it/validation.texy +++ b/forms/it/validation.texy @@ -77,7 +77,7 @@ Caricamento file Per i controlli `addUpload()`, `addMultiUpload()` si possono utilizzare anche le seguenti regole: -| `MaxFileSize` | dimensione massima del file | `int` +| `MaxFileSize` | dimensione massima del file in byte | `int` | `MimeType` | Tipo MIME, accetta caratteri jolly (`'video/*'`) | `string\|string[]` | `Image` | il file caricato è JPEG, PNG, GIF, WebP | - - | il nome del file corrisponde a una regola regolare. | `Pattern` | il nome del file corrisponde a un'espressione regolare | `string` diff --git a/forms/pl/validation.texy b/forms/pl/validation.texy index f6a652e651..6e274847e2 100644 --- a/forms/pl/validation.texy +++ b/forms/pl/validation.texy @@ -77,7 +77,7 @@ Przesyłanie plików Poniższe zasady mogą być również stosowane dla elementów `addUpload()`, `addMultiUpload()`: -| `MaxFileSize` | maksymalny rozmiar pliku | `int` +| `MaxFileSize` | maksymalny rozmiar pliku w bajtach | `int` | `MimeType` | Typ MIME, dozwolone symbole wieloznaczne (`'video/*'`) | `string\|string[]` | `Image` | obraz JPEG, PNG, GIF, WebP | -. | `Pattern` | nazwa pliku pasuje do wyrażenia regularnego | `string` diff --git a/forms/pt/validation.texy b/forms/pt/validation.texy index b2331fc1ba..4388fa84f5 100644 --- a/forms/pt/validation.texy +++ b/forms/pt/validation.texy @@ -77,7 +77,7 @@ Upload de arquivos Para controles `addUpload()`, `addMultiUpload()` as seguintes regras também podem ser usadas: -| `MaxFileSize` | tamanho máximo do arquivo | `int` +| `MaxFileSize` | tamanho máximo do arquivo em bytes | `int` | `MimeType` | tipo MIME, aceita wildcards (`'video/*'`) | `string\|string[]` | `Image` | o arquivo carregado é JPEG, PNG, GIF, WebP | - | `Pattern` | o nome do arquivo corresponde à expressão regular | `string` diff --git a/forms/ro/validation.texy b/forms/ro/validation.texy index 3c4b009059..820828604c 100644 --- a/forms/ro/validation.texy +++ b/forms/ro/validation.texy @@ -77,7 +77,7 @@ Pentru elementele `addMultiUpload()`, `addCheckboxList()`, `addMultiSelect()` pu Pentru controalele `addUpload()`, `addMultiUpload()` se pot utiliza, de asemenea, următoarele reguli: -| `MaxFileSize` | dimensiunea maximă a fișierului | `int` +| `MaxFileSize` | dimensiunea maximă a fișierului în bytes | `int` | `MimeType` | tip MIME, acceptă wildcards (`'video/*'`) | `string\|string[]` | `Image` | fișierul încărcat este JPEG, PNG, GIF, WebP | - | `Pattern` | numele fișierului se potrivește cu o expresie regulată | `string` diff --git a/forms/ru/validation.texy b/forms/ru/validation.texy index 895a1dc5ff..75900c35a5 100644 --- a/forms/ru/validation.texy +++ b/forms/ru/validation.texy @@ -77,7 +77,7 @@ Nette поставляется с рядом предопределенных п Для элементов управления `addUpload()`, `addMultiUpload()` также могут быть использованы следующие правила: -| `MaxFileSize` | максимальный размер файла | `int` +| `MaxFileSize` | Максимальный размер файла в байтах | `int` | `MimeType` | Тип MIME, принимает подстановочные знаки (`'video/*'`) | `string\|string[]` | `Image` | загруженный файл является JPEG, PNG, GIF, WebP | - | `Pattern` | имя файла соответствует регулярному выражению | `string` diff --git a/forms/sl/validation.texy b/forms/sl/validation.texy index ddcf592b27..e1462b7710 100644 --- a/forms/sl/validation.texy +++ b/forms/sl/validation.texy @@ -77,7 +77,7 @@ Prenos datotek Za kontrole `addUpload()`, `addMultiUpload()` se lahko uporabljajo tudi naslednja pravila: -| `MaxFileSize` | največja velikost datoteke | `int` +| `MaxFileSize` | največja velikost datoteke v bajtih | `int` | `MimeType` | vrsta MIME, sprejema nadomestne znake (`'video/*'`) | `string\|string[]` | `Image` | naložena datoteka je JPEG, PNG, GIF, WebP | - | `Pattern` | ime datoteke ustreza regularnemu izrazu | `string` diff --git a/forms/tr/validation.texy b/forms/tr/validation.texy index 484738d6be..d7865aaba5 100644 --- a/forms/tr/validation.texy +++ b/forms/tr/validation.texy @@ -77,7 +77,7 @@ Dosya Yükleme `addUpload()`, `addMultiUpload()` kontrolleri için aşağıdaki kurallar da kullanılabilir: -| `MaxFileSize` | maksimum dosya boyutu | `int` +| `MaxFileSize` | bayt cinsinden maksimum dosya boyutu | `int` | `MimeType` | MIME türü, joker karakterleri kabul eder (`'video/*'`) | `string\|string[]` | `Image` | yüklenen dosya JPEG, PNG, GIF, WebP | - | `Pattern` | dosya adı düzenli ifadeyle eşleşiyor | `string` diff --git a/forms/uk/validation.texy b/forms/uk/validation.texy index ff28466195..9e04e2eb15 100644 --- a/forms/uk/validation.texy +++ b/forms/uk/validation.texy @@ -77,7 +77,7 @@ Nette постачається з низкою попередньо визнач Для елементів керування `addUpload()`, `addMultiUpload()` також можуть бути використані такі правила: -| `MaxFileSize` | максимальний розмір файлу | `int` +| `MaxFileSize` | максимальний розмір файлу в байтах | `int` | `MimeType` | Тип MIME, приймає підстановні знаки (`'video/*'`) | `string\|string[]` | `Image` | завантажений файл є JPEG, PNG, GIF, WebP | - | `Pattern` | ім'я файлу відповідає регулярному виразу | `string` From f932041517b6d4d6c860a463d94cf52a19c9e592 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sun, 18 Feb 2024 01:58:10 +0100 Subject: [PATCH 055/137] updated web-project --- application/bg/bootstrap.texy | 2 +- application/bg/how-it-works.texy | 2 +- application/cs/bootstrap.texy | 2 +- application/cs/how-it-works.texy | 2 +- application/de/bootstrap.texy | 2 +- application/de/how-it-works.texy | 2 +- application/el/bootstrap.texy | 2 +- application/el/how-it-works.texy | 2 +- application/en/bootstrap.texy | 2 +- application/en/how-it-works.texy | 2 +- application/es/bootstrap.texy | 2 +- application/es/how-it-works.texy | 2 +- application/fr/bootstrap.texy | 2 +- application/fr/how-it-works.texy | 2 +- application/hu/bootstrap.texy | 2 +- application/hu/how-it-works.texy | 2 +- application/it/bootstrap.texy | 2 +- application/it/how-it-works.texy | 2 +- application/pl/bootstrap.texy | 2 +- application/pl/how-it-works.texy | 2 +- application/pt/bootstrap.texy | 2 +- application/pt/how-it-works.texy | 2 +- application/ro/bootstrap.texy | 2 +- application/ro/how-it-works.texy | 2 +- application/ru/bootstrap.texy | 2 +- application/ru/how-it-works.texy | 2 +- application/sl/bootstrap.texy | 2 +- application/sl/how-it-works.texy | 2 +- application/tr/bootstrap.texy | 2 +- application/tr/how-it-works.texy | 2 +- application/uk/bootstrap.texy | 2 +- application/uk/how-it-works.texy | 2 +- quickstart/bg/home-page.texy | 6 ++---- quickstart/cs/home-page.texy | 6 ++---- quickstart/de/home-page.texy | 6 ++---- quickstart/el/home-page.texy | 6 ++---- quickstart/en/home-page.texy | 6 ++---- quickstart/es/home-page.texy | 6 ++---- quickstart/fr/home-page.texy | 6 ++---- quickstart/hu/home-page.texy | 6 ++---- quickstart/it/home-page.texy | 6 ++---- quickstart/pl/home-page.texy | 6 ++---- quickstart/pt/home-page.texy | 6 ++---- quickstart/ro/home-page.texy | 6 ++---- quickstart/ru/home-page.texy | 6 ++---- quickstart/sl/home-page.texy | 6 ++---- quickstart/tr/home-page.texy | 6 ++---- quickstart/uk/home-page.texy | 6 ++---- 48 files changed, 64 insertions(+), 96 deletions(-) diff --git a/application/bg/bootstrap.texy b/application/bg/bootstrap.texy index 8d0b3dc5c4..a7989b2d15 100644 --- a/application/bg/bootstrap.texy +++ b/application/bg/bootstrap.texy @@ -150,7 +150,7 @@ $configurator->addConfig($appDir . '/config/common.neon'); ```php $configurator->addConfig($appDir . '/config/common.neon'); -$configurator->addConfig($appDir . '/config/local.neon'); +$configurator->addConfig($appDir . '/config/services.neon'); if (PHP_SAPI === 'cli') { $configurator->addConfig($appDir . '/config/cli.php'); } diff --git a/application/bg/how-it-works.texy b/application/bg/how-it-works.texy index 4325c76dd5..3cdb0786e2 100644 --- a/application/bg/how-it-works.texy +++ b/application/bg/how-it-works.texy @@ -33,7 +33,7 @@ ├── bin/ ← скрипты командной строки ├── config/ ← файлы конфигурации │ ├── common.neon -│ └── local.neon +│ └── services.neon ├── log/ ← журналы ошибок ├── temp/ ← временные файлы, кэш, … ├── vendor/ ← библиотеки, установленные через Composer diff --git a/application/cs/bootstrap.texy b/application/cs/bootstrap.texy index 55fbbfc0f5..a0b9db0792 100644 --- a/application/cs/bootstrap.texy +++ b/application/cs/bootstrap.texy @@ -150,7 +150,7 @@ Pokud chceme přidat více konfiguračních souborů, můžeme funkci `addConfig ```php $configurator->addConfig($appDir . '/config/common.neon'); -$configurator->addConfig($appDir . '/config/local.neon'); +$configurator->addConfig($appDir . '/config/services.neon'); if (PHP_SAPI === 'cli') { $configurator->addConfig($appDir . '/config/cli.php'); } diff --git a/application/cs/how-it-works.texy b/application/cs/how-it-works.texy index 978e29c388..92ff5e9d9b 100644 --- a/application/cs/how-it-works.texy +++ b/application/cs/how-it-works.texy @@ -33,7 +33,7 @@ Adresářová struktura vypadá nějak takto: ├── bin/ ← skripty spouštěné z příkazové řádky ├── config/ ← konfigurační soubory │ ├── common.neon -│ └── local.neon +│ └── services.neon ├── log/ ← logované chyby ├── temp/ ← dočasné soubory, cache, … ├── vendor/ ← knihovny instalované Composerem diff --git a/application/de/bootstrap.texy b/application/de/bootstrap.texy index 590e4e76ef..a5ddc1e604 100644 --- a/application/de/bootstrap.texy +++ b/application/de/bootstrap.texy @@ -150,7 +150,7 @@ Die Methode `addConfig()` kann mehrfach aufgerufen werden, um mehrere Dateien hi ```php $configurator->addConfig($appDir . '/config/common.neon'); -$configurator->addConfig($appDir . '/config/local.neon'); +$configurator->addConfig($appDir . '/config/services.neon'); if (PHP_SAPI === 'cli') { $configurator->addConfig($appDir . '/config/cli.php'); } diff --git a/application/de/how-it-works.texy b/application/de/how-it-works.texy index 3ac55697e4..010ba04907 100644 --- a/application/de/how-it-works.texy +++ b/application/de/how-it-works.texy @@ -33,7 +33,7 @@ Die Verzeichnisstruktur sieht in etwa so aus: ├── bin/ ← Skripte für die Kommandozeile ├── config/ ← Konfigurationsdateien │ ├── common.neon -│ └── local.neon +│ └── services.neon ├── log/ ← Fehlerprotokolle ├── temp/ ← temporäre Dateien, Cache, … ├── vendor/ ← vom Composer installierte Bibliotheken diff --git a/application/el/bootstrap.texy b/application/el/bootstrap.texy index 71f6028048..7ee2f81c13 100644 --- a/application/el/bootstrap.texy +++ b/application/el/bootstrap.texy @@ -150,7 +150,7 @@ $configurator->addConfig($appDir . '/config/common.neon'); ```php $configurator->addConfig($appDir . '/config/common.neon'); -$configurator->addConfig($appDir . '/config/local.neon'); +$configurator->addConfig($appDir . '/config/services.neon'); if (PHP_SAPI === 'cli') { $configurator->addConfig($appDir . '/config/cli.php'); } diff --git a/application/el/how-it-works.texy b/application/el/how-it-works.texy index 2cfe6c52b9..f7a4be0a0b 100644 --- a/application/el/how-it-works.texy +++ b/application/el/how-it-works.texy @@ -33,7 +33,7 @@ ├── bin/ ← scripts for the command line ├── config/ ← configuration files │ ├── common.neon -│ └── local.neon +│ └── services.neon ├── log/ ← error logs ├── temp/ ← temporary files, cache, … ├── vendor/ ← libraries installed by Composer diff --git a/application/en/bootstrap.texy b/application/en/bootstrap.texy index c763e715a3..14a412cd6f 100644 --- a/application/en/bootstrap.texy +++ b/application/en/bootstrap.texy @@ -150,7 +150,7 @@ The method `addConfig()` can be called multiple times to add multiple files. ```php $configurator->addConfig($appDir . '/config/common.neon'); -$configurator->addConfig($appDir . '/config/local.neon'); +$configurator->addConfig($appDir . '/config/services.neon'); if (PHP_SAPI === 'cli') { $configurator->addConfig($appDir . '/config/cli.php'); } diff --git a/application/en/how-it-works.texy b/application/en/how-it-works.texy index 08d7c3eb8b..612d192393 100644 --- a/application/en/how-it-works.texy +++ b/application/en/how-it-works.texy @@ -33,7 +33,7 @@ The directory structure looks something like this: ├── bin/ ← scripts for the command line ├── config/ ← configuration files │ ├── common.neon -│ └── local.neon +│ └── services.neon ├── log/ ← error logs ├── temp/ ← temporary files, cache, … ├── vendor/ ← libraries installed by Composer diff --git a/application/es/bootstrap.texy b/application/es/bootstrap.texy index 3b67d5c4b9..bed14d1d22 100644 --- a/application/es/bootstrap.texy +++ b/application/es/bootstrap.texy @@ -150,7 +150,7 @@ El método `addConfig()` se puede llamar varias veces para añadir varios archiv ```php $configurator->addConfig($appDir . '/config/common.neon'); -$configurator->addConfig($appDir . '/config/local.neon'); +$configurator->addConfig($appDir . '/config/services.neon'); if (PHP_SAPI === 'cli') { $configurator->addConfig($appDir . '/config/cli.php'); } diff --git a/application/es/how-it-works.texy b/application/es/how-it-works.texy index c23895a22f..1706cb62a5 100644 --- a/application/es/how-it-works.texy +++ b/application/es/how-it-works.texy @@ -33,7 +33,7 @@ La estructura de directorios se parece a esto ├── bin/ ← scripts para la línea de comandos ├── config/ ← archivos de configuración │ ├── common.neon -│ └── local.neon +│ └── services.neon ├── log/ ← registros de errores ├── temp/ ← archivos temporales, caché, ... ├── vendor/ ← libraries installed by Composer diff --git a/application/fr/bootstrap.texy b/application/fr/bootstrap.texy index 8bea659e34..3b80608880 100644 --- a/application/fr/bootstrap.texy +++ b/application/fr/bootstrap.texy @@ -150,7 +150,7 @@ La méthode `addConfig()` peut être appelée plusieurs fois pour ajouter plusie ```php $configurator->addConfig($appDir . '/config/common.neon'); -$configurator->addConfig($appDir . '/config/local.neon'); +$configurator->addConfig($appDir . '/config/services.neon'); if (PHP_SAPI === 'cli') { $configurator->addConfig($appDir . '/config/cli.php'); } diff --git a/application/fr/how-it-works.texy b/application/fr/how-it-works.texy index 09d020332a..9c4358110a 100644 --- a/application/fr/how-it-works.texy +++ b/application/fr/how-it-works.texy @@ -33,7 +33,7 @@ La structure des répertoires ressemble à ceci : ├── bin/ ← scripts pour la ligne de commande ├── config/ ← configuration files │ ├── common.neon -│ └── local.neon +│ └── services.neon ├── log/ ← journaux d'erreurs ├── temp/ ← fichiers temporaires, cache, … ├── vendor/ ← bibliothèques installées par Composer diff --git a/application/hu/bootstrap.texy b/application/hu/bootstrap.texy index 5d0a614439..1ef07fd756 100644 --- a/application/hu/bootstrap.texy +++ b/application/hu/bootstrap.texy @@ -150,7 +150,7 @@ A `addConfig()` metódus többször is meghívható több fájl hozzáadásához ```php $configurator->addConfig($appDir . '/config/common.neon'); -$configurator->addConfig($appDir . '/config/local.neon'); +$configurator->addConfig($appDir . '/config/services.neon'); if (PHP_SAPI === 'cli') { $configurator->addConfig($appDir . '/config/cli.php'); } diff --git a/application/hu/how-it-works.texy b/application/hu/how-it-works.texy index f7503c9ef1..5101363032 100644 --- a/application/hu/how-it-works.texy +++ b/application/hu/how-it-works.texy @@ -33,7 +33,7 @@ A könyvtárszerkezet valahogy így néz ki: ├── bin/ ← scripts for the command line ├── config/ ← configuration files │ ├── common.neon -│ └── local.neon +│ └── services.neon ├── log/ ← error logs ├── temp/ ← temporary files, cache, … ├── vendor/ ← libraries installed by Composer diff --git a/application/it/bootstrap.texy b/application/it/bootstrap.texy index 4efbe28af1..b2c87a4373 100644 --- a/application/it/bootstrap.texy +++ b/application/it/bootstrap.texy @@ -150,7 +150,7 @@ Il metodo `addConfig()` può essere richiamato più volte per aggiungere più fi ```php $configurator->addConfig($appDir . '/config/common.neon'); -$configurator->addConfig($appDir . '/config/local.neon'); +$configurator->addConfig($appDir . '/config/services.neon'); if (PHP_SAPI === 'cli') { $configurator->addConfig($appDir . '/config/cli.php'); } diff --git a/application/it/how-it-works.texy b/application/it/how-it-works.texy index bff0380317..91e4f4e5ef 100644 --- a/application/it/how-it-works.texy +++ b/application/it/how-it-works.texy @@ -33,7 +33,7 @@ La struttura delle directory è simile a questa: ├── bin/ ← scripts for the command line ├── config/ ← configuration files │ ├── common.neon -│ └── local.neon +│ └── services.neon ├── log/ ← error logs ├── temp/ ← temporary files, cache, … ├── vendor/ ← libraries installed by Composer diff --git a/application/pl/bootstrap.texy b/application/pl/bootstrap.texy index 3fb6475d75..4b23e1f658 100644 --- a/application/pl/bootstrap.texy +++ b/application/pl/bootstrap.texy @@ -150,7 +150,7 @@ Jeśli chcemy dodać więcej plików konfiguracyjnych, możemy wywołać funkcj ```php $configurator->addConfig($appDir . '/config/common.neon'); -$configurator->addConfig($appDir . '/config/local.neon'); +$configurator->addConfig($appDir . '/config/services.neon'); if (PHP_SAPI === 'cli') { $configurator->addConfig($appDir . '/config/cli.php'); } diff --git a/application/pl/how-it-works.texy b/application/pl/how-it-works.texy index fa65218c64..9cbbb61f69 100644 --- a/application/pl/how-it-works.texy +++ b/application/pl/how-it-works.texy @@ -33,7 +33,7 @@ Struktura katalogów wygląda mniej więcej tak: ├── bin/ ← skripty spouštěné z příkazové řádky ├── config/ ← konfigurační soubory │ ├── common.neon -│ └── local.neon +│ └── services.neon ├── log/ ← logované chyby ├── temp/ ← dočasné soubory, cache, … ├── vendor/ ← knihovny instalované Composerem diff --git a/application/pt/bootstrap.texy b/application/pt/bootstrap.texy index 1ebef20eff..85dca58e88 100644 --- a/application/pt/bootstrap.texy +++ b/application/pt/bootstrap.texy @@ -150,7 +150,7 @@ O método `addConfig()` pode ser chamado várias vezes para adicionar vários ar ```php $configurator->addConfig($appDir . '/config/common.neon'); -$configurator->addConfig($appDir . '/config/local.neon'); +$configurator->addConfig($appDir . '/config/services.neon'); if (PHP_SAPI === 'cli') { $configurator->addConfig($appDir . '/config/cli.php'); } diff --git a/application/pt/how-it-works.texy b/application/pt/how-it-works.texy index 68f955b2b5..a73637f71e 100644 --- a/application/pt/how-it-works.texy +++ b/application/pt/how-it-works.texy @@ -33,7 +33,7 @@ A estrutura do diretório é algo parecido com isto: ├── bin/ ← scripts for the command line ├── config/ ← configuration files │ ├── common.neon -│ └── local.neon +│ └── services.neon ├── log/ ← error logs ├── temp/ ← temporary files, cache, … ├── vendor/ ← libraries installed by Composer diff --git a/application/ro/bootstrap.texy b/application/ro/bootstrap.texy index def23eed0e..a13e217c3c 100644 --- a/application/ro/bootstrap.texy +++ b/application/ro/bootstrap.texy @@ -150,7 +150,7 @@ Metoda `addConfig()` poate fi apelată de mai multe ori pentru a adăuga mai mul ```php $configurator->addConfig($appDir . '/config/common.neon'); -$configurator->addConfig($appDir . '/config/local.neon'); +$configurator->addConfig($appDir . '/config/services.neon'); if (PHP_SAPI === 'cli') { $configurator->addConfig($appDir . '/config/cli.php'); } diff --git a/application/ro/how-it-works.texy b/application/ro/how-it-works.texy index 7dacddf162..75291693ee 100644 --- a/application/ro/how-it-works.texy +++ b/application/ro/how-it-works.texy @@ -33,7 +33,7 @@ Structura directoarelor arată cam așa: ├── bin/ ← scripts for the command line ├── config/ ← configuration files │ ├── common.neon -│ └── local.neon +│ └── services.neon ├── log/ ← error logs ├── temp/ ← temporary files, cache, … ├── vendor/ ← libraries installed by Composer diff --git a/application/ru/bootstrap.texy b/application/ru/bootstrap.texy index 071d2c9fc5..6e041613e9 100644 --- a/application/ru/bootstrap.texy +++ b/application/ru/bootstrap.texy @@ -150,7 +150,7 @@ $configurator->addConfig($appDir . '/config/common.neon'); ```php $configurator->addConfig($appDir . '/config/common.neon'); -$configurator->addConfig($appDir . '/config/local.neon'); +$configurator->addConfig($appDir . '/config/services.neon'); if (PHP_SAPI === 'cli') { $configurator->addConfig($appDir . '/config/cli.php'); } diff --git a/application/ru/how-it-works.texy b/application/ru/how-it-works.texy index 02bdce2b15..39b20c686c 100644 --- a/application/ru/how-it-works.texy +++ b/application/ru/how-it-works.texy @@ -33,7 +33,7 @@ ├── bin/ ← скрипты командной строки ├── config/ ← файлы конфигурации │ ├── common.neon -│ └── local.neon +│ └── services.neon ├── log/ ← журналы ошибок ├── temp/ ← временные файлы, кэш, … ├── vendor/ ← библиотеки, установленные через Composer diff --git a/application/sl/bootstrap.texy b/application/sl/bootstrap.texy index bc60e3cfe8..840ebe2ab6 100644 --- a/application/sl/bootstrap.texy +++ b/application/sl/bootstrap.texy @@ -150,7 +150,7 @@ Metodo `addConfig()` lahko za dodajanje več datotek pokličete večkrat. ```php $configurator->addConfig($appDir . '/config/common.neon'); -$configurator->addConfig($appDir . '/config/local.neon'); +$configurator->addConfig($appDir . '/config/services.neon'); if (PHP_SAPI === 'cli') { $configurator->addConfig($appDir . '/config/cli.php'); } diff --git a/application/sl/how-it-works.texy b/application/sl/how-it-works.texy index 9139f15de5..0149fdc95f 100644 --- a/application/sl/how-it-works.texy +++ b/application/sl/how-it-works.texy @@ -33,7 +33,7 @@ Struktura imenikov je videti nekako takole: ├── bin/ ← scripts for the command line ├── config/ ← configuration files │ ├── common.neon -│ └── local.neon +│ └── services.neon ├── log/ ← error logs ├── temp/ ← temporary files, cache, … ├── vendor/ ← libraries installed by Composer diff --git a/application/tr/bootstrap.texy b/application/tr/bootstrap.texy index 403f4ee3f7..98cf02a208 100644 --- a/application/tr/bootstrap.texy +++ b/application/tr/bootstrap.texy @@ -150,7 +150,7 @@ Birden fazla dosya eklemek için `addConfig()` yöntemi birden fazla kez çağr ```php $configurator->addConfig($appDir . '/config/common.neon'); -$configurator->addConfig($appDir . '/config/local.neon'); +$configurator->addConfig($appDir . '/config/services.neon'); if (PHP_SAPI === 'cli') { $configurator->addConfig($appDir . '/config/cli.php'); } diff --git a/application/tr/how-it-works.texy b/application/tr/how-it-works.texy index c083b0f45c..78f72c450c 100644 --- a/application/tr/how-it-works.texy +++ b/application/tr/how-it-works.texy @@ -33,7 +33,7 @@ Dizin yapısı şuna benzer: ├── bin/ ← scripts for the command line ├── config/ ← configuration files │ ├── common.neon -│ └── local.neon +│ └── services.neon ├── log/ ← error logs ├── temp/ ← temporary files, cache, … ├── vendor/ ← libraries installed by Composer diff --git a/application/uk/bootstrap.texy b/application/uk/bootstrap.texy index f71b35252b..0ebf2ae13d 100644 --- a/application/uk/bootstrap.texy +++ b/application/uk/bootstrap.texy @@ -150,7 +150,7 @@ $configurator->addConfig($appDir . '/config/common.neon'); ```php $configurator->addConfig($appDir . '/config/common.neon'); -$configurator->addConfig($appDir . '/config/local.neon'); +$configurator->addConfig($appDir . '/config/services.neon'); if (PHP_SAPI === 'cli') { $configurator->addConfig($appDir . '/config/cli.php'); } diff --git a/application/uk/how-it-works.texy b/application/uk/how-it-works.texy index 03cb3b413a..be1f7ce5aa 100644 --- a/application/uk/how-it-works.texy +++ b/application/uk/how-it-works.texy @@ -33,7 +33,7 @@ ├── bin/ ← скрипты командной строки ├── config/ ← файлы конфигурации │ ├── common.neon -│ └── local.neon +│ └── services.neon ├── log/ ← журналы ошибок ├── temp/ ← временные файлы, кэш, … ├── vendor/ ← библиотеки, установленные через Composer diff --git a/quickstart/bg/home-page.texy b/quickstart/bg/home-page.texy index fcb701ca5b..ffd094653a 100644 --- a/quickstart/bg/home-page.texy +++ b/quickstart/bg/home-page.texy @@ -66,9 +66,9 @@ INSERT INTO `posts` (`id`, `title`, `content`, `created_at`) VALUES Сега, след като базата данни е създадена и в нея има няколко публикации, е време да ги покажем на нашата нова блестяща страница. -Първо, трябва да укажем на приложението коя база данни да използва. Конфигурацията на връзката с базата данни се съхранява във файла `config/local.neon`. Създайте връзка DSN((Име на източника на данни)) и вашите пълномощия. Това трябва да изглежда по следния начин: +Първо, трябва да укажем на приложението коя база данни да използва. Конфигурацията на връзката с базата данни се съхранява във файла `config/common.neon`. Създайте връзка DSN((Име на източника на данни)) и вашите пълномощия. Това трябва да изглежда по следния начин: -```neon .{file:config/local.neon} +```neon .{file:config/common.neon} database: dsn: 'mysql:host=127.0.0.1;dbname=quickstart' user: *укажите здесь имя пользователя* @@ -78,8 +78,6 @@ database: .[note] Не забравяйте да правите отстъпи, когато редактирате този файл. [Форматът NEON |neon:format] приема както интервали, така и табулации, но не и двете заедно! В конфигурационния файл в уеб проекта по подразбиране се използва таблично представяне. -Цялата конфигурация се съхранява в `config/` във файловете `common.neon` и `local.neon`. Файлът `common.neon` съдържа глобалната конфигурация на приложението, докато `local.neon` съдържа само специфични за средата параметри (например разликата между сървъра за разработка и производствения сървър). - Осъществяване на връзката с базата данни .[#toc-injecting-the-database-connection] ================================================================================== diff --git a/quickstart/cs/home-page.texy b/quickstart/cs/home-page.texy index b1c620ae4e..ed58e422a6 100644 --- a/quickstart/cs/home-page.texy +++ b/quickstart/cs/home-page.texy @@ -66,9 +66,9 @@ Připojení k databázi Nyní, když je již databáze vytvořena a máme v ní uloženo pár článků, je ten správný čas zobrazit je na naší krásné nové stránce. -Prvně musíme aplikaci říct, jakou databázi má použít. Připojení k databázi nastavíme v souboru `config/local.neon` pomocí DSN((Data Source Name)) a přihlašovacích údajů. Mělo by to vypadat nějak takto: +Prvně musíme aplikaci říct, jakou databázi má použít. Připojení k databázi nastavíme v souboru `config/common.neon` pomocí DSN((Data Source Name)) a přihlašovacích údajů. Mělo by to vypadat nějak takto: -```neon .{file:config/local.neon} +```neon .{file:config/common.neon} database: dsn: 'mysql:host=127.0.0.1;dbname=quickstart' user: *zde vložte jméno uživatele* @@ -78,8 +78,6 @@ database: .[note] Při editování tohoto souboru dávejte pozor na odsazení řádků. Formát [NEON |neon:format] akceptuje jak odsazení pomocí mezer, tak odsazení pomocí tabulátorů, ale ne obojí zároveň. Výchozí konfigurační soubor ve Web Projectu využívá tabulátory. -Veškerá konfigurace, včetně konfigurace databáze, je uložena v adresáři `/config/` v souborech `common.neon` a `local.neon`. Soubor `common.neon` obsahuje globální nastavení aplikace a `local.neon` pouze ty parametry, které jsou specifické pro aktuální prostředí (rozdíl mezi vývojovým a produkčním serverem apod.). - Předání databázového spojení ============================ diff --git a/quickstart/de/home-page.texy b/quickstart/de/home-page.texy index 2ab1c8db32..3858683dd0 100644 --- a/quickstart/de/home-page.texy +++ b/quickstart/de/home-page.texy @@ -66,9 +66,9 @@ Verbinden mit der Datenbank .[#toc-connecting-to-the-database] Jetzt, wo die Datenbank erstellt ist und wir einige Beiträge darin haben, ist es an der Zeit, sie auf unserer neuen glänzenden Seite anzuzeigen. -Zuerst müssen wir unserer Anwendung mitteilen, welche Datenbank sie verwenden soll. Die Konfiguration der Datenbankverbindung wird in `config/local.neon` gespeichert. Legen Sie die Verbindung DSN((Data Source Name)) und Ihre Anmeldedaten fest. Es sollte so aussehen: +Zuerst müssen wir unserer Anwendung mitteilen, welche Datenbank sie verwenden soll. Die Konfiguration der Datenbankverbindung wird in `config/common.neon` gespeichert. Legen Sie die Verbindung DSN((Data Source Name)) und Ihre Anmeldedaten fest. Es sollte so aussehen: -```neon .{file:config/local.neon} +```neon .{file:config/common.neon} database: dsn: 'mysql:host=127.0.0.1;dbname=quickstart' user: *enter user name* @@ -78,8 +78,6 @@ database: .[note] Achten Sie bei der Bearbeitung dieser Datei auf die Einrückung. Das [NEON-Format |neon:format] akzeptiert sowohl Leerzeichen als auch Tabulatoren, aber nicht beides zusammen! Die Konfigurationsdatei im Webprojekt verwendet standardmäßig Tabulatoren. -Die gesamte Konfiguration ist in `config/` in den Dateien `common.neon` und `local.neon` gespeichert. Die Datei `common.neon` enthält die globale Konfiguration der Anwendung und `local.neon` enthält nur die Parameter, die für die Umgebung spezifisch sind (z. B. den Unterschied zwischen Entwicklungs- und Produktionsserver). - Injizieren der Datenbankverbindung .[#toc-injecting-the-database-connection] ============================================================================ diff --git a/quickstart/el/home-page.texy b/quickstart/el/home-page.texy index 812b5ef745..1441f4fb27 100644 --- a/quickstart/el/home-page.texy +++ b/quickstart/el/home-page.texy @@ -66,9 +66,9 @@ INSERT INTO `posts` (`id`, `title`, `content`, `created_at`) VALUES Τώρα, όταν η βάση δεδομένων έχει δημιουργηθεί και έχουμε κάποιες αναρτήσεις σε αυτήν, είναι η κατάλληλη στιγμή να τις εμφανίσουμε στη νέα μας λαμπερή σελίδα. -Πρώτα, πρέπει να πούμε στην εφαρμογή μας ποια βάση δεδομένων θα χρησιμοποιήσει. Η ρύθμιση της σύνδεσης με τη βάση δεδομένων αποθηκεύεται στο `config/local.neon`. Ορίστε τη σύνδεση DSN((Data Source Name)) και τα διαπιστευτήριά σας. Θα πρέπει να μοιάζει κάπως έτσι: +Πρώτα, πρέπει να πούμε στην εφαρμογή μας ποια βάση δεδομένων θα χρησιμοποιήσει. Η ρύθμιση της σύνδεσης με τη βάση δεδομένων αποθηκεύεται στο `config/common.neon`. Ορίστε τη σύνδεση DSN((Data Source Name)) και τα διαπιστευτήριά σας. Θα πρέπει να μοιάζει κάπως έτσι: -```neon .{file:config/local.neon} +```neon .{file:config/common.neon} database: dsn: 'mysql:host=127.0.0.1;dbname=quickstart' user: *enter user name* @@ -78,8 +78,6 @@ database: .[note] Προσέξτε τις εσοχές κατά την επεξεργασία αυτού του αρχείου. Η [μορφή NEON |neon:format] δέχεται τόσο κενά όσο και ταμπέλες, αλλά όχι και τα δύο μαζί! Το αρχείο ρυθμίσεων στο Web Project χρησιμοποιεί τα tabs ως προεπιλογή. -Ολόκληρη η διαμόρφωση αποθηκεύεται στο `config/` στα αρχεία `common.neon` και `local.neon`. Το αρχείο `common.neon` περιέχει τη γενική διαμόρφωση της εφαρμογής και το `local.neon` περιέχει μόνο τις παραμέτρους που αφορούν το περιβάλλον (π.χ. τη διαφορά μεταξύ του διακομιστή ανάπτυξης και του διακομιστή παραγωγής). - Εισαγωγή της σύνδεσης της βάσης δεδομένων .[#toc-injecting-the-database-connection] =================================================================================== diff --git a/quickstart/en/home-page.texy b/quickstart/en/home-page.texy index 411f3dd8a3..f61704a775 100644 --- a/quickstart/en/home-page.texy +++ b/quickstart/en/home-page.texy @@ -66,9 +66,9 @@ Connecting to the Database Now, when the database is created and we have some posts in it, it’s the right time to display them on our new shiny page. -First, we need to tell our application about which database to use. The database connection configuration is stored in `config/local.neon`. Set the connection DSN((Data Source Name)) and your credentials. It should look like this: +First, we need to tell our application about which database to use. The database connection configuration is stored in `config/common.neon`. Set the connection DSN((Data Source Name)) and your credentials. It should look like this: -```neon .{file:config/local.neon} +```neon .{file:config/common.neon} database: dsn: 'mysql:host=127.0.0.1;dbname=quickstart' user: *enter user name* @@ -78,8 +78,6 @@ database: .[note] Be aware of indenting while editing this file. [NEON format|neon:format] accepts both spaces and tabs but not both together! The configuration file in the Web Project uses tabs as default. -The whole configuration including is stored in `config/` in files `common.neon` and `local.neon`. File `common.neon` contains the global configuration of the application and `local.neon` contains only the parameters specific to the environment (e.g. the difference between development and production server). - Injecting the Database Connection ================================= diff --git a/quickstart/es/home-page.texy b/quickstart/es/home-page.texy index 9eb7e78e61..509a140f32 100644 --- a/quickstart/es/home-page.texy +++ b/quickstart/es/home-page.texy @@ -66,9 +66,9 @@ Conexión a la base de datos .[#toc-connecting-to-the-database] Ahora, cuando la base de datos está creada y tenemos algunos posts en ella, es el momento de mostrarlos en nuestra nueva y brillante página. -Primero, necesitamos decirle a nuestra aplicación qué base de datos usar. La configuración de la conexión a la base de datos se almacena en `config/local.neon`. Configura la conexión DSN((Data Source Name)) y tus credenciales. Debería verse así: +Primero, necesitamos decirle a nuestra aplicación qué base de datos usar. La configuración de la conexión a la base de datos se almacena en `config/common.neon`. Configura la conexión DSN((Data Source Name)) y tus credenciales. Debería verse así: -```neon .{file:config/local.neon} +```neon .{file:config/common.neon} database: dsn: 'mysql:host=127.0.0.1;dbname=quickstart' user: *enter user name* @@ -78,8 +78,6 @@ database: .[note] Tenga en cuenta la sangría al editar este archivo. El [formato NEON |neon:format] acepta tanto espacios como tabuladores, pero no ambos a la vez. El archivo de configuración del Proyecto Web utiliza tabuladores por defecto. -Toda la configuración incluida se almacena en `config/` en los archivos `common.neon` y `local.neon`. El archivo `common.neon` contiene la configuración global de la aplicación y `local.neon` contiene sólo los parámetros específicos del entorno (por ejemplo, la diferencia entre el servidor de desarrollo y el de producción). - Inyección de la conexión a la base de datos .[#toc-injecting-the-database-connection] ===================================================================================== diff --git a/quickstart/fr/home-page.texy b/quickstart/fr/home-page.texy index 9b97de5ee3..97d71f44e7 100644 --- a/quickstart/fr/home-page.texy +++ b/quickstart/fr/home-page.texy @@ -66,9 +66,9 @@ Connexion à la base de données .[#toc-connecting-to-the-database] Maintenant, quand la base de données est créée et que nous avons des articles dedans, c'est le bon moment pour les afficher sur notre nouvelle page brillante. -Tout d'abord, nous devons indiquer à notre application quelle base de données utiliser. La configuration de la connexion à la base de données est stockée dans `config/local.neon`. Définissez la connexion DSN((Data Source Name)) et vos informations d'identification. Cela devrait ressembler à ceci : +Tout d'abord, nous devons indiquer à notre application quelle base de données utiliser. La configuration de la connexion à la base de données est stockée dans `config/common.neon`. Définissez la connexion DSN((Data Source Name)) et vos informations d'identification. Cela devrait ressembler à ceci : -```neon .{file:config/local.neon} +```neon .{file:config/common.neon} database: dsn: 'mysql:host=127.0.0.1;dbname=quickstart' user: *enter user name* @@ -78,8 +78,6 @@ database: .[note] Faites attention à l'indentation lorsque vous modifiez ce fichier. Le [format NEON |neon:format] accepte les espaces et les tabulations, mais pas les deux ensemble ! Le fichier de configuration du projet Web utilise les tabulations par défaut. -L'ensemble de la configuration y compris est stocké dans `config/` dans les fichiers `common.neon` et `local.neon`. Le fichier `common.neon` contient la configuration globale de l'application et `local.neon` ne contient que les paramètres spécifiques à l'environnement (par exemple, la différence entre le serveur de développement et le serveur de production). - Injection de la connexion à la base de données .[#toc-injecting-the-database-connection] ======================================================================================== diff --git a/quickstart/hu/home-page.texy b/quickstart/hu/home-page.texy index bbb0f10169..0140160ef3 100644 --- a/quickstart/hu/home-page.texy +++ b/quickstart/hu/home-page.texy @@ -66,9 +66,9 @@ Csatlakozás az adatbázishoz .[#toc-connecting-to-the-database] Most, hogy az adatbázis elkészült, és van benne néhány bejegyzés, itt az ideje, hogy megjelenítsük őket az új, csillogó oldalunkon. -Először is meg kell mondanunk az alkalmazásunknak, hogy melyik adatbázist használja. Az adatbázis-kapcsolat konfigurációját a `config/local.neon` oldalon tároljuk. Állítsuk be a DSN((Data Source Name)) kapcsolatot és a hitelesítő adatokat. Így kell kinéznie: +Először is meg kell mondanunk az alkalmazásunknak, hogy melyik adatbázist használja. Az adatbázis-kapcsolat konfigurációját a `config/common.neon` oldalon tároljuk. Állítsuk be a DSN((Data Source Name)) kapcsolatot és a hitelesítő adatokat. Így kell kinéznie: -```neon .{file:config/local.neon} +```neon .{file:config/common.neon} database: dsn: 'mysql:host=127.0.0.1;dbname=quickstart' user: *enter user name* @@ -78,8 +78,6 @@ database: .[note] Figyeljen a behúzásokra a fájl szerkesztése közben. A [NEON formátum |neon:format] elfogadja a szóközöket és a tabulátorokat is, de nem mindkettőt együtt! A webes projekt konfigurációs fájlja alapértelmezés szerint tabulátorokat használ. -A teljes konfiguráció, beleértve a `config/` fájlt is, a `common.neon` és a `local.neon` fájlokban található. A `common.neon` fájl tartalmazza az alkalmazás globális konfigurációját, a `local.neon` pedig csak a környezetre jellemző paramétereket (pl. a fejlesztési és a termelési szerver közötti különbség). - Az adatbázis-csatlakozás beillesztése .[#toc-injecting-the-database-connection] =============================================================================== diff --git a/quickstart/it/home-page.texy b/quickstart/it/home-page.texy index f5698f2217..231bdf9b8c 100644 --- a/quickstart/it/home-page.texy +++ b/quickstart/it/home-page.texy @@ -66,9 +66,9 @@ Connessione al database .[#toc-connecting-to-the-database] Ora, quando il database è stato creato e abbiamo alcuni post al suo interno, è il momento giusto per visualizzarli sulla nostra nuova pagina. -Per prima cosa, dobbiamo indicare alla nostra applicazione quale database utilizzare. La configurazione della connessione al database è memorizzata in `config/local.neon`. Impostare la connessione DSN((Data Source Name)) e le credenziali. Dovrebbe essere così: +Per prima cosa, dobbiamo indicare alla nostra applicazione quale database utilizzare. La configurazione della connessione al database è memorizzata in `config/common.neon`. Impostare la connessione DSN((Data Source Name)) e le credenziali. Dovrebbe essere così: -```neon .{file:config/local.neon} +```neon .{file:config/common.neon} database: dsn: 'mysql:host=127.0.0.1;dbname=quickstart' user: *enter user name* @@ -78,8 +78,6 @@ database: .[note] Fare attenzione all'indentazione durante la modifica di questo file. Il [formato NEON |neon:format] accetta sia spazi che tabulazioni, ma non entrambi insieme! Il file di configurazione del progetto Web utilizza le tabulazioni come impostazione predefinita. -L'intera configurazione è memorizzata in `config/` nei file `common.neon` e `local.neon`. Il file `common.neon` contiene la configurazione globale dell'applicazione e `local.neon` contiene solo i parametri specifici dell'ambiente (ad esempio, la differenza tra il server di sviluppo e quello di produzione). - Iniettare la connessione al database .[#toc-injecting-the-database-connection] ============================================================================== diff --git a/quickstart/pl/home-page.texy b/quickstart/pl/home-page.texy index 205ecb59d6..47a493df40 100644 --- a/quickstart/pl/home-page.texy +++ b/quickstart/pl/home-page.texy @@ -66,9 +66,9 @@ Podłączenie do bazy danych .[#toc-connecting-to-the-database] Teraz, gdy baza danych jest utworzona i mamy kilka artykułów w niej zapisanych, to dobry moment, aby wyświetlić je na naszej pięknej, nowej stronie. -Najpierw musimy powiedzieć aplikacji, z jakiej bazy danych ma korzystać. Konfigurujemy połączenie z bazą danych w pliku `config/local.neon` używając DSN((Data Source Name)) i poświadczeń logowania. Powinno to wyglądać coś takiego: +Najpierw musimy powiedzieć aplikacji, z jakiej bazy danych ma korzystać. Konfigurujemy połączenie z bazą danych w pliku `config/common.neon` używając DSN((Data Source Name)) i poświadczeń logowania. Powinno to wyglądać coś takiego: -```neon .{file:config/local.neon} +```neon .{file:config/common.neon} database: dsn: 'mysql:host=127.0.0.1;dbname=quickstart' user: *zde vložte jméno uživatele* @@ -78,8 +78,6 @@ database: .[note] Podczas edycji tego pliku zwróć uwagę na wcięcie linii. Format [NEON |neon:format] akceptuje zarówno wcięcie spacji, jak i wcięcie tabulatora, ale nie oba jednocześnie. Domyślny plik konfiguracyjny w Web Project wykorzystuje zakładki. -Cała konfiguracja, w tym konfiguracja bazy danych, jest przechowywana w katalogu `/config/` w plikach `common.neon` i `local.neon`. Plik `common.neon` zawiera globalne ustawienia aplikacji, a plik `local.neon` zawiera tylko te parametry, które są specyficzne dla bieżącego środowiska (różnica między serwerami deweloperskimi i produkcyjnymi, itp.) - Przekazanie połączenia z bazą danych .[#toc-injecting-the-database-connection] ============================================================================== diff --git a/quickstart/pt/home-page.texy b/quickstart/pt/home-page.texy index 9d93cca03f..f7ad50de49 100644 --- a/quickstart/pt/home-page.texy +++ b/quickstart/pt/home-page.texy @@ -66,9 +66,9 @@ Conexão com o banco de dados .[#toc-connecting-to-the-database] Agora, quando o banco de dados é criado e temos alguns posts nele, é o momento certo para exibi-los em nossa nova página brilhante. -Em primeiro lugar, precisamos informar nossa aplicação sobre qual banco de dados utilizar. A configuração da conexão do banco de dados é armazenada em `config/local.neon`. Defina a conexão DSN((Data Source Name)) e suas credenciais. Deve ter este aspecto: +Em primeiro lugar, precisamos informar nossa aplicação sobre qual banco de dados utilizar. A configuração da conexão do banco de dados é armazenada em `config/common.neon`. Defina a conexão DSN((Data Source Name)) e suas credenciais. Deve ter este aspecto: -```neon .{file:config/local.neon} +```neon .{file:config/common.neon} database: dsn: 'mysql:host=127.0.0.1;dbname=quickstart' user: *enter user name* @@ -78,8 +78,6 @@ database: .[note] Esteja atento à indentação durante a edição deste arquivo. [O formato NEON |neon:format] aceita ambos os espaços e abas, mas não ambos juntos! O arquivo de configuração no Projeto Web utiliza abas como padrão. -Toda a configuração inclusive é armazenada em `config/` nos arquivos `common.neon` e `local.neon`. O arquivo `common.neon` contém a configuração global da aplicação e `local.neon` contém apenas os parâmetros específicos do ambiente (por exemplo, a diferença entre servidor de desenvolvimento e de produção). - Injetando a conexão do banco de dados .[#toc-injecting-the-database-connection] =============================================================================== diff --git a/quickstart/ro/home-page.texy b/quickstart/ro/home-page.texy index b9c41ef20f..6199c5a555 100644 --- a/quickstart/ro/home-page.texy +++ b/quickstart/ro/home-page.texy @@ -66,9 +66,9 @@ Conectarea la baza de date .[#toc-connecting-to-the-database] Acum, când baza de date este creată și avem câteva mesaje în ea, este momentul potrivit pentru a le afișa pe noua noastră pagină strălucitoare. -În primul rând, trebuie să spunem aplicației noastre ce bază de date să folosească. Configurația conexiunii la baza de date este stocată în `config/local.neon`. Setați conexiunea DSN((Data Source Name)) și acreditările. Ar trebui să arate astfel: +În primul rând, trebuie să spunem aplicației noastre ce bază de date să folosească. Configurația conexiunii la baza de date este stocată în `config/common.neon`. Setați conexiunea DSN((Data Source Name)) și acreditările. Ar trebui să arate astfel: -```neon .{file:config/local.neon} +```neon .{file:config/common.neon} database: dsn: 'mysql:host=127.0.0.1;dbname=quickstart' user: *enter user name* @@ -78,8 +78,6 @@ database: .[note] Fiți atenți la indentare în timpul editării acestui fișier. [Formatul NEON |neon:format] acceptă atât spații, cât și tabulări, dar nu ambele împreună! Fișierul de configurare din proiectul web utilizează tabulatoarele în mod implicit. -Întreaga configurație, inclusiv este stocată în `config/` în fișierele `common.neon` și `local.neon`. Fișierul `common.neon` conține configurația globală a aplicației, iar `local.neon` conține doar parametrii specifici mediului (de exemplu, diferența dintre serverul de dezvoltare și cel de producție). - Injectarea conexiunii la baza de date .[#toc-injecting-the-database-connection] =============================================================================== diff --git a/quickstart/ru/home-page.texy b/quickstart/ru/home-page.texy index d678339fd4..4d0d1a7ecb 100644 --- a/quickstart/ru/home-page.texy +++ b/quickstart/ru/home-page.texy @@ -66,9 +66,9 @@ INSERT INTO `posts` (`id`, `title`, `content`, `created_at`) VALUES Теперь, когда база данных создана и в ней есть несколько постов, самое время отобразить их на нашей новой блестящей странице. -Во-первых, нам нужно сообщить нашему приложению, какую базу данных использовать. Конфигурация подключения к базе данных хранится в файле `config/local.neon`. Установите соединение DSN((Имя источника данных)) и свои учётные данные. Это должно выглядеть следующим образом: +Во-первых, нам нужно сообщить нашему приложению, какую базу данных использовать. Конфигурация подключения к базе данных хранится в файле `config/common.neon`. Установите соединение DSN((Имя источника данных)) и свои учётные данные. Это должно выглядеть следующим образом: -```neon .{file:config/local.neon} +```neon .{file:config/common.neon} database: dsn: 'mysql:host=127.0.0.1;dbname=quickstart' user: *укажите здесь имя пользователя* @@ -78,8 +78,6 @@ database: .[note] Помните об отступах при редактировании этого файла. [Формат NEON|neon:format] принимает и пробелы, и табуляцию, но не то и другое вместе! В файле конфигурации в веб-проекте по умолчанию используется табуляция. -Вся конфигурация хранится в `config/` в файлах `common.neon` и `local.neon`. Файл `common.neon` содержит глобальную конфигурацию приложения, а `local.neon` содержит только параметры, специфичные для среды (например, разница между сервером разработки и рабочим сервером). - Внедрение подключения к базе данных .[#toc-injecting-the-database-connection] ============================================================================= diff --git a/quickstart/sl/home-page.texy b/quickstart/sl/home-page.texy index 64e508ca40..201c054204 100644 --- a/quickstart/sl/home-page.texy +++ b/quickstart/sl/home-page.texy @@ -66,9 +66,9 @@ Povezovanje s podatkovno bazo .[#toc-connecting-to-the-database] Ko je zbirka podatkov ustvarjena in imamo v njej nekaj objav, je zdaj pravi čas, da jih prikažemo na naši novi svetleči strani. -Najprej moramo našemu programu povedati, katero podatkovno zbirko naj uporabi. Konfiguracija povezave s podatkovno bazo je shranjena v `config/local.neon`. Nastavite povezavo DSN((Data Source Name)) in svoje poverilnice. Izgledati mora takole: +Najprej moramo našemu programu povedati, katero podatkovno zbirko naj uporabi. Konfiguracija povezave s podatkovno bazo je shranjena v `config/common.neon`. Nastavite povezavo DSN((Data Source Name)) in svoje poverilnice. Izgledati mora takole: -```neon .{file:config/local.neon} +```neon .{file:config/common.neon} database: dsn: 'mysql:host=127.0.0.1;dbname=quickstart' user: *enter user name* @@ -78,8 +78,6 @@ database: .[note] Pri urejanju te datoteke bodite pozorni na alineje. [Oblika NEON |neon:format] sprejema tako presledke kot tabulatorje, vendar ne obojega skupaj! Konfiguracijska datoteka v spletnem projektu privzeto uporablja tabulatorje. -Celotna konfiguracija je shranjena v `config/` v datotekah `common.neon` in `local.neon`. Datoteka `common.neon` vsebuje globalno konfiguracijo aplikacije, datoteka `local.neon` pa samo parametre, ki so značilni za okolje (npr. razlika med razvojnim in produkcijskim strežnikom). - Vbrizgavanje povezave s podatkovno bazo .[#toc-injecting-the-database-connection] ================================================================================= diff --git a/quickstart/tr/home-page.texy b/quickstart/tr/home-page.texy index a6711306d3..befc2d672c 100644 --- a/quickstart/tr/home-page.texy +++ b/quickstart/tr/home-page.texy @@ -66,9 +66,9 @@ Veritabanına Bağlanma .[#toc-connecting-to-the-database] Şimdi, veritabanı oluşturulduğunda ve içinde bazı gönderilerimiz olduğunda, bunları yeni parlak sayfamızda görüntülemenin tam zamanıdır. -İlk olarak, uygulamamıza hangi veritabanını kullanacağını söylememiz gerekir. Veritabanı bağlantı yapılandırması `config/local.neon` adresinde saklanır. DSN((Veri Kaynağı Adı)) bağlantısını ve kimlik bilgilerinizi ayarlayın. Bu şekilde görünmelidir: +İlk olarak, uygulamamıza hangi veritabanını kullanacağını söylememiz gerekir. Veritabanı bağlantı yapılandırması `config/common.neon` adresinde saklanır. DSN((Veri Kaynağı Adı)) bağlantısını ve kimlik bilgilerinizi ayarlayın. Bu şekilde görünmelidir: -```neon .{file:config/local.neon} +```neon .{file:config/common.neon} database: dsn: 'mysql:host=127.0.0.1;dbname=quickstart' user: *enter user name* @@ -78,8 +78,6 @@ database: .[note] Bu dosyayı düzenlerken girintilere dikkat edin. [NEON formatı |neon:format] hem boşlukları hem de sekmeleri kabul eder ancak ikisini birlikte kabul etmez! Web Projesindeki yapılandırma dosyası varsayılan olarak sekmeleri kullanır. -Tüm yapılandırma `config/` adresinde `common.neon` ve `local.neon` dosyalarında saklanır. `common.neon` dosyası uygulamanın genel yapılandırmasını içerirken, `local.neon` dosyası yalnızca ortama özgü parametreleri (örneğin geliştirme ve üretim sunucusu arasındaki fark) içerir. - Veritabanı Bağlantısının Enjekte Edilmesi .[#toc-injecting-the-database-connection] =================================================================================== diff --git a/quickstart/uk/home-page.texy b/quickstart/uk/home-page.texy index d93ad3e9ca..f181decfef 100644 --- a/quickstart/uk/home-page.texy +++ b/quickstart/uk/home-page.texy @@ -66,9 +66,9 @@ INSERT INTO `posts` (`id`, `title`, `content`, `created_at`) VALUES Тепер, коли база даних створена і в ній є кілька постів, саме час відобразити їх на нашій новій блискучій сторінці. -По-перше, нам потрібно повідомити нашому додатку, яку базу даних використовувати. Конфігурація підключення до бази даних зберігається у файлі `config/local.neon`. Встановіть з'єднання DSN((Ім'я джерела даних)) і свої облікові дані. Це має виглядати так: +По-перше, нам потрібно повідомити нашому додатку, яку базу даних використовувати. Конфігурація підключення до бази даних зберігається у файлі `config/common.neon`. Встановіть з'єднання DSN((Ім'я джерела даних)) і свої облікові дані. Це має виглядати так: -```neon .{file:config/local.neon} +```neon .{file:config/common.neon} database: dsn: 'mysql:host=127.0.0.1;dbname=quickstart' user: *укажите здесь имя пользователя* @@ -78,8 +78,6 @@ database: .[note] Пам'ятайте про відступи під час редагування цього файлу. [Формат NEON |neon:format] приймає і пробіли, і табуляцію, але не те й інше разом! У файлі конфігурації у веб-проекті за замовчуванням використовується табуляція. -Уся конфігурація зберігається в `config/` у файлах `common.neon` і `local.neon`. Файл `common.neon` містить глобальну конфігурацію додатка, а `local.neon` містить тільки параметри, специфічні для середовища (наприклад, різниця між сервером розробки та робочим сервером). - Впровадження підключення до бази даних .[#toc-injecting-the-database-connection] ================================================================================ From 1f65728ab112aa29dd5b2a228f7dd6de472fcd4e Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sat, 2 Mar 2024 15:25:07 +0100 Subject: [PATCH 056/137] migrations updated --- migrations/cs/to-2-3.texy | 4 +--- migrations/cs/to-2-4.texy | 6 +++--- migrations/cs/to-3-0.texy | 6 +++--- migrations/cs/to-3-1.texy | 10 +++++----- migrations/en/to-2-3.texy | 4 +--- migrations/en/to-2-4.texy | 6 +++--- migrations/en/to-3-0.texy | 6 +++--- migrations/en/to-3-1.texy | 10 +++++----- 8 files changed, 24 insertions(+), 28 deletions(-) diff --git a/migrations/cs/to-2-3.texy b/migrations/cs/to-2-3.texy index 2678fce526..bff8ab9808 100644 --- a/migrations/cs/to-2-3.texy +++ b/migrations/cs/to-2-3.texy @@ -1,14 +1,12 @@ Přechod na verzi 2.3 ******************** -Verzí Nette 2.3 se rozumí, že máte tyto balíčky nainstalované ve verze 2.3.*. Ostatní balíčky mohou mít vyšší nebo nižší čísla verzí, kompatibilitu hlídá Composer. +Verzí Nette 2.3 se rozumí, že máte tyto balíčky nainstalované ve verzi 2.3.*: ```json "require": { "nette/application": "2.3.*", "nette/bootstrap": "2.3.*", - "nette/caching": "2.3.*", - "nette/database": "2.3.*", "nette/di": "2.3.*", "nette/forms": "2.3.*", "nette/http": "2.3.*", diff --git a/migrations/cs/to-2-4.texy b/migrations/cs/to-2-4.texy index 7e9857cc16..4a12f4a9a9 100644 --- a/migrations/cs/to-2-4.texy +++ b/migrations/cs/to-2-4.texy @@ -3,14 +3,12 @@ Přechod na verzi 2.4 Minimální požadovaná verze PHP je 5.6 (pro Latte a Tracy 5.4). -Verzí Nette 2.4 se rozumí, že máte tyto balíčky nainstalované ve verze 2.4.* (resp. 2.5.*). Ostatní balíčky mohou mít vyšší nebo nižší čísla verzí, kompatibilitu hlídá Composer. +Verzí Nette 2.4 se rozumí, že máte tyto balíčky nainstalované ve verzi 2.4.*: ```json "require": { "nette/application": "2.4.*", "nette/bootstrap": "2.4.*", - "nette/caching": "2.5.*", - "nette/database": "2.4.*", "nette/di": "2.4.*", "nette/forms": "2.4.*", "nette/http": "2.4.*", @@ -18,6 +16,8 @@ Verzí Nette 2.4 se rozumí, že máte tyto balíčky nainstalované ve verze 2. }, ``` +Pozor: u ostatních balíčků nainstalujte nejnovější verzi, kterou vám dovolí Composer! Mohou mít totiž jiné verzování. Zkuste uvést `"*"` a podívejte se, jakou verzi Composer nainstaluje. + Deprecated ========== diff --git a/migrations/cs/to-3-0.texy b/migrations/cs/to-3-0.texy index b0f3168f36..9eef7e537f 100644 --- a/migrations/cs/to-3-0.texy +++ b/migrations/cs/to-3-0.texy @@ -3,14 +3,12 @@ Přechod na verzi 3.0 Minimální požadovaná verze PHP je 7.1. -Verzí Nette 3.0 se rozumí, že máte tyto balíčky nainstalované ve verze 3.0.*. Ostatní balíčky mohou mít vyšší nebo nižší čísla verzí, kompatibilitu hlídá Composer. +Verzí Nette 3.0 se rozumí, že máte tyto balíčky nainstalované ve verzi 3.0.*: ```json "require": { "nette/application": "3.0.*", "nette/bootstrap": "3.0.*", - "nette/caching": "3.0.*", - "nette/database": "3.0.*", "nette/di": "3.0.*", "nette/forms": "3.0.*", "nette/http": "3.0.*", @@ -18,6 +16,8 @@ Verzí Nette 3.0 se rozumí, že máte tyto balíčky nainstalované ve verze 3. }, ``` +Pozor: u ostatních balíčků nainstalujte nejnovější verzi, kterou vám dovolí Composer! Mohou mít totiž jiné verzování. Zkuste uvést `"*"` a podívejte se, jakou verzi Composer nainstaluje. + PHP 7.1 type hints ------------------ diff --git a/migrations/cs/to-3-1.texy b/migrations/cs/to-3-1.texy index 87cb17b6d9..0b3fd295ef 100644 --- a/migrations/cs/to-3-1.texy +++ b/migrations/cs/to-3-1.texy @@ -3,22 +3,22 @@ Přechod na verzi 3.1 Minimální požadovaná verze PHP je 7.2. -Všechny změny názvů uvedené v tomto dokumentu znamenají, že původní název samozřejmě nadále existuje a funguje, jen je označený jako deprecated. Můžete se setkat s tím, že vám je bude IDE vizuálně označovat jako deprecated. - -Verzí Nette 3.1 se rozumí, že máte tyto balíčky nainstalované ve verze 3.1.*. Ostatní balíčky mohou mít vyšší nebo nižší čísla verzí, kompatibilitu hlídá Composer. +Verzí Nette 3.1 se rozumí, že máte tyto balíčky nainstalované ve verze 3.1.*: ```json "require": { "nette/application": "3.1.*", "nette/bootstrap": "3.1.*", - "nette/caching": "3.1.*", - "nette/database": "3.1.*", "nette/forms": "3.1.*", "nette/http": "3.1.*", "nette/security": "3.1.*", }, ``` +Pozor: u ostatních balíčků nainstalujte nejnovější verzi, kterou vám dovolí Composer! Mohou mít totiž jiné verzování. Zkuste uvést `"*"` a podívejte se, jakou verzi Composer nainstaluje. + +Všemi změnami názvů uvedenými v tomto dokumentu se myslí, že původní názvy samozřejmě nadále existují a fungují, jen jsou označené jako deprecated. Můžete se setkat s tím, že vám je bude IDE vizuálně označovat jako deprecated. + Názvy rozhraní -------------- diff --git a/migrations/en/to-2-3.texy b/migrations/en/to-2-3.texy index 0abe9dcacd..ede630debb 100644 --- a/migrations/en/to-2-3.texy +++ b/migrations/en/to-2-3.texy @@ -1,14 +1,12 @@ Migrating to Version 2.3 ************************ -Nette version 2.3 means that you have these packages installed in version 2.3.*. Other packages may have higher or lower version numbers, compatibility is ensured by Composer. +Nette 2.3 means that you have these packages installed in version 2.3.*: ```json "require": { "nette/application": "2.3.*", "nette/bootstrap": "2.3.*", - "nette/caching": "2.3.*", - "nette/database": "2.3.*", "nette/di": "2.3.*", "nette/forms": "2.3.*", "nette/http": "2.3.*", diff --git a/migrations/en/to-2-4.texy b/migrations/en/to-2-4.texy index 40945dd76e..0f7a9257a7 100644 --- a/migrations/en/to-2-4.texy +++ b/migrations/en/to-2-4.texy @@ -3,14 +3,12 @@ Migrating to Version 2.4 Minimum required PHP version is 5.6 (for Latte and Tracy 5.4). -Nette version 2.4 means that you have these packages installed in version 2.4.* (or 2.5.*). Other packages may have higher or lower version numbers, compatibility is ensured by Composer. +Nette version 2.4 means that you have these packages installed in version 2.4.*: ```json "require": { "nette/application": "2.4.*", "nette/bootstrap": "2.4.*", - "nette/caching": "2.5.*", - "nette/database": "2.4.*", "nette/di": "2.4.*", "nette/forms": "2.4.*", "nette/http": "2.4.*", @@ -18,6 +16,8 @@ Nette version 2.4 means that you have these packages installed in version 2.4.* }, ``` +Warning: for other packages, install the latest version that Composer will allow! They may have different versioning. Try `"*"` and see what version Composer installs. + Deprecated Stuff ================ diff --git a/migrations/en/to-3-0.texy b/migrations/en/to-3-0.texy index ebec235b37..c8011fe68a 100644 --- a/migrations/en/to-3-0.texy +++ b/migrations/en/to-3-0.texy @@ -3,14 +3,12 @@ Migrating to Version 3.0 Minimum required PHP version is 7.1. -Nette version 3.0 means that you have these packages installed in version 3.0.*. Other packages may have higher or lower version numbers, compatibility is ensured by Composer. +Nette 3.0 means that you have these packages installed in version 3.0.*: ```json "require": { "nette/application": "3.0.*", "nette/bootstrap": "3.0.*", - "nette/caching": "3.0.*", - "nette/database": "3.0.*", "nette/di": "3.0.*", "nette/forms": "3.0.*", "nette/http": "3.0.*", @@ -18,6 +16,8 @@ Nette version 3.0 means that you have these packages installed in version 3.0.*. }, ``` +Warning: for other packages, install the latest version that Composer will allow! They may have different versioning. Try `"*"` and see what version Composer installs. + PHP 7.1 Type Hints ------------------ diff --git a/migrations/en/to-3-1.texy b/migrations/en/to-3-1.texy index c0e53998ee..157e4e5ea4 100644 --- a/migrations/en/to-3-1.texy +++ b/migrations/en/to-3-1.texy @@ -3,22 +3,22 @@ Migrating to Version 3.1 Minimum required PHP version is 7.2. -All name changes mentioned in this document mean that the original name obviously still exists and works, it is just marked as deprecated. You may encounter the IDE visually marking them as deprecated. - -Nette version 3.1 means that you have these packages installed in version 3.1.*. Other packages may have higher or lower version numbers, compatibility is ensured by Composer. +Nette version 3.1 means that you have these packages installed in version 3.1.*: ```json "require": { "nette/application": "3.1.*", "nette/bootstrap": "3.1.*", - "nette/caching": "3.1.*", - "nette/database": "3.1.*", "nette/forms": "3.1.*", "nette/http": "3.1.*", "nette/security": "3.1.*", }, ``` +Warning: for other packages, install the latest version that Composer will allow! They may have different versioning. Try `"*"` and see what version Composer installs. + +All the name changes mentioned in this document mean that the original names still exist and work, of course, they are just marked as deprecated. You may encounter the IDE visually marking them as deprecated. + Interface Names --------------- From 4fcc4063b11eedd63d376828a4e4cc9bb5470fa9 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Fri, 10 Feb 2023 13:12:46 +0100 Subject: [PATCH 057/137] migration guide for Nette 3.2 [WIP] --- migrations/cs/@home.texy | 1 + migrations/cs/@left-menu.texy | 1 + migrations/cs/to-3-2.texy | 28 ++++++++++++++++++++++++++++ migrations/en/@home.texy | 1 + migrations/en/@left-menu.texy | 1 + migrations/en/to-3-2.texy | 28 ++++++++++++++++++++++++++++ 6 files changed, 60 insertions(+) create mode 100644 migrations/cs/to-3-2.texy create mode 100644 migrations/en/to-3-2.texy diff --git a/migrations/cs/@home.texy b/migrations/cs/@home.texy index 9ef31ca6f9..18e175c7d9 100644 --- a/migrations/cs/@home.texy +++ b/migrations/cs/@home.texy @@ -1,6 +1,7 @@ Přechod na novější verze ************************ +- [z Nette 3.1 na 3.2 |to-3-2] - [z Nette 3.0 na 3.1 |to-3-1] - [z Nette 2.4 na 3.0 |to-3-0] - [z Nette 2.3 na 2.4 |to-2-4] diff --git a/migrations/cs/@left-menu.texy b/migrations/cs/@left-menu.texy index 82c0d7e4a7..6f807d7d72 100644 --- a/migrations/cs/@left-menu.texy +++ b/migrations/cs/@left-menu.texy @@ -1,6 +1,7 @@ Přechod na novější verze ************************ - [Úvod |@home] +- [Z verze 3.1 na 3.2 |to-3-2] - [Z verze 3.0 na 3.1 |to-3-1] - [Z verze 2.4 na 3.0 |to-3-0] - [Z verze 2.3 na 2.4 |to-2-4] diff --git a/migrations/cs/to-3-2.texy b/migrations/cs/to-3-2.texy new file mode 100644 index 0000000000..d8ed7422e5 --- /dev/null +++ b/migrations/cs/to-3-2.texy @@ -0,0 +1,28 @@ +Přechod na verzi 3.2 +******************** + +Minimální požadovaná verze PHP je 8.1. + +Verzí Nette 3.2 se rozumí, že máte tyto balíčky nainstalované ve verze 3.2.*: + +```json +"require": { + "nette/application": "3.2.*", + "nette/bootstrap": "3.2.*", + "nette/forms": "3.2.*", + "nette/http": "3.3.*", + "nette/security": "3.2.*", +}, +``` + +Pozor: u ostatních balíčků nainstalujte nejnovější verzi, kterou vám dovolí Composer! Mohou mít totiž jiné verzování. Zkuste uvést `"*"` a podívejte se, jakou verzi Composer nainstaluje. + + +Novinky +------- + +Tato verze využívají všech vymožeností PHP 8. Kód tedy obsahuje všechny nové typehinty zavedené v PHP 8, typy u properties, nové jazykové featury a nativní funkce. Pokusil jsem se maximálně zachovat zpětnou kompatibilitu a tam, kde by přidání typu mohlo něco rozbít, jsem ho zatím nepřidával. + +Dále třídy až na výjimky přestaly využívat traitu Nette\SmartObject, protože její vylepšení po dlouhých letech proniklo do samotného PHP a už tak není potřeba. + +Finder se přestěhoval do balíčku `nette/utils`, odstraňte jej z composeru. diff --git a/migrations/en/@home.texy b/migrations/en/@home.texy index d49961c0f8..33b6c35c23 100644 --- a/migrations/en/@home.texy +++ b/migrations/en/@home.texy @@ -1,6 +1,7 @@ Upgrade Guide ************* +- [from Nette 3.1 to 3.2 |to-3-2] - [from Nette 3.0 to 3.1 |to-3-1] - [from Nette 2.4 to 3.0 |to-3-0] - [from Nette 2.3 to 2.4 |to-2-4] diff --git a/migrations/en/@left-menu.texy b/migrations/en/@left-menu.texy index af1cd6e312..15d695bbc4 100644 --- a/migrations/en/@left-menu.texy +++ b/migrations/en/@left-menu.texy @@ -1,6 +1,7 @@ Upgrade Guide ************* - [Overview |@home] +- [From 3.1 to 3.2 |to-3-2] - [From 3.0 to 3.1 |to-3-1] - [From 2.4 to 3.0 |to-3-0] - [From 2.3 to 2.4 |to-2-4] diff --git a/migrations/en/to-3-2.texy b/migrations/en/to-3-2.texy new file mode 100644 index 0000000000..2e33147c1e --- /dev/null +++ b/migrations/en/to-3-2.texy @@ -0,0 +1,28 @@ +Migrating to Version 3.2 +************************ + +Minimum required PHP version is 8.1. + +Nette version 3.2 means that you have these packages installed in version 3.2.*: + +```json +"require": { + "nette/application": "3.2.*", + "nette/bootstrap": "3.2.*", + "nette/forms": "3.2.*", + "nette/http": "3.3.*", + "nette/security": "3.2.*", +}, +``` + +Warning: for other packages, install the latest version that Composer will allow! They may have different versioning. Try `"*"` and see what version Composer installs. + + +News +---- + +This version takes full advantage of all the features of PHP 8. So the code contains all the new typehints introduced in PHP 8, types for properties, new language features and native functions. I have tried to maintain backward compatibility as much as possible and where adding a type might break something, I have not added it yet. + +Furthermore, classes have, with a few exceptions, no longer use the Nette\SmartObject trait, as its enhancements after many years have made their way into PHP itself and are no longer needed. + +Finder has moved to the package `nette/utils`, remove it from composer. From fd6b1541bdb057cf7fc5679d4214d19a25062db6 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sun, 10 Mar 2024 18:20:05 +0100 Subject: [PATCH 058/137] oop: improvements --- ...uction-to-object-oriented-programming.texy | 168 ++++++++++++--- ...uction-to-object-oriented-programming.texy | 168 ++++++++++++--- ...uction-to-object-oriented-programming.texy | 168 ++++++++++++--- ...uction-to-object-oriented-programming.texy | 168 ++++++++++++--- ...uction-to-object-oriented-programming.texy | 168 ++++++++++++--- ...uction-to-object-oriented-programming.texy | 168 ++++++++++++--- ...uction-to-object-oriented-programming.texy | 168 ++++++++++++--- ...uction-to-object-oriented-programming.texy | 168 ++++++++++++--- ...uction-to-object-oriented-programming.texy | 168 ++++++++++++--- ...uction-to-object-oriented-programming.texy | 168 ++++++++++++--- ...uction-to-object-oriented-programming.texy | 168 ++++++++++++--- ...uction-to-object-oriented-programming.texy | 168 ++++++++++++--- ...uction-to-object-oriented-programming.texy | 168 ++++++++++++--- ...uction-to-object-oriented-programming.texy | 168 ++++++++++++--- ...uction-to-object-oriented-programming.texy | 192 ++++++++++++++---- ...uction-to-object-oriented-programming.texy | 168 ++++++++++++--- 16 files changed, 2329 insertions(+), 383 deletions(-) diff --git a/nette/bg/introduction-to-object-oriented-programming.texy b/nette/bg/introduction-to-object-oriented-programming.texy index 12388a51fc..7d6e3af2ab 100644 --- a/nette/bg/introduction-to-object-oriented-programming.texy +++ b/nette/bg/introduction-to-object-oriented-programming.texy @@ -52,7 +52,9 @@ $person = new Person(25); echo $person->howOldAreYou(); // Outputs: 25 ``` -В този пример класът `Person` има свойство `$age` и конструктор, който задава това свойство. След това методът `howOldAreYou()` осигурява достъп до възрастта на лицето. +В този пример класът `Person` има свойство (променлива) `$age` и конструктор, който задава това свойство. След това методът `howOldAreYou()` осигурява достъп до възрастта на лицето. + +Псевдопроменливата `$this` се използва вътре в класа за достъп до свойствата и методите на обекта. Ключовата дума `new` се използва за създаване на нов екземпляр на даден клас. В горния пример създадохме ново лице на възраст 25 години. @@ -80,7 +82,7 @@ echo $person->howOldAreYou(); // Outputs: 20 В този пример, ако не посочите възраст при създаването на обект `Person`, ще бъде използвана стойността по подразбиране 20. -И накрая, дефинирането на свойството с неговата инициализация чрез конструктора може да бъде съкратено и опростено по следния начин: +Хубавото е, че дефиницията на свойството с инициализацията му чрез конструктора може да бъде съкратена и опростена по следния начин: ```php class Person @@ -92,6 +94,8 @@ class Person } ``` +За пълнота, в допълнение към конструкторите обектите могат да имат деструктори (метод `__destruct`), които се извикват преди обектът да бъде освободен от паметта. + Пространства от имена .[#toc-namespaces] ---------------------------------------- @@ -152,9 +156,9 @@ class Person $this->age = $age; } - function howOldAreYou() + function printInformation() { - return $this->age; + echo "Age: {$this->age} years\n"; } } @@ -170,8 +174,8 @@ class Student extends Person function printInformation() { - echo 'Age of student: ', $this->howOldAreYou(); - echo 'Field of study: ', $this->fieldOfStudy; + parent::printInformation(); + echo "Field of study: {$this->fieldOfStudy} \n"; } } @@ -183,12 +187,26 @@ $student->printInformation(); - Използвахме ключовата дума `extends`, за да разширим класа `Person`, което означава, че класът `Student` наследява всички методи и свойства от `Person`. -- Ключовата дума `parent::` ни позволява да извикваме методи от родителския клас. В този случай извикахме конструктора от класа `Person`, преди да добавим наша собствена функционалност към класа `Student`. +- Ключовата дума `parent::` ни позволява да извикваме методи от родителския клас. В този случай извикахме конструктора от класа `Person`, преди да добавим наша собствена функционалност към класа `Student`. И по същия начин - метода на `printInformation()` класа-родител, преди да изведем информацията за учениците. Наследяването е предназначено за ситуации, в които между класовете има връзка "е а". Например, клас `Student` е клас `Person`. Котката е животно. То ни позволява в случаите, когато в кода очакваме един обект (например "Човек"), да използваме вместо него производен обект (например "Ученик"). От съществено значение е да осъзнаем, че основната цел на наследяването **не е** да предотврати дублирането на кода. Напротив, неправилното използване на наследяването може да доведе до сложен и труден за поддържане код. Ако между класовете няма връзка "е а", трябва да помислим за композиция вместо за наследяване. +Обърнете внимание, че методите `printInformation()` в класовете `Person` и `Student` извеждат малко по-различна информация. Можем да добавим и други класове (например `Employee`), които ще предоставят други реализации на този метод. Възможността обекти от различни класове да реагират на един и същ метод по различни начини се нарича полиморфизъм: + +```php +$people = [ + new Person(30), + new Student(20, 'Computer Science'), + new Employee(45, 'Director'), +]; + +foreach ($people as $person) { + $person->printInformation(); +} +``` + Композиция .[#toc-composition] ------------------------------ @@ -202,7 +220,7 @@ class Engine { function start() { - echo "Engine is running."; + echo 'Engine is running.'; } } @@ -218,7 +236,7 @@ class Car function start() { $this->engine->start(); - echo "The car is ready to drive!"; + echo 'The car is ready to drive!'; } } @@ -386,7 +404,29 @@ $cat = new Cat; $cat->makeSound(); ``` -Ако даден клас имплементира интерфейс, но не са дефинирани всички очаквани методи, PHP ще хвърли грешка. Един клас може да имплементира няколко интерфейса едновременно, което е различно от наследяването, при което класът може да наследява само от един клас. +Ако даден клас имплементира интерфейс, но не са дефинирани всички очаквани методи, PHP ще хвърли грешка. + +Един клас може да имплементира няколко интерфейса едновременно, което е различно от наследяването, при което класът може да наследява само от един клас: + +```php +interface Guardian +{ + function guardHouse(); +} + +class Dog implements Animal, Guardian +{ + public function makeSound() + { + echo 'Bark'; + } + + public function guardHouse() + { + echo 'Dog diligently guards the house'; + } +} +``` Абстрактни класове .[#toc-abstract-classes] @@ -422,6 +462,8 @@ $instance->abstractMethod(); В този пример имаме абстрактен клас с един обикновен и един абстрактен метод. След това имаме клас `Child`, който наследява от `AbstractClass` и предоставя имплементация за абстрактния метод. +По какво се различават интерфейсите и абстрактните класове? Абстрактните класове могат да съдържат както абстрактни, така и конкретни методи, докато интерфейсите само определят кои методи трябва да имплементира класът, но не предоставят имплементация. Един клас може да наследи само един абстрактен клас, но може да имплементира произволен брой интерфейси. + Проверка на типа .[#toc-type-checking] -------------------------------------- @@ -450,7 +492,7 @@ class Person public function printAge(): void { - echo "This person is " . $this->age . " years old."; + echo "This person is {$this->age} years old."; } } @@ -465,6 +507,21 @@ function printPersonAge(Person $person): void По този начин гарантираме, че нашият код очаква и работи с данни от правилния тип, което ни помага да предотвратим потенциални грешки. +Някои типове не могат да бъдат записани директно в PHP. В този случай те се изписват в коментара phpDoc, който е стандартният формат за документиране на PHP код, започващ с `/**` и завършващ с `*/`. Той ви позволява да добавяте описания на класове, методи и т.н. А също и да се изброяват сложни типове, като се използват така наречените анотации `@var`, `@param` и `@return`. Тези типове след това се използват от инструментите за статичен анализ на кода, но не се проверяват от самия PHP. + +```php +class Registry +{ + /** @var array indicates that it's an array of Person objects */ + private array $persons = []; + + public function addPerson(Person $person): void + { + $this->persons[] = $person; + } +} +``` + Сравнение и идентичност .[#toc-comparison-and-identity] ------------------------------------------------------- @@ -635,31 +692,47 @@ $truck->honk(); // Also outputs 'Beep beep!' Изключения ---------- -Изключенията в ООП ни позволяват да обработваме и управляваме грешки, които могат да възникнат по време на изпълнението на нашия код. По същество те са обекти, предназначени да регистрират грешки или неочаквани ситуации във вашата програма. - -В PHP имаме вградения клас `Exception` за тези обекти. Той има няколко метода, които ни позволяват да получим повече информация за изключението, като например съобщение за грешка, файла и реда, където е възникнала грешката, и т.н. +Изключенията в ООП ни позволяват да се справяме с грешките и неочакваните ситуации в нашия код. Те са обекти, които носят информация за грешка или необичайна ситуация. -Когато възникне проблем, можем да "хвърлим" изключение (с помощта на `throw`). Ако искаме да "хванем" и обработим това изключение, използваме блоковете `try` и `catch`. +В PHP имаме вграден клас `Exception`, който служи за основа на всички изключения. Той има няколко метода, които ни позволяват да получим повече информация за изключението, например съобщение за грешка, файла и реда, където е възникнала грешката, и т.н. -Нека видим как работи това: +Когато в кода възникне грешка, можем да "хвърлим" изключението, като използваме ключовата дума `throw`. ```php -try { - throw new Exception('Message explaining the reason for the exception'); +function division(float $a, float $b): float +{ + if ($b === 0) { + throw new Exception('Division by zero!'); + } + return $a / $b; +} +``` - // This code won't execute - echo 'I am a message that nobody will read'; +Когато функцията `division()` получи null като втори аргумент, тя хвърля изключение със съобщение за грешка `'Division by zero!'`. За да предотвратим срив на програмата при хвърляне на изключението, го улавяме в блока `try/catch`: +```php +try { + echo division(10, 0); } catch (Exception $e) { echo 'Exception caught: '. $e->getMessage(); } ``` -Важно е да се отбележи, че изключението може да бъде хвърлено по-надълбоко, по време на извикването на други методи. +Кодът, който може да хвърли изключение, е обвит в блок `try`. Ако изключението бъде хвърлено, изпълнението на кода се премества в блок `catch`, където можем да обработим изключението (например да напишем съобщение за грешка). -За един блок `try` могат да бъдат зададени няколко блока `catch`, ако очаквате различни видове изключения. +След блоковете `try` и `catch` можем да добавим незадължителен блок `finally`, който се изпълнява винаги, независимо дали изключението е хвърлено или не (дори ако използваме `return`, `break` или `continue` в блока `try` или `catch` ): -Можем също така да създадем йерархия на изключенията, при която всеки клас на изключението наследява от предишния. Като пример, разгледайте едно просто банково приложение, което позволява депозити и тегления: +```php +try { + echo division(10, 0); +} catch (Exception $e) { + echo 'Exception caught: '. $e->getMessage(); +} finally { + // Code that is always executed whether the exception has been thrown or not +} +``` + +Можем също така да създадем свои собствени класове за изключения (йерархия), които наследяват класа Exception. Като пример, разгледайте едно просто банково приложение, което позволява депозити и тегления: ```php class BankingException extends Exception {} @@ -691,7 +764,11 @@ class BankAccount return $this->balance; } } +``` +За един блок `try` могат да бъдат зададени няколко блока `catch`, ако очаквате различни видове изключения. + +```php $account = new BankAccount; $account->deposit(500); @@ -709,6 +786,51 @@ try { В този пример е важно да се отбележи редът на блоковете `catch`. Тъй като всички изключения се наследяват от `BankingException`, ако имахме този блок първи, всички изключения щяха да бъдат уловени в него, без кодът да достига до следващите блокове `catch`. Затова е важно по-специфичните изключения (т.е. тези, които се наследяват от други) да бъдат по-нагоре в реда на блоковете `catch` от родителските си изключения. +Итерации .[#toc-iterations] +--------------------------- + +В PHP можете да правите цикли през обекти с помощта на цикъла `foreach`, подобно на цикъла през масив. За да работи това, обектът трябва да реализира специален интерфейс. + +Първият вариант е да имплементирате интерфейса `Iterator`, който има методи `current()` за връщане на текущата стойност, `key()` за връщане на ключа, `next()` за преминаване към следващата стойност, `rewind()` за преминаване към началото и `valid()` за проверка дали вече сме в края. + +Другият вариант е да реализираме интерфейс `IteratorAggregate`, който има само един метод `getIterator()`. Той или връща заместващ обект, който ще осигури обхождането, или може да бъде генератор, който е специална функция, използваща `yield`, за да връща последователно ключове и стойности: + +```php +class Person +{ + public function __construct( + public int $age, + ) { + } +} + +class Registry implements IteratorAggregate +{ + private array $people = []; + + public function addPerson(Person $person): void + { + $this->people[] = $person; + } + + public function getIterator(): Generator + { + foreach ($this->people as $person) { + yield $person; + } + } +} + +$list = new Registry; +$list->addPerson(new Person(30)); +$list->addPerson(new Person(25)); + +foreach ($list as $person) { + echo "Age: {$person->age} years\n"; +} +``` + + Най-добри практики .[#toc-best-practices] ----------------------------------------- diff --git a/nette/cs/introduction-to-object-oriented-programming.texy b/nette/cs/introduction-to-object-oriented-programming.texy index 3d86fd5405..7aa59bda34 100644 --- a/nette/cs/introduction-to-object-oriented-programming.texy +++ b/nette/cs/introduction-to-object-oriented-programming.texy @@ -52,7 +52,9 @@ $osoba = new Osoba(25); echo $osoba->kolikJeTiLet(); // Vypíše: 25 ``` -V tomto příkladě třída `Osoba` má vlastnost `$vek` a dále konstruktor, který nastavuje tuto vlastnost. Metoda `kolikJeTiLet()` pak umožňuje přístup k věku osoby. +V tomto příkladě třída `Osoba` má vlastnost (proměnnou) `$vek` a dále konstruktor, který nastavuje tuto vlastnost. Metoda `kolikJeTiLet()` pak umožňuje přístup k věku osoby. + +Pseudoproměnná `$this` se používá uvnitř třídy pro přístup k vlastnostem a metodám objektu. Klíčové slovo `new` se používá k vytvoření nové instance třídy. Ve výše uvedeném příkladu jsme vytvořili novou osobu s věkem 25. @@ -80,7 +82,7 @@ echo $osoba->kolikJeTiLet(); // Vypíše: 20 V tomto příkladě, pokud nezadáte věk při vytváření objektu `Osoba`, bude použita výchozí hodnota 20. -A nakonec, definice vlastnosti s její inicializací přes konstruktor se dá takto zkrátit a zjednodušit: +Příjemné je, že definice vlastnosti s její inicializací přes konstruktor se dá takto zkrátit a zjednodušit: ```php class Osoba @@ -92,6 +94,8 @@ class Osoba } ``` +Pro úplnost, kromě konstruktorů mohou mít objekty i destruktory (metoda `__destruct`), které se zavolají před tím, než je objekt uvolněn z paměti. + Jmenné prostory --------------- @@ -152,9 +156,9 @@ class Osoba $this->vek = $vek; } - function kolikJeTiLet() + function vypisInformace() { - return $this->vek; + echo "Věk: {$this->age} let\n"; } } @@ -170,8 +174,8 @@ class Student extends Osoba function vypisInformace() { - echo 'Věk studenta: ', $this->kolikJeTiLet(); - echo 'Obor studia: ', $this->obor; + parent::vypisInformace(); + echo "Obor studia: {$this->obor} \n"; } } @@ -183,12 +187,26 @@ Jak tento kód funguje? - Použili jsme klíčové slovo `extends` k rozšíření třídy `Osoba`, což znamená, že třída `Student` zdědí všechny metody a vlastnosti z `Osoby`. -- Klíčové slovo `parent::` nám umožňuje volat metody z nadřazené třídy. V tomto případě jsme volali konstruktor z třídy `Osoba` před přidáním vlastní funkcionality do třídy `Student`. +- Klíčové slovo `parent::` nám umožňuje volat metody z nadřazené třídy. V tomto případě jsme volali konstruktor z třídy `Osoba` před přidáním vlastní funkcionality do třídy `Student`. A obdobně i metodu `vypisInformace()` předka před vypsáním informací o studentovi. Dědičnost je určená pro situace, kdy existuje vztah "je" mezi třídami. Například `Student` je `Osoba`. Kočka je zvíře. Dává nám možnost v případech, kdy v kódu očekáváme jeden objekt (např. "Osoba"), použít místo něj objekt zděděný (např. "Student"). Je důležité si uvědomit, že hlavním účelem dědičnosti **není** zabránit duplikaci kódu. Naopak, nesprávné využití dědičnosti může vést k složitému a těžko udržitelnému kódu. Pokud vztah "je" mezi třídami neexistuje, měli bychom místo dědičnosti uvažovat o kompozici. +Všimněte si, že metody `vypisInformace()` ve třídách `Osoba` a `Student` vypisují trochu jiné informace. A můžeme doplnit další třídy (například `Zamestnanec`), které budou poskytovat další implementace této metody. Schopnost objektů různých tříd reagovat na stejnou metodu různými způsoby se nazývá polymorfismus: + +```php +$osoby = [ + new Osoba(30), + new Student(20, 'Informatika'), + new Zamestnanec(45, 'Ředitel'), +]; + +foreach ($osoby as $osoba) { + $osoba->vypisInformace(); +} +``` + Kompozice --------- @@ -202,7 +220,7 @@ class Motor { function zapni() { - echo "Motor běží."; + echo 'Motor běží.'; } } @@ -218,7 +236,7 @@ class Auto function start() { $this->motor->zapni(); - echo "Auto je připraveno k jízdě!"; + echo 'Auto je připraveno k jízdě!'; } } @@ -386,7 +404,29 @@ $kocka = new Kocka; $kocka->vydejZvuk(); ``` -Pokud třída implementuje rozhraní, ale nejsou v ní definované všechny očekávané metody, PHP vyhodí chybu. Třída může implementovat více rozhraní najednou, což je rozdíl oproti dědičnosti, kde může třída dědit pouze od jedné třídy. +Pokud třída implementuje rozhraní, ale nejsou v ní definované všechny očekávané metody, PHP vyhodí chybu. + +Třída může implementovat více rozhraní najednou, což je rozdíl oproti dědičnosti, kde může třída dědit pouze od jedné třídy: + +```php +interface Hlidac +{ + function hlidejDum(); +} + +class Pes implements Zvire, Hlidac +{ + public function vydejZvuk() + { + echo 'Haf'; + } + + public function hlidejDum() + { + echo 'Pes bedlivě střeží dům'; + } +} +``` Abstraktní třídy @@ -422,6 +462,8 @@ $instance->abstraktniMetoda(); V tomto příkladu máme abstraktní třídu s jednou obyčejnou a jednou abstraktní metodou. Poté máme třídu `Potomek`, která dědí z `AbstraktniTrida` a poskytuje implementaci pro abstraktní metodu. +Jak se vlastně liší rozhraní a abstraktních tříd? Abstraktní třídy mohou obsahovat jak abstraktní, tak konkrétní metody, zatímco rozhraní pouze definují, jaké metody musí třída implementovat, ale neposkytují žádnou implementaci. Třída může dědit jen od jedné abstraktní třídy, ale může implementovat libovolný počet rozhraní. + Typová kontrola --------------- @@ -450,7 +492,7 @@ class Osoba public function vypisVek(): void { - echo "Této osobě je " . $this->vek . " let."; + echo "Této osobě je {$this->vek} let."; } } @@ -465,6 +507,21 @@ function vypisVekOsoby(Osoba $osoba): void Tímto způsobem jsme zajistili, že náš kód očekává a pracuje s daty správného typu, což nám pomáhá předcházet potenciálním chybám. +Některé typy nelze v PHP přímo zapsat. V takovém případě se uvádí v phpDoc komentáři, což je standardní formát pro dokumentaci PHP kódu začínající `/**` a končící `*/`. Umožňuje přidávat popisy tříd, metod a tak dále. A také uvádět komplexní typy pomocí tzv. anotací `@var`, `@param` a `@return`. Tyto typy pak využívají nástroje pro statickou analýzu kódu, ale samotné PHP je nekontroluje. + +```php +class Seznam +{ + /** @var array zápis říká, že jde o pole objektů Osoba */ + private array $osoby = []; + + public function pridatOsobu(Osoba $osoba): void + { + $this->osoby[] = $osoba; + } +} +``` + Porovnávání a identita ---------------------- @@ -635,31 +692,47 @@ Traity vám umožní snadno a efektivně sdílet kód mezi třídami. Přitom ne Výjimky ------- -Výjimky v OOP nám umožňují řídit a ošetřovat chyby, které mohou vzniknout během provádění našeho kódu. Jsou to vlastně objekty určené k zaznamenání chyb nebo nečekaných situací ve vašem programu. - -V PHP máme pro tyto objekty k dispozici vestavěnou třídu `Exception`. Ta má několik metod, které nám umožňují získat více informací o výjimce, jako je zpráva o chybě, soubor a řádek, kde k chybě došlo, atd. +Výjimky v OOP nám umožňují elegantně zpracovávat chyby a neočekávané situace v našem kódu. Jsou to objekty, které nesou informace o chybě nebo neobvyklé situaci. -Když se objeví problém, můžeme "vyhodit" výjimku (použitím `throw`). Chceme-li tuto výjimku "chytit" a nějak zpracovat, použijeme bloky `try` a `catch`. +V PHP máme vestavěnou třídu `Exception`, která slouží jako základ pro všechny výjimky. Ta má několik metod, které nám umožňují získat více informací o výjimce, jako je zpráva o chybě, soubor a řádek, kde k chybě došlo, atd. -Ukážeme si, jak to funguje: +Když v kódu nastane chyba, můžeme "vyhodit" výjimku pomocí klíčového slova `throw`. ```php -try { - throw new Exception('Zpráva vysvětlující důvod výjimky'); +function deleni(float $a, float $b): float +{ + if ($b === 0) { + throw new Exception('Dělení nulou!'); + } + return $a / $b; +} +``` - // Tento kód se neprovede - echo 'Jsem zpráva, kterou nikdo nepřečte'; +Když funkce `deleni()` dostane jako druhý argument nulu, vyhodí výjimku s chybovou zprávou `'Dělení nulou!'`. Abychom zabránili pádu programu při vyhození výjimky, zachytíme ji v bloku `try/catch`: +```php +try { + echo deleni(10, 0); } catch (Exception $e) { echo 'Výjimka zachycena: '. $e->getMessage(); } ``` -Důležité je, že výjimka může být vyhozena hlouběji, při volání jiných metod. +Kód, který může vyhodit výjimku, je zabalen do bloku `try`. Pokud je výjimka vyhozena, provádění kódu se přesune do bloku `catch`, kde můžeme výjimku zpracovat (např. vypsat chybovou zprávu). -Pro jeden blok `try` lze uvést více bloků `catch`, pokud očekáváte různé typy výjimek. +Po blocích `try` a `catch` můžeme přidat nepovinný blok `finally`, který se provede vždy, ať už byla výjimka vyhozena nebo ne (dokonce i v případě, že v bloku `try` nebo `catch` použijeme příkaz `return`, `break` nebo `continue`): -Zároveň můžeme vytvořit hierarchii výjimek, kde každá třída výjimky dědí od té předchozí. Jako příklad si představme jednoduchou bankovní aplikaci, která umožňuje provádět vklady a výběry: +```php +try { + echo deleni(10, 0); +} catch (Exception $e) { + echo 'Výjimka zachycena: '. $e->getMessage(); +} finally { + // Kód, který se provede vždy, ať už byla výjimka vyhozena nebo ne +} +``` + +Můžeme také vytvořit vlastní třídy (hierarchii) výjimek, které dědí od třídy Exception. Jako příklad si představme jednoduchou bankovní aplikaci, která umožňuje provádět vklady a výběry: ```php class BankovniVyjimka extends Exception {} @@ -691,7 +764,11 @@ class BankovniUcet return $this->zustatek; } } +``` +Pro jeden blok `try` lze uvést více bloků `catch`, pokud očekáváte různé typy výjimek. + +```php $ucet = new BankovniUcet; $ucet->vlozit(500); @@ -709,6 +786,51 @@ try { V tomto příkladu je důležité si všimnout pořadí bloků `catch`. Protože všechny výjimky dědí od `BankovniVyjimka`, pokud bychom tento blok měli první, zachytily by se v něm všechny výjimky, aniž by se kód dostal k následujícím `catch` blokům. Proto je důležité mít specifičtější výjimky (tj. ty, které dědí od jiných) v bloku `catch` výše v pořadí než jejich rodičovské výjimky. +Iterace +------- + +V PHP můžete procházet objekty pomocí `foreach` smyčky, podobně jako procházíte pole. Aby to fungovalo, objekt musí implementovat speciální rozhraní. + +První možností je implementovat rozhraní `Iterator`, které má metody `current()` vracející aktuální hodnotu, `key()` vracející klíč, `next()` přesouvající se na další hodnotu, `rewind()` přesouvající se na začátek a `valid()` zjišťující, zda ještě nejsme na konci. + +Druhou možností je implementovat rozhraní `IteratorAggregate`, které má jen jednu metodu `getIterator()`. Ta buď vrací zástupný objekt, který bude zajišťovat procházení, nebo může představovat generátor, což je speciální funkce, ve které se používá `yield` pro postupné vracení klíčů a hodnot: + +```php +class Osoba +{ + public function __construct( + public int $vek, + ) { + } +} + +class Seznam implements IteratorAggregate +{ + private array $osoby = []; + + public function pridatOsobu(Osoba $osoba): void + { + $this->osoby[] = $osoba; + } + + public function getIterator(): Generator + { + foreach ($this->osoby as $osoba) { + yield $osoba; + } + } +} + +$seznam = new Seznam; +$seznam->pridatOsobu(new Osoba(30)); +$seznam->pridatOsobu(new Osoba(25)); + +foreach ($seznam as $osoba) { + echo "Věk: {$osoba->vek} let \n"; +} +``` + + Správné postupy --------------- diff --git a/nette/de/introduction-to-object-oriented-programming.texy b/nette/de/introduction-to-object-oriented-programming.texy index 88a1f0cdff..d9bc24c1da 100644 --- a/nette/de/introduction-to-object-oriented-programming.texy +++ b/nette/de/introduction-to-object-oriented-programming.texy @@ -52,7 +52,9 @@ $person = new Person(25); echo $person->howOldAreYou(); // Outputs: 25 ``` -In diesem Beispiel hat die Klasse `Person` eine Eigenschaft `$age` und einen Konstruktor, der diese Eigenschaft festlegt. Die Methode `howOldAreYou()` ermöglicht dann den Zugriff auf das Alter der Person. +In diesem Beispiel hat die Klasse `Person` eine Eigenschaft (Variable) `$age` und einen Konstruktor, der diese Eigenschaft setzt. Die Methode `howOldAreYou()` ermöglicht dann den Zugriff auf das Alter der Person. + +Die Pseudovariable `$this` wird innerhalb der Klasse für den Zugriff auf die Eigenschaften und Methoden des Objekts verwendet. Das Schlüsselwort `new` wird verwendet, um eine neue Instanz einer Klasse zu erstellen. Im obigen Beispiel haben wir eine neue Person im Alter von 25 Jahren erstellt. @@ -80,7 +82,7 @@ echo $person->howOldAreYou(); // Outputs: 20 Wenn Sie in diesem Beispiel bei der Erstellung eines `Person` Objekts kein Alter angeben, wird der Standardwert von 20 verwendet. -Schließlich kann die Definition von Eigenschaften mit ihrer Initialisierung über den Konstruktor wie folgt verkürzt und vereinfacht werden: +Das Schöne daran ist, dass die Eigenschaftsdefinition mit ihrer Initialisierung über den Konstruktor wie folgt verkürzt und vereinfacht werden kann: ```php class Person @@ -92,6 +94,8 @@ class Person } ``` +Der Vollständigkeit halber sei erwähnt, dass Objekte neben Konstruktoren auch Destruktoren haben können (Methode `__destruct`), die aufgerufen werden, bevor das Objekt aus dem Speicher freigegeben wird. + Namespaces .[#toc-namespaces] ----------------------------- @@ -152,9 +156,9 @@ class Person $this->age = $age; } - function howOldAreYou() + function printInformation() { - return $this->age; + echo "Age: {$this->age} years\n"; } } @@ -170,8 +174,8 @@ class Student extends Person function printInformation() { - echo 'Age of student: ', $this->howOldAreYou(); - echo 'Field of study: ', $this->fieldOfStudy; + parent::printInformation(); + echo "Field of study: {$this->fieldOfStudy} \n"; } } @@ -183,12 +187,26 @@ Wie funktioniert dieser Code? - Wir haben das Schlüsselwort `extends` verwendet, um die Klasse `Person` zu erweitern, d.h. die Klasse `Student` erbt alle Methoden und Eigenschaften von `Person`. -- Mit dem Schlüsselwort `parent::` können wir Methoden der übergeordneten Klasse aufrufen. In diesem Fall haben wir den Konstruktor der Klasse `Person` aufgerufen, bevor wir der Klasse `Student` unsere eigenen Funktionen hinzugefügt haben. +- Mit dem Schlüsselwort `parent::` können wir Methoden der übergeordneten Klasse aufrufen. In diesem Fall haben wir den Konstruktor der Klasse `Person` aufgerufen, bevor wir der Klasse `Student` unsere eigenen Funktionen hinzugefügt haben. Ähnlich verhält es sich mit der Vorgängermethode `printInformation()`, bevor wir die Schülerinformationen auflisten. Vererbung ist für Situationen gedacht, in denen es eine "ist ein"-Beziehung zwischen Klassen gibt. Zum Beispiel ist eine `Student` eine `Person`. Eine Katze ist ein Tier. Sie ermöglicht es uns, in Fällen, in denen wir ein Objekt (z. B. "Person") im Code erwarten, stattdessen ein abgeleitetes Objekt zu verwenden (z. B. "Student"). Es ist wichtig zu erkennen, dass der Hauptzweck der Vererbung **nicht** darin besteht, doppelten Code zu verhindern. Im Gegenteil, der Missbrauch von Vererbung kann zu komplexem und schwer zu wartendem Code führen. Wenn es keine "ist ein"-Beziehung zwischen Klassen gibt, sollten wir Komposition anstelle von Vererbung in Betracht ziehen. +Beachten Sie, dass die Methoden `printInformation()` in den Klassen `Person` und `Student` leicht unterschiedliche Informationen ausgeben. Und wir können weitere Klassen hinzufügen (z. B. `Employee`), die andere Implementierungen dieser Methode bereitstellen werden. Die Fähigkeit von Objekten verschiedener Klassen, auf dieselbe Methode auf unterschiedliche Weise zu reagieren, wird als Polymorphismus bezeichnet: + +```php +$people = [ + new Person(30), + new Student(20, 'Computer Science'), + new Employee(45, 'Director'), +]; + +foreach ($people as $person) { + $person->printInformation(); +} +``` + Komposition .[#toc-composition] ------------------------------- @@ -202,7 +220,7 @@ class Engine { function start() { - echo "Engine is running."; + echo 'Engine is running.'; } } @@ -218,7 +236,7 @@ class Car function start() { $this->engine->start(); - echo "The car is ready to drive!"; + echo 'The car is ready to drive!'; } } @@ -386,7 +404,29 @@ $cat = new Cat; $cat->makeSound(); ``` -Wenn eine Klasse eine Schnittstelle implementiert, aber nicht alle erwarteten Methoden definiert sind, wird PHP einen Fehler ausgeben. Eine Klasse kann mehrere Schnittstellen auf einmal implementieren, was sich von der Vererbung unterscheidet, bei der eine Klasse nur von einer Klasse erben kann. +Wenn eine Klasse eine Schnittstelle implementiert, aber nicht alle erwarteten Methoden definiert sind, wird PHP einen Fehler ausgeben. + +Eine Klasse kann mehrere Schnittstellen auf einmal implementieren, was sich von der Vererbung unterscheidet, bei der eine Klasse nur von einer Klasse erben kann: + +```php +interface Guardian +{ + function guardHouse(); +} + +class Dog implements Animal, Guardian +{ + public function makeSound() + { + echo 'Bark'; + } + + public function guardHouse() + { + echo 'Dog diligently guards the house'; + } +} +``` Abstrakte Klassen .[#toc-abstract-classes] @@ -422,6 +462,8 @@ $instance->abstractMethod(); In diesem Beispiel haben wir eine abstrakte Klasse mit einer regulären und einer abstrakten Methode. Dann haben wir eine Klasse `Child`, die von `AbstractClass` erbt und eine Implementierung für die abstrakte Methode bereitstellt. +Was ist der Unterschied zwischen Schnittstellen und abstrakten Klassen? Abstrakte Klassen können sowohl abstrakte als auch konkrete Methoden enthalten, während Schnittstellen nur festlegen, welche Methoden die Klasse implementieren muss, aber keine Implementierung anbieten. Eine Klasse kann nur von einer abstrakten Klasse erben, kann aber eine beliebige Anzahl von Schnittstellen implementieren. + Typ-Prüfung .[#toc-type-checking] --------------------------------- @@ -450,7 +492,7 @@ class Person public function printAge(): void { - echo "This person is " . $this->age . " years old."; + echo "This person is {$this->age} years old."; } } @@ -465,6 +507,21 @@ function printPersonAge(Person $person): void Auf diese Weise stellen wir sicher, dass unser Code Daten des richtigen Typs erwartet und mit ihnen arbeitet, was uns hilft, mögliche Fehler zu vermeiden. +Einige Typen können nicht direkt in PHP geschrieben werden. In diesem Fall werden sie im phpDoc-Kommentar aufgeführt, dem Standardformat für die Dokumentation von PHP-Code, das mit `/**` beginnt und mit `*/` endet. Es ermöglicht Ihnen, Beschreibungen von Klassen, Methoden usw. hinzuzufügen. Außerdem können Sie komplexe Typen mit den so genannten Annotationen `@var`, `@param` und `@return` auflisten. Diese Typen werden dann von statischen Code-Analyse-Tools verwendet, aber nicht von PHP selbst überprüft. + +```php +class Registry +{ + /** @var array indicates that it's an array of Person objects */ + private array $persons = []; + + public function addPerson(Person $person): void + { + $this->persons[] = $person; + } +} +``` + Vergleich und Identität .[#toc-comparison-and-identity] ------------------------------------------------------- @@ -635,31 +692,47 @@ Traits ermöglichen eine einfache und effiziente gemeinsame Nutzung von Code zwi Ausnahmen --------- -Ausnahmen in OOP ermöglichen es uns, Fehler zu behandeln und zu verwalten, die während der Ausführung unseres Codes auftreten können. Sie sind im Wesentlichen Objekte, die dazu dienen, Fehler oder unerwartete Situationen in Ihrem Programm aufzuzeichnen. +Ausnahmen in der OOP ermöglichen es uns, Fehler und unerwartete Situationen in unserem Code anständig zu behandeln. Sie sind Objekte, die Informationen über einen Fehler oder eine ungewöhnliche Situation enthalten. -In PHP gibt es für diese Objekte die eingebaute Klasse `Exception`. Sie verfügt über mehrere Methoden, mit denen wir weitere Informationen über die Ausnahme erhalten können, z. B. die Fehlermeldung, die Datei und die Zeile, in der der Fehler aufgetreten ist, usw. +In PHP haben wir eine eingebaute Klasse `Exception`, die als Basis für alle Ausnahmen dient. Sie verfügt über mehrere Methoden, mit denen wir weitere Informationen über die Ausnahme erhalten können, z. B. die Fehlermeldung, die Datei und die Zeile, in der der Fehler aufgetreten ist, usw. -Wenn ein Problem auftritt, können wir eine Ausnahme "werfen" (mit `throw`). Wenn wir diese Ausnahme "abfangen" und verarbeiten wollen, verwenden wir die Blöcke `try` und `catch`. - -Schauen wir uns an, wie das funktioniert: +Wenn ein Fehler im Code auftritt, können wir die Ausnahme mit dem Schlüsselwort `throw` "werfen". ```php -try { - throw new Exception('Message explaining the reason for the exception'); +function division(float $a, float $b): float +{ + if ($b === 0) { + throw new Exception('Division by zero!'); + } + return $a / $b; +} +``` - // This code won't execute - echo 'I am a message that nobody will read'; +Wenn die Funktion `division()` null als zweites Argument erhält, löst sie eine Ausnahme mit der Fehlermeldung `'Division by zero!'` aus. Um zu verhindern, dass das Programm abstürzt, wenn die Ausnahme ausgelöst wird, fangen wir sie im Block `try/catch` ab: +```php +try { + echo division(10, 0); } catch (Exception $e) { echo 'Exception caught: '. $e->getMessage(); } ``` -Es ist wichtig zu wissen, dass eine Ausnahme auch tiefer, während des Aufrufs anderer Methoden, ausgelöst werden kann. +Code, der eine Ausnahme auslösen kann, wird in einen Block `try` eingeschlossen. Wenn die Ausnahme ausgelöst wird, geht die Codeausführung in einen Block `catch` über, in dem wir die Ausnahme behandeln können (z. B. eine Fehlermeldung schreiben). -Für einen `try` Block können mehrere `catch` Blöcke angegeben werden, wenn Sie verschiedene Arten von Ausnahmen erwarten. +Nach den Blöcken `try` und `catch` kann ein optionaler Block `finally` eingefügt werden, der immer ausgeführt wird, unabhängig davon, ob die Ausnahme ausgelöst wurde oder nicht (auch wenn `return`, `break` oder `continue` im Block `try` oder `catch` verwendet wird): + +```php +try { + echo division(10, 0); +} catch (Exception $e) { + echo 'Exception caught: '. $e->getMessage(); +} finally { + // Code that is always executed whether the exception has been thrown or not +} +``` -Wir können auch eine Ausnahmehierarchie erstellen, bei der jede Ausnahmeklasse von der vorhergehenden erbt. Nehmen wir als Beispiel eine einfache Bankanwendung, die Einzahlungen und Abhebungen zulässt: +Wir können auch unsere eigenen Ausnahmeklassen (Hierarchie) erstellen, die von der Klasse Exception erben. Betrachten wir als Beispiel eine einfache Bankanwendung, die Einzahlungen und Abhebungen erlaubt: ```php class BankingException extends Exception {} @@ -691,7 +764,11 @@ class BankAccount return $this->balance; } } +``` + +Mehrere `catch` Blöcke können für einen einzigen `try` Block angegeben werden, wenn Sie verschiedene Arten von Ausnahmen erwarten. +```php $account = new BankAccount; $account->deposit(500); @@ -709,6 +786,51 @@ try { In diesem Beispiel ist es wichtig, die Reihenfolge der `catch` Blöcke zu beachten. Da alle Ausnahmen von `BankingException` erben, würden alle Ausnahmen in diesem Block abgefangen werden, ohne dass der Code die nachfolgenden Blöcke von `catch` erreicht. Daher ist es wichtig, spezifischere Ausnahmen (d. h. solche, die von anderen erben) in der Reihenfolge der `catch` -Blöcke höher anzusiedeln als ihre übergeordneten Ausnahmen. +Wiederholungen .[#toc-iterations] +--------------------------------- + +In PHP können Sie mit der `foreach` Schleife durch Objekte laufen, ähnlich wie Sie durch ein Array laufen. Damit dies funktioniert, muss das Objekt eine spezielle Schnittstelle implementieren. + +Die erste Möglichkeit besteht darin, die Schnittstelle `Iterator` zu implementieren, die über die Methoden `current()`, die den aktuellen Wert zurückgeben, `key()`, die den Schlüssel zurückgeben, `next()`, die zum nächsten Wert springen, `rewind()`, die zum Anfang springen, und `valid()`, die überprüft, ob wir schon am Ende sind, verfügt. + +Die andere Möglichkeit besteht darin, eine Schnittstelle `IteratorAggregate` zu implementieren, die nur eine Methode `getIterator()` hat. Diese gibt entweder ein Platzhalterobjekt zurück, das die Durchquerung ermöglicht, oder sie kann ein Generator sein, eine spezielle Funktion, die `yield` verwendet, um Schlüssel und Werte nacheinander zurückzugeben: + +```php +class Person +{ + public function __construct( + public int $age, + ) { + } +} + +class Registry implements IteratorAggregate +{ + private array $people = []; + + public function addPerson(Person $person): void + { + $this->people[] = $person; + } + + public function getIterator(): Generator + { + foreach ($this->people as $person) { + yield $person; + } + } +} + +$list = new Registry; +$list->addPerson(new Person(30)); +$list->addPerson(new Person(25)); + +foreach ($list as $person) { + echo "Age: {$person->age} years\n"; +} +``` + + Bewährte Praktiken .[#toc-best-practices] ----------------------------------------- diff --git a/nette/el/introduction-to-object-oriented-programming.texy b/nette/el/introduction-to-object-oriented-programming.texy index 92d7a8cf58..fdffc10a6e 100644 --- a/nette/el/introduction-to-object-oriented-programming.texy +++ b/nette/el/introduction-to-object-oriented-programming.texy @@ -52,7 +52,9 @@ $person = new Person(25); echo $person->howOldAreYou(); // Outputs: 25 ``` -Σε αυτό το παράδειγμα, η κλάση `Person` έχει μια ιδιότητα `$age` και έναν κατασκευαστή που ορίζει αυτή την ιδιότητα. Η μέθοδος `howOldAreYou()` παρέχει στη συνέχεια πρόσβαση στην ηλικία του ατόμου. +Σε αυτό το παράδειγμα, η κλάση `Person` έχει μια ιδιότητα (μεταβλητή) `$age` και έναν κατασκευαστή που ορίζει αυτή την ιδιότητα. Η μέθοδος `howOldAreYou()` παρέχει στη συνέχεια πρόσβαση στην ηλικία του ατόμου. + +Η ψευδομεταβλητή `$this` χρησιμοποιείται μέσα στην κλάση για την πρόσβαση στις ιδιότητες και τις μεθόδους του αντικειμένου. Η λέξη-κλειδί `new` χρησιμοποιείται για τη δημιουργία μιας νέας περίπτωσης μιας κλάσης. Στο παραπάνω παράδειγμα, δημιουργήσαμε ένα νέο άτομο ηλικίας 25 ετών. @@ -80,7 +82,7 @@ echo $person->howOldAreYou(); // Outputs: 20 Σε αυτό το παράδειγμα, αν δεν καθορίσετε μια ηλικία κατά τη δημιουργία ενός αντικειμένου `Person`, θα χρησιμοποιηθεί η προεπιλεγμένη τιμή 20. -Τέλος, ο ορισμός της ιδιότητας με την αρχικοποίησή της μέσω του κατασκευαστή μπορεί να συντομευτεί και να απλοποιηθεί ως εξής: +Το ωραίο είναι ότι ο ορισμός της ιδιότητας με την αρχικοποίησή της μέσω του κατασκευαστή μπορεί να συντομευτεί και να απλοποιηθεί ως εξής: ```php class Person @@ -92,6 +94,8 @@ class Person } ``` +Για λόγους πληρότητας, εκτός από τους κατασκευαστές, τα αντικείμενα μπορούν να έχουν καταστροφείς (μέθοδος `__destruct`) που καλούνται πριν από την αποδέσμευση του αντικειμένου από τη μνήμη. + Χώροι ονομάτων .[#toc-namespaces] --------------------------------- @@ -152,9 +156,9 @@ class Person $this->age = $age; } - function howOldAreYou() + function printInformation() { - return $this->age; + echo "Age: {$this->age} years\n"; } } @@ -170,8 +174,8 @@ class Student extends Person function printInformation() { - echo 'Age of student: ', $this->howOldAreYou(); - echo 'Field of study: ', $this->fieldOfStudy; + parent::printInformation(); + echo "Field of study: {$this->fieldOfStudy} \n"; } } @@ -183,12 +187,26 @@ $student->printInformation(); - Χρησιμοποιήσαμε τη λέξη-κλειδί `extends` για να επεκτείνουμε την κλάση `Person`, δηλαδή η κλάση `Student` κληρονομεί όλες τις μεθόδους και τις ιδιότητες από την `Person`. -- Η λέξη-κλειδί `parent::` μας επιτρέπει να καλούμε μεθόδους από τη γονική κλάση. Σε αυτή την περίπτωση, καλέσαμε τον κατασκευαστή από την κλάση `Person` πριν προσθέσουμε τη δική μας λειτουργικότητα στην κλάση `Student`. +- Η λέξη-κλειδί `parent::` μας επιτρέπει να καλούμε μεθόδους από τη γονική κλάση. Σε αυτή την περίπτωση, καλέσαμε τον κατασκευαστή από την κλάση `Person` πριν προσθέσουμε τη δική μας λειτουργικότητα στην κλάση `Student`. Και ομοίως, τη μέθοδο του προγόνου `printInformation()` πριν καταχωρίσουμε τις πληροφορίες του μαθητή. Η κληρονομικότητα προορίζεται για καταστάσεις όπου υπάρχει μια σχέση "είναι ένα" μεταξύ κλάσεων. Για παράδειγμα, μια `Student` είναι μια `Person`. Μια γάτα είναι ένα ζώο. Μας επιτρέπει σε περιπτώσεις όπου περιμένουμε ένα αντικείμενο (π.χ. "Person") στον κώδικα να χρησιμοποιήσουμε αντί αυτού ένα παράγωγο αντικείμενο (π.χ. "Student"). Είναι σημαντικό να συνειδητοποιήσουμε ότι ο πρωταρχικός σκοπός της κληρονομικότητας **δεν** είναι να αποτρέψει την επανάληψη του κώδικα. Αντιθέτως, η κακή χρήση της κληρονομικότητας μπορεί να οδηγήσει σε πολύπλοκο και δύσκολα συντηρήσιμο κώδικα. Εάν δεν υπάρχει σχέση "είναι ένα" μεταξύ των κλάσεων, θα πρέπει να εξετάσουμε τη σύνθεση αντί της κληρονομικότητας. +Σημειώστε ότι οι μέθοδοι `printInformation()` στις κλάσεις `Person` και `Student` δίνουν ελαφρώς διαφορετικές πληροφορίες. Και μπορούμε να προσθέσουμε άλλες κλάσεις (όπως η `Employee`) που θα παρέχουν άλλες υλοποιήσεις αυτής της μεθόδου. Η ικανότητα των αντικειμένων διαφορετικών κλάσεων να ανταποκρίνονται στην ίδια μέθοδο με διαφορετικούς τρόπους ονομάζεται πολυμορφισμός: + +```php +$people = [ + new Person(30), + new Student(20, 'Computer Science'), + new Employee(45, 'Director'), +]; + +foreach ($people as $person) { + $person->printInformation(); +} +``` + Σύνθεση .[#toc-composition] --------------------------- @@ -202,7 +220,7 @@ class Engine { function start() { - echo "Engine is running."; + echo 'Engine is running.'; } } @@ -218,7 +236,7 @@ class Car function start() { $this->engine->start(); - echo "The car is ready to drive!"; + echo 'The car is ready to drive!'; } } @@ -386,7 +404,29 @@ $cat = new Cat; $cat->makeSound(); ``` -Εάν μια κλάση υλοποιεί μια διασύνδεση, αλλά δεν έχουν οριστεί όλες οι αναμενόμενες μέθοδοι, η PHP θα εκπέμψει ένα σφάλμα. Μια κλάση μπορεί να υλοποιήσει πολλές διεπαφές ταυτόχρονα, κάτι που διαφέρει από την κληρονομικότητα, όπου μια κλάση μπορεί να κληρονομήσει μόνο από μια κλάση. +Εάν μια κλάση υλοποιεί μια διασύνδεση, αλλά δεν έχουν οριστεί όλες οι αναμενόμενες μέθοδοι, η PHP θα εκπέμψει ένα σφάλμα. + +Μια κλάση μπορεί να υλοποιήσει πολλές διεπαφές ταυτόχρονα, κάτι που διαφέρει από την κληρονομικότητα, όπου μια κλάση μπορεί να κληρονομήσει μόνο από μια κλάση: + +```php +interface Guardian +{ + function guardHouse(); +} + +class Dog implements Animal, Guardian +{ + public function makeSound() + { + echo 'Bark'; + } + + public function guardHouse() + { + echo 'Dog diligently guards the house'; + } +} +``` Αφηρημένες κλάσεις .[#toc-abstract-classes] @@ -422,6 +462,8 @@ $instance->abstractMethod(); Σε αυτό το παράδειγμα, έχουμε μια αφηρημένη κλάση με μια κανονική και μια αφηρημένη μέθοδο. Στη συνέχεια έχουμε μια κλάση `Child` που κληρονομεί από την `AbstractClass` και παρέχει μια υλοποίηση για την αφηρημένη μέθοδο. +Σε τι διαφέρουν οι διεπαφές και οι αφηρημένες κλάσεις; Οι αφηρημένες κλάσεις μπορούν να περιέχουν τόσο αφηρημένες όσο και συγκεκριμένες μεθόδους, ενώ οι διεπαφές ορίζουν μόνο ποιες μεθόδους πρέπει να υλοποιεί η κλάση, αλλά δεν παρέχουν καμία υλοποίηση. Μια κλάση μπορεί να κληρονομήσει από μία μόνο αφηρημένη κλάση, αλλά μπορεί να υλοποιήσει οποιονδήποτε αριθμό διεπαφών. + Έλεγχος τύπου .[#toc-type-checking] ----------------------------------- @@ -450,7 +492,7 @@ class Person public function printAge(): void { - echo "This person is " . $this->age . " years old."; + echo "This person is {$this->age} years old."; } } @@ -465,6 +507,21 @@ function printPersonAge(Person $person): void Με αυτόν τον τρόπο εξασφαλίζουμε ότι ο κώδικάς μας αναμένει και λειτουργεί με δεδομένα του σωστού τύπου, βοηθώντας μας να αποφύγουμε πιθανά σφάλματα. +Ορισμένοι τύποι δεν μπορούν να γραφτούν απευθείας σε PHP. Σε αυτή την περίπτωση, αναφέρονται στο σχόλιο phpDoc, το οποίο είναι η τυπική μορφή για την τεκμηρίωση κώδικα PHP, ξεκινώντας με `/**` και τελειώνοντας με `*/`. Σας επιτρέπει να προσθέσετε περιγραφές κλάσεων, μεθόδων κ.λπ. Και επίσης να απαριθμήσετε σύνθετους τύπους χρησιμοποιώντας τις λεγόμενες επισημειώσεις `@var`, `@param` και `@return`. Αυτοί οι τύποι χρησιμοποιούνται στη συνέχεια από εργαλεία στατικής ανάλυσης κώδικα, αλλά δεν ελέγχονται από την ίδια την PHP. + +```php +class Registry +{ + /** @var array indicates that it's an array of Person objects */ + private array $persons = []; + + public function addPerson(Person $person): void + { + $this->persons[] = $person; + } +} +``` + Σύγκριση και ταυτότητα .[#toc-comparison-and-identity] ------------------------------------------------------ @@ -635,31 +692,47 @@ $truck->honk(); // Also outputs 'Beep beep!' Εξαιρέσεις ---------- -Οι εξαιρέσεις στην OOP μας επιτρέπουν να χειριζόμαστε και να διαχειριζόμαστε σφάλματα που μπορεί να προκύψουν κατά την εκτέλεση του κώδικά μας. Πρόκειται ουσιαστικά για αντικείμενα που έχουν σχεδιαστεί για να καταγράφουν σφάλματα ή απροσδόκητες καταστάσεις στο πρόγραμμά σας. - -Στην PHP, έχουμε την ενσωματωμένη κλάση `Exception` για αυτά τα αντικείμενα. Διαθέτει διάφορες μεθόδους που μας επιτρέπουν να λάβουμε περισσότερες πληροφορίες σχετικά με την εξαίρεση, όπως το μήνυμα σφάλματος, το αρχείο και τη γραμμή όπου συνέβη το σφάλμα κ.λπ. +Οι εξαιρέσεις στην OOP μας επιτρέπουν να χειριζόμαστε με αξιοπρέπεια σφάλματα και απροσδόκητες καταστάσεις στον κώδικά μας. Πρόκειται για αντικείμενα που μεταφέρουν πληροφορίες σχετικά με ένα σφάλμα ή μια ασυνήθιστη κατάσταση. -Όταν προκύπτει ένα πρόβλημα, μπορούμε να "πετάξουμε" μια εξαίρεση (χρησιμοποιώντας την `throw`). Αν θέλουμε να "πιάσουμε" και να επεξεργαστούμε αυτή την εξαίρεση, χρησιμοποιούμε τα μπλοκ `try` και `catch`. +Στην PHP, έχουμε μια ενσωματωμένη κλάση `Exception`, η οποία χρησιμεύει ως βάση για όλες τις εξαιρέσεις. Αυτή διαθέτει διάφορες μεθόδους που μας επιτρέπουν να λάβουμε περισσότερες πληροφορίες σχετικά με την εξαίρεση, όπως το μήνυμα σφάλματος, το αρχείο και τη γραμμή όπου συνέβη το σφάλμα κ.λπ. -Ας δούμε πώς λειτουργεί: +Όταν εμφανίζεται ένα σφάλμα στον κώδικα, μπορούμε να "πετάξουμε" την εξαίρεση χρησιμοποιώντας τη λέξη-κλειδί `throw`. ```php -try { - throw new Exception('Message explaining the reason for the exception'); +function division(float $a, float $b): float +{ + if ($b === 0) { + throw new Exception('Division by zero!'); + } + return $a / $b; +} +``` - // This code won't execute - echo 'I am a message that nobody will read'; +Όταν η συνάρτηση `division()` λαμβάνει null ως δεύτερο όρισμά της, εκπέμπει μια εξαίρεση με το μήνυμα σφάλματος `'Division by zero!'`. Για να αποτρέψουμε τη συντριβή του προγράμματος όταν εκπέμπεται η εξαίρεση, την παγιδεύουμε στο μπλοκ `try/catch`: +```php +try { + echo division(10, 0); } catch (Exception $e) { echo 'Exception caught: '. $e->getMessage(); } ``` -Είναι σημαντικό να σημειωθεί ότι μια εξαίρεση μπορεί να δημιουργηθεί βαθύτερα, κατά τη διάρκεια της κλήσης άλλων μεθόδων. +Ο κώδικας που μπορεί να πετάξει μια εξαίρεση τυλίγεται σε ένα μπλοκ `try`. Αν η εξαίρεση εκτοξευτεί, η εκτέλεση του κώδικα μεταφέρεται σε ένα μπλοκ `catch`, όπου μπορούμε να χειριστούμε την εξαίρεση (π.χ. να γράψουμε ένα μήνυμα σφάλματος). + +Μετά τα μπλοκ `try` και `catch`, μπορούμε να προσθέσουμε ένα προαιρετικό μπλοκ `finally`, το οποίο εκτελείται πάντα, ανεξάρτητα από το αν η εξαίρεση προκλήθηκε ή όχι (ακόμη και αν χρησιμοποιήσουμε τα μπλοκ `return`, `break` ή `continue` στο μπλοκ `try` ή `catch` ): -Για ένα μπλοκ `try`, μπορούν να καθοριστούν πολλαπλά μπλοκ `catch`, αν περιμένετε διαφορετικούς τύπους εξαιρέσεων. +```php +try { + echo division(10, 0); +} catch (Exception $e) { + echo 'Exception caught: '. $e->getMessage(); +} finally { + // Code that is always executed whether the exception has been thrown or not +} +``` -Μπορούμε επίσης να δημιουργήσουμε μια ιεραρχία εξαιρέσεων, όπου κάθε κλάση εξαιρέσεων κληρονομεί από την προηγούμενη. Ως παράδειγμα, θεωρήστε μια απλή τραπεζική εφαρμογή που επιτρέπει καταθέσεις και αναλήψεις: +Μπορούμε επίσης να δημιουργήσουμε τις δικές μας κλάσεις εξαιρέσεων (ιεραρχία) που κληρονομούν από την κλάση Exception. Ως παράδειγμα, θεωρήστε μια απλή τραπεζική εφαρμογή που επιτρέπει καταθέσεις και αναλήψεις: ```php class BankingException extends Exception {} @@ -691,7 +764,11 @@ class BankAccount return $this->balance; } } +``` + +Μπορούν να καθοριστούν πολλαπλά μπλοκ `catch` για ένα μόνο μπλοκ `try`, εάν περιμένετε διαφορετικούς τύπους εξαιρέσεων. +```php $account = new BankAccount; $account->deposit(500); @@ -709,6 +786,51 @@ try { Σε αυτό το παράδειγμα, είναι σημαντικό να σημειωθεί η σειρά των μπλοκ `catch`. Δεδομένου ότι όλες οι εξαιρέσεις κληρονομούν από το `BankingException`, αν είχαμε αυτό το μπλοκ πρώτο, όλες οι εξαιρέσεις θα συλλαμβάνονταν σε αυτό χωρίς ο κώδικας να φτάσει στα επόμενα μπλοκ `catch`. Επομένως, είναι σημαντικό να έχουμε πιο συγκεκριμένες εξαιρέσεις (δηλαδή αυτές που κληρονομούν από άλλες) πιο ψηλά στη σειρά των μπλοκ `catch` από τις εξαιρέσεις των γονέων τους. +Επαναλήψεις .[#toc-iterations] +------------------------------ + +Στην PHP, μπορείτε να διατρέχετε αντικείμενα με τη χρήση του βρόχου `foreach`, όπως ακριβώς κάνετε βρόχο σε έναν πίνακα. Για να λειτουργήσει αυτό, το αντικείμενο πρέπει να υλοποιεί μια ειδική διεπαφή. + +Η πρώτη επιλογή είναι να υλοποιήσετε τη διεπαφή `Iterator`, η οποία έχει τις μεθόδους `current()` που επιστρέφουν την τρέχουσα τιμή, `key()` που επιστρέφουν το κλειδί, `next()` που μεταβαίνουν στην επόμενη τιμή, `rewind()` που μεταβαίνουν στην αρχή και `valid()` που ελέγχουν αν έχουμε φτάσει στο τέλος. + +Η άλλη επιλογή είναι να υλοποιήσουμε μια διεπαφή `IteratorAggregate`, η οποία έχει μόνο μια μέθοδο `getIterator()`. Αυτή είτε επιστρέφει ένα αντικείμενο τοποθέτησης που θα παρέχει τη διάσχιση, είτε μπορεί να είναι μια γεννήτρια, η οποία είναι μια ειδική συνάρτηση που χρησιμοποιεί το `yield` για να επιστρέφει διαδοχικά τα κλειδιά και τις τιμές: + +```php +class Person +{ + public function __construct( + public int $age, + ) { + } +} + +class Registry implements IteratorAggregate +{ + private array $people = []; + + public function addPerson(Person $person): void + { + $this->people[] = $person; + } + + public function getIterator(): Generator + { + foreach ($this->people as $person) { + yield $person; + } + } +} + +$list = new Registry; +$list->addPerson(new Person(30)); +$list->addPerson(new Person(25)); + +foreach ($list as $person) { + echo "Age: {$person->age} years\n"; +} +``` + + Βέλτιστες πρακτικές .[#toc-best-practices] ------------------------------------------ diff --git a/nette/en/introduction-to-object-oriented-programming.texy b/nette/en/introduction-to-object-oriented-programming.texy index bc21f72802..f8be46baf1 100644 --- a/nette/en/introduction-to-object-oriented-programming.texy +++ b/nette/en/introduction-to-object-oriented-programming.texy @@ -52,7 +52,9 @@ $person = new Person(25); echo $person->howOldAreYou(); // Outputs: 25 ``` -In this example, the `Person` class has a property `$age` and a constructor that sets this property. The `howOldAreYou()` method then provides access to the person's age. +In this example, the `Person` class has a property (variable) `$age` and a constructor that sets this property. The `howOldAreYou()` method then provides access to the person's age. + +The `$this` pseudo-variable is used inside the class to access the properties and methods of the object. The `new` keyword is used to create a new instance of a class. In the example above, we created a new person aged 25. @@ -80,7 +82,7 @@ echo $person->howOldAreYou(); // Outputs: 20 In this example, if you don't specify an age when creating a `Person` object, the default value of 20 will be used. -Lastly, property definition with its initialization via the constructor can be shortened and simplified like this: +The nice thing is that the property definition with its initialization via the constructor can be shortened and simplified like this: ```php class Person @@ -92,6 +94,8 @@ class Person } ``` +For completeness, in addition to constructors, objects can have destructors (method `__destruct`) that are called before the object is released from memory. + Namespaces ---------- @@ -152,9 +156,9 @@ class Person $this->age = $age; } - function howOldAreYou() + function printInformation() { - return $this->age; + echo "Age: {$this->age} years\n"; } } @@ -170,8 +174,8 @@ class Student extends Person function printInformation() { - echo 'Age of student: ', $this->howOldAreYou(); - echo 'Field of study: ', $this->fieldOfStudy; + parent::printInformation(); + echo "Field of study: {$this->fieldOfStudy} \n"; } } @@ -183,12 +187,26 @@ How does this code work? - We used the `extends` keyword to extend the `Person` class, meaning the `Student` class inherits all methods and properties from `Person`. -- The `parent::` keyword allows us to call methods from the parent class. In this case, we called the constructor from the `Person` class before adding our own functionality to the `Student` class. +- The `parent::` keyword allows us to call methods from the parent class. In this case, we called the constructor from the `Person` class before adding our own functionality to the `Student` class. And similarly, the `printInformation()` ancestor method before listing the student information. Inheritance is meant for situations where there's an "is a" relationship between classes. For instance, a `Student` is a `Person`. A cat is an animal. It allows us in cases where we expect one object (e.g., "Person") in the code to use a derived object instead (e.g., "Student"). It's essential to realize that the primary purpose of inheritance **is not** to prevent code duplication. On the contrary, misuse of inheritance can lead to complex and hard-to-maintain code. If there's no "is a" relationship between classes, we should consider composition instead of inheritance. +Note that the `printInformation()` methods in the `Person` and `Student` classes output slightly different information. And we can add other classes (such as `Employee`) that will provide other implementations of this method. The ability of objects of different classes to respond to the same method in different ways is called polymorphism: + +```php +$people = [ + new Person(30), + new Student(20, 'Computer Science'), + new Employee(45, 'Director'), +]; + +foreach ($people as $person) { + $person->printInformation(); +} +``` + Composition ----------- @@ -202,7 +220,7 @@ class Engine { function start() { - echo "Engine is running."; + echo 'Engine is running.'; } } @@ -218,7 +236,7 @@ class Car function start() { $this->engine->start(); - echo "The car is ready to drive!"; + echo 'The car is ready to drive!'; } } @@ -386,7 +404,29 @@ $cat = new Cat; $cat->makeSound(); ``` -If a class implements an interface, but not all expected methods are defined, PHP will throw an error. A class can implement multiple interfaces at once, which is different from inheritance, where a class can only inherit from one class. +If a class implements an interface, but not all expected methods are defined, PHP will throw an error. + +A class can implement multiple interfaces at once, which is different from inheritance, where a class can only inherit from one class: + +```php +interface Guardian +{ + function guardHouse(); +} + +class Dog implements Animal, Guardian +{ + public function makeSound() + { + echo 'Bark'; + } + + public function guardHouse() + { + echo 'Dog diligently guards the house'; + } +} +``` Abstract Classes @@ -422,6 +462,8 @@ $instance->abstractMethod(); In this example, we have an abstract class with one regular and one abstract method. Then we have a `Child` class that inherits from `AbstractClass` and provides an implementation for the abstract method. +How are interfaces and abstract classes different? Abstract classes can contain both abstract and concrete methods, while interfaces only define what methods the class must implement, but provide no implementation. A class can inherit from only one abstract class, but can implement any number of interfaces. + Type Checking ------------- @@ -450,7 +492,7 @@ class Person public function printAge(): void { - echo "This person is " . $this->age . " years old."; + echo "This person is {$this->age} years old."; } } @@ -465,6 +507,21 @@ function printPersonAge(Person $person): void In this way, we ensure that our code expects and works with data of the correct type, helping us prevent potential errors. +Some types cannot be written directly in PHP. In this case, they are listed in the phpDoc comment, which is the standard format for documenting PHP code, starting with `/**` and ending with `*/`. It allows you to add descriptions of classes, methods, and so on. And also to list complex types using so-called annotations `@var`, `@param` and `@return`. These types are then used by static code analysis tools, but are not checked by PHP itself. + +```php +class Registry +{ + /** @var array indicates that it's an array of Person objects */ + private array $persons = []; + + public function addPerson(Person $person): void + { + $this->persons[] = $person; + } +} +``` + Comparison and Identity ----------------------- @@ -635,31 +692,47 @@ Traits allow you to easily and efficiently share code between classes. They do n Exceptions ---------- -Exceptions in OOP allow us to handle and manage errors that may arise during the execution of our code. They are essentially objects designed to record errors or unexpected situations in your program. +Exceptions in OOP allow us to gracefully handle errors and unexpected situations in our code. They are objects that carry information about an error or unusual situation. -In PHP, we have the built-in `Exception` class for these objects. It has several methods that allow us to get more information about the exception, such as the error message, the file, and the line where the error occurred, etc. +In PHP, we have a built-in class `Exception`, which serves as the basis for all exceptions. This has several methods that allow us to get more information about the exception, such as the error message, the file and line where the error occurred, etc. -When a problem arises, we can "throw" an exception (using `throw`). If we want to "catch" and process this exception, we use `try` and `catch` blocks. - -Let's see how it works: +When an error occurs in the code, we can "throw" the exception using the `throw` keyword. ```php -try { - throw new Exception('Message explaining the reason for the exception'); +function division(float $a, float $b): float +{ + if ($b === 0) { + throw new Exception('Division by zero!'); + } + return $a / $b; +} +``` - // This code won't execute - echo 'I am a message that nobody will read'; +When the `division()` function receives null as its second argument, it throws an exception with the error message `'Division by zero!'`. To prevent the program from crashing when the exception is thrown, we trap it in the `try/catch` block: +```php +try { + echo division(10, 0); } catch (Exception $e) { echo 'Exception caught: '. $e->getMessage(); } ``` -It's important to note that an exception can be thrown deeper, during the call to other methods. +Code that can throw an exception is wrapped in a block `try`. If the exception is thrown, the code execution moves to a block `catch`, where we can handle the exception (e.g., write an error message). -For one `try` block, multiple `catch` blocks can be specified if you expect different types of exceptions. +After the `try` and `catch` blocks, we can add an optional block `finally`, which is always executed whether the exception was thrown or not (even if we use `return`, `break`, or `continue` in the `try` or `catch` block): + +```php +try { + echo division(10, 0); +} catch (Exception $e) { + echo 'Exception caught: '. $e->getMessage(); +} finally { + // Code that is always executed whether the exception has been thrown or not +} +``` -We can also create an exception hierarchy, where each exception class inherits from the previous one. As an example, consider a simple banking application that allows deposits and withdrawals: +We can also create our own exception classes (hierarchy) that inherit from the Exception class. As an example, consider a simple banking application that allows deposits and withdrawals: ```php class BankingException extends Exception {} @@ -691,7 +764,11 @@ class BankAccount return $this->balance; } } +``` + +Multiple `catch` blocks can be specified for a single `try` block if you expect different types of exceptions. +```php $account = new BankAccount; $account->deposit(500); @@ -709,6 +786,51 @@ try { In this example, it's important to note the order of the `catch` blocks. Since all exceptions inherit from `BankingException`, if we had this block first, all exceptions would be caught in it without the code reaching the subsequent `catch` blocks. Therefore, it's important to have more specific exceptions (i.e., those that inherit from others) higher in the `catch` block order than their parent exceptions. +Iterations +---------- + +In PHP, you can loop through objects using the `foreach` loop, much like you loop through an array. For this to work, the object must implement a special interface. + +The first option is to implement the interface `Iterator`, which has methods `current()` returning the current value, `key()` returning the key, `next()` moving to the next value, `rewind()` moving to the beginning, and `valid()` checking to see if we're at the end yet. + +The other option is to implement an interface `IteratorAggregate`, which has only one method `getIterator()`. This either returns a placeholder object that will provide the traversal, or it can be a generator, which is a special function that uses `yield` to return keys and values sequentially: + +```php +class Person +{ + public function __construct( + public int $age, + ) { + } +} + +class Registry implements IteratorAggregate +{ + private array $people = []; + + public function addPerson(Person $person): void + { + $this->people[] = $person; + } + + public function getIterator(): Generator + { + foreach ($this->people as $person) { + yield $person; + } + } +} + +$list = new Registry; +$list->addPerson(new Person(30)); +$list->addPerson(new Person(25)); + +foreach ($list as $person) { + echo "Age: {$person->age} years\n"; +} +``` + + Best Practices -------------- diff --git a/nette/es/introduction-to-object-oriented-programming.texy b/nette/es/introduction-to-object-oriented-programming.texy index a4c42a0dcc..e60ec556b6 100644 --- a/nette/es/introduction-to-object-oriented-programming.texy +++ b/nette/es/introduction-to-object-oriented-programming.texy @@ -52,7 +52,9 @@ $person = new Person(25); echo $person->howOldAreYou(); // Outputs: 25 ``` -En este ejemplo, la clase `Person` tiene una propiedad `$age` y un constructor que establece esta propiedad. El método `howOldAreYou()` proporciona acceso a la edad de la persona. +En este ejemplo, la clase `Person` tiene una propiedad (variable) `$age` y un constructor que establece esta propiedad. A continuación, el método `howOldAreYou()` proporciona acceso a la edad de la persona. + +La pseudo-variable `$this` se utiliza dentro de la clase para acceder a las propiedades y métodos del objeto. La palabra clave `new` se utiliza para crear una nueva instancia de una clase. En el ejemplo anterior, hemos creado una nueva persona de 25 años. @@ -80,7 +82,7 @@ echo $person->howOldAreYou(); // Outputs: 20 En este ejemplo, si no se especifica una edad al crear un objeto `Person`, se utilizará el valor por defecto de 20. -Por último, la definición de propiedades con su inicialización a través del constructor se puede acortar y simplificar así: +Lo bueno es que la definición de la propiedad con su inicialización a través del constructor se puede acortar y simplificar así: ```php class Person @@ -92,6 +94,8 @@ class Person } ``` +Para completar, además de constructores, los objetos pueden tener destructores (método `__destruct`) que son llamados antes de que el objeto sea liberado de la memoria. + Espacios de nombres .[#toc-namespaces] -------------------------------------- @@ -152,9 +156,9 @@ class Person $this->age = $age; } - function howOldAreYou() + function printInformation() { - return $this->age; + echo "Age: {$this->age} years\n"; } } @@ -170,8 +174,8 @@ class Student extends Person function printInformation() { - echo 'Age of student: ', $this->howOldAreYou(); - echo 'Field of study: ', $this->fieldOfStudy; + parent::printInformation(); + echo "Field of study: {$this->fieldOfStudy} \n"; } } @@ -183,12 +187,26 @@ $student->printInformation(); - Utilizamos la palabra clave `extends` para extender la clase `Person`, lo que significa que la clase `Student` hereda todos los métodos y propiedades de `Person`. -- La palabra clave `parent::` nos permite llamar a métodos de la clase padre. En este caso, hemos llamado al constructor de la clase `Person` antes de añadir nuestra propia funcionalidad a la clase `Student`. +- La palabra clave `parent::` nos permite llamar a métodos de la clase padre. En este caso, llamamos al constructor de la clase `Person` antes de añadir nuestra propia funcionalidad a la clase `Student`. Y de forma similar, el método del ancestro `printInformation()` antes de listar la información del estudiante. La herencia está pensada para situaciones en las que existe una relación "es un" entre clases. Por ejemplo, un `Student` es un `Person`. Un gato es un animal. Nos permite, en casos en los que esperamos un objeto (por ejemplo, "Persona") en el código, utilizar un objeto derivado en su lugar (por ejemplo, "Estudiante"). Es esencial darse cuenta de que el propósito principal de la herencia **no es** evitar la duplicación de código. Al contrario, un mal uso de la herencia puede llevar a un código complejo y difícil de mantener. Si no existe una relación "es un" entre clases, deberíamos considerar la composición en lugar de la herencia. +Observe que los métodos `printInformation()` de las clases `Person` y `Student` proporcionan información ligeramente diferente. Y podemos añadir otras clases (como `Employee`) que proporcionarán otras implementaciones de este método. La capacidad de los objetos de diferentes clases para responder al mismo método de diferentes maneras se llama polimorfismo: + +```php +$people = [ + new Person(30), + new Student(20, 'Computer Science'), + new Employee(45, 'Director'), +]; + +foreach ($people as $person) { + $person->printInformation(); +} +``` + Composición .[#toc-composition] ------------------------------- @@ -202,7 +220,7 @@ class Engine { function start() { - echo "Engine is running."; + echo 'Engine is running.'; } } @@ -218,7 +236,7 @@ class Car function start() { $this->engine->start(); - echo "The car is ready to drive!"; + echo 'The car is ready to drive!'; } } @@ -386,7 +404,29 @@ $cat = new Cat; $cat->makeSound(); ``` -Si una clase implementa una interfaz, pero no todos los métodos esperados están definidos, PHP arrojará un error. Una clase puede implementar múltiples interfaces a la vez, que es diferente de la herencia, donde una clase sólo puede heredar de una clase. +Si una clase implementa una interfaz, pero no todos los métodos esperados están definidos, PHP lanzará un error. + +Una clase puede implementar múltiples interfaces a la vez, que es diferente de la herencia, donde una clase sólo puede heredar de una clase: + +```php +interface Guardian +{ + function guardHouse(); +} + +class Dog implements Animal, Guardian +{ + public function makeSound() + { + echo 'Bark'; + } + + public function guardHouse() + { + echo 'Dog diligently guards the house'; + } +} +``` Clases Abstractas .[#toc-abstract-classes] @@ -422,6 +462,8 @@ $instance->abstractMethod(); En este ejemplo, tenemos una clase abstracta con un método normal y otro abstracto. Luego tenemos una clase `Child` que hereda de `AbstractClass` y proporciona una implementación para el método abstracto. +¿En qué se diferencian las interfaces de las clases abstractas? Las clases abstractas pueden contener métodos abstractos y concretos, mientras que las interfaces sólo definen qué métodos debe implementar la clase, pero no proporcionan ninguna implementación. Una clase sólo puede heredar de una clase abstracta, pero puede implementar cualquier número de interfaces. + Comprobación de tipos .[#toc-type-checking] ------------------------------------------- @@ -450,7 +492,7 @@ class Person public function printAge(): void { - echo "This person is " . $this->age . " years old."; + echo "This person is {$this->age} years old."; } } @@ -465,6 +507,21 @@ function printPersonAge(Person $person): void De esta forma, nos aseguramos de que nuestro código espera y trabaja con datos del tipo correcto, ayudándonos a prevenir posibles errores. +Algunos tipos no pueden escribirse directamente en PHP. En este caso, se listan en el comentario phpDoc, que es el formato estándar para documentar código PHP, comenzando con `/**` y terminando con `*/`. Permite añadir descripciones de clases, métodos, etcétera. Y también listar tipos complejos usando las llamadas anotaciones `@var`, `@param` y `@return`. Estos tipos son luego utilizados por herramientas de análisis estático de código, pero no son comprobados por el propio PHP. + +```php +class Registry +{ + /** @var array indicates that it's an array of Person objects */ + private array $persons = []; + + public function addPerson(Person $person): void + { + $this->persons[] = $person; + } +} +``` + Comparación e identidad .[#toc-comparison-and-identity] ------------------------------------------------------- @@ -635,31 +692,47 @@ Los traits permiten compartir código entre clases de forma fácil y eficiente. Excepciones ----------- -Las excepciones en POO nos permiten manejar y gestionar los errores que puedan surgir durante la ejecución de nuestro código. Son esencialmente objetos diseñados para registrar errores o situaciones inesperadas en tu programa. +Las excepciones en programación orientada a objetos nos permiten manejar con elegancia errores y situaciones inesperadas en nuestro código. Son objetos que contienen información sobre un error o una situación inusual. -En PHP, tenemos la clase incorporada `Exception` para estos objetos. Tiene varios métodos que nos permiten obtener más información sobre la excepción, como el mensaje de error, el archivo y la línea donde se produjo el error, etc. +En PHP, tenemos una clase incorporada `Exception`, que sirve como base para todas las excepciones. Esta tiene varios métodos que nos permiten obtener más información sobre la excepción, como el mensaje de error, el archivo y la línea donde ocurrió el error, etc. -Cuando surge un problema, podemos "lanzar" una excepción (utilizando `throw`). Si queremos "atrapar" y procesar esta excepción, utilizamos los bloques `try` y `catch`. - -Veamos cómo funciona: +Cuando se produce un error en el código, podemos "lanzar" la excepción utilizando la palabra clave `throw`. ```php -try { - throw new Exception('Message explaining the reason for the exception'); +function division(float $a, float $b): float +{ + if ($b === 0) { + throw new Exception('Division by zero!'); + } + return $a / $b; +} +``` - // This code won't execute - echo 'I am a message that nobody will read'; +Cuando la función `division()` recibe null como segundo argumento, lanza una excepción con el mensaje de error `'Division by zero!'`. Para evitar que el programa se bloquee cuando se lanza la excepción, la atrapamos en el bloque `try/catch`: +```php +try { + echo division(10, 0); } catch (Exception $e) { echo 'Exception caught: '. $e->getMessage(); } ``` -Es importante notar que una excepción puede ser lanzada más profundamente, durante la llamada a otros métodos. +El código que puede lanzar una excepción se envuelve en un bloque `try`. Si se lanza la excepción, la ejecución del código se mueve a un bloque `catch`, donde podemos manejar la excepción (por ejemplo, escribir un mensaje de error). -Para un bloque `try`, se pueden especificar varios bloques `catch` si se esperan diferentes tipos de excepciones. +Después de los bloques `try` y `catch`, podemos añadir un bloque opcional `finally`, que siempre se ejecuta, se haya lanzado o no la excepción (incluso si usamos `return`, `break`, o `continue` en el bloque `try` o `catch` ): + +```php +try { + echo division(10, 0); +} catch (Exception $e) { + echo 'Exception caught: '. $e->getMessage(); +} finally { + // Code that is always executed whether the exception has been thrown or not +} +``` -También podemos crear una jerarquía de excepciones, donde cada clase de excepción hereda de la anterior. Como ejemplo, considere una simple aplicación bancaria que permite depósitos y retiros: +También podemos crear nuestras propias clases de excepción (jerarquía) que hereden de la clase Exception. Como ejemplo, consideremos una simple aplicación bancaria que permite depósitos y retiros: ```php class BankingException extends Exception {} @@ -691,7 +764,11 @@ class BankAccount return $this->balance; } } +``` + +Se pueden especificar varios bloques `catch` para un único bloque `try` si se esperan diferentes tipos de excepciones. +```php $account = new BankAccount; $account->deposit(500); @@ -709,6 +786,51 @@ try { En este ejemplo, es importante tener en cuenta el orden de los bloques `catch`. Dado que todas las excepciones heredan de `BankingException`, si tuviéramos este bloque en primer lugar, todas las excepciones se atraparían en él sin que el código llegara a los bloques `catch` posteriores. Por lo tanto, es importante tener las excepciones más específicas (es decir, aquellas que heredan de otras) más arriba en el orden del bloque `catch` que sus excepciones padre. +Iteraciones .[#toc-iterations] +------------------------------ + +En PHP, puedes hacer un bucle a través de objetos usando el bucle `foreach`, de la misma manera que lo haces a través de un array. Para que esto funcione, el objeto debe implementar una interfaz especial. + +La primera opción es implementar la interfaz `Iterator`, que tiene métodos `current()` que devuelve el valor actual, `key()` que devuelve la clave, `next()` que se mueve al siguiente valor, `rewind()` que se mueve al principio, y `valid()` que comprueba si ya hemos llegado al final. + +La otra opción es implementar una interfaz `IteratorAggregate`, que sólo tiene un método `getIterator()`. Esto devuelve un objeto marcador de posición que proporcionará el recorrido, o puede ser un generador, que es una función especial que utiliza `yield` para devolver claves y valores secuencialmente: + +```php +class Person +{ + public function __construct( + public int $age, + ) { + } +} + +class Registry implements IteratorAggregate +{ + private array $people = []; + + public function addPerson(Person $person): void + { + $this->people[] = $person; + } + + public function getIterator(): Generator + { + foreach ($this->people as $person) { + yield $person; + } + } +} + +$list = new Registry; +$list->addPerson(new Person(30)); +$list->addPerson(new Person(25)); + +foreach ($list as $person) { + echo "Age: {$person->age} years\n"; +} +``` + + Buenas prácticas .[#toc-best-practices] --------------------------------------- diff --git a/nette/fr/introduction-to-object-oriented-programming.texy b/nette/fr/introduction-to-object-oriented-programming.texy index c6fd46ecbb..d65c6026e3 100644 --- a/nette/fr/introduction-to-object-oriented-programming.texy +++ b/nette/fr/introduction-to-object-oriented-programming.texy @@ -52,7 +52,9 @@ $person = new Person(25); echo $person->howOldAreYou(); // Outputs: 25 ``` -Dans cet exemple, la classe `Person` possède une propriété `$age` et un constructeur qui définit cette propriété. La méthode `howOldAreYou()` permet ensuite d'accéder à l'âge de la personne. +Dans cet exemple, la classe `Person` possède une propriété (variable) `$age` et un constructeur qui définit cette propriété. La méthode `howOldAreYou()` permet ensuite d'accéder à l'âge de la personne. + +La pseudo-variable `$this` est utilisée à l'intérieur de la classe pour accéder aux propriétés et aux méthodes de l'objet. Le mot-clé `new` est utilisé pour créer une nouvelle instance d'une classe. Dans l'exemple ci-dessus, nous avons créé une nouvelle personne âgée de 25 ans. @@ -80,7 +82,7 @@ echo $person->howOldAreYou(); // Outputs: 20 Dans cet exemple, si vous ne spécifiez pas d'âge lors de la création d'un objet `Person`, la valeur par défaut de 20 sera utilisée. -Enfin, la définition d'une propriété avec son initialisation via le constructeur peut être raccourcie et simplifiée comme suit : +L'avantage est que la définition de la propriété avec son initialisation via le constructeur peut être raccourcie et simplifiée comme suit : ```php class Person @@ -92,6 +94,8 @@ class Person } ``` +Pour être complet, outre les constructeurs, les objets peuvent avoir des destructeurs (méthode `__destruct`) qui sont appelés avant que l'objet ne soit libéré de la mémoire. + Espaces nominatifs .[#toc-namespaces] ------------------------------------- @@ -152,9 +156,9 @@ class Person $this->age = $age; } - function howOldAreYou() + function printInformation() { - return $this->age; + echo "Age: {$this->age} years\n"; } } @@ -170,8 +174,8 @@ class Student extends Person function printInformation() { - echo 'Age of student: ', $this->howOldAreYou(); - echo 'Field of study: ', $this->fieldOfStudy; + parent::printInformation(); + echo "Field of study: {$this->fieldOfStudy} \n"; } } @@ -183,12 +187,26 @@ Comment fonctionne ce code ? - Nous avons utilisé le mot-clé `extends` pour étendre la classe `Person`, ce qui signifie que la classe `Student` hérite de toutes les méthodes et propriétés de `Person`. -- Le mot-clé `parent::` nous permet d'appeler des méthodes de la classe mère. Dans ce cas, nous avons appelé le constructeur de la classe `Person` avant d'ajouter notre propre fonctionnalité à la classe `Student`. +- Le mot-clé `parent::` nous permet d'appeler les méthodes de la classe mère. Dans ce cas, nous avons appelé le constructeur de la classe `Person` avant d'ajouter notre propre fonctionnalité à la classe `Student`. De même, nous avons appelé la méthode de l'ancêtre `printInformation()` avant d'énumérer les informations sur les étudiants. L'héritage est destiné aux situations où il existe une relation "est un" entre les classes. Par exemple, un `Student` est un `Person`. Un chat est un animal. Il nous permet, dans les cas où nous attendons un objet (par exemple, "Personne") dans le code, d'utiliser un objet dérivé à la place (par exemple, "Étudiant"). Il est essentiel de comprendre que l'objectif premier de l'héritage **n'est pas** d'empêcher la duplication du code. Au contraire, une mauvaise utilisation de l'héritage peut conduire à un code complexe et difficile à maintenir. S'il n'y a pas de relation "is a" entre les classes, nous devrions envisager la composition plutôt que l'héritage. +Notez que les méthodes `printInformation()` des classes `Person` et `Student` produisent des informations légèrement différentes. Nous pouvons également ajouter d'autres classes (telles que `Employee`) qui fourniront d'autres implémentations de cette méthode. La capacité des objets de différentes classes à répondre à la même méthode de différentes manières est appelée polymorphisme : + +```php +$people = [ + new Person(30), + new Student(20, 'Computer Science'), + new Employee(45, 'Director'), +]; + +foreach ($people as $person) { + $person->printInformation(); +} +``` + La composition .[#toc-composition] ---------------------------------- @@ -202,7 +220,7 @@ class Engine { function start() { - echo "Engine is running."; + echo 'Engine is running.'; } } @@ -218,7 +236,7 @@ class Car function start() { $this->engine->start(); - echo "The car is ready to drive!"; + echo 'The car is ready to drive!'; } } @@ -386,7 +404,29 @@ $cat = new Cat; $cat->makeSound(); ``` -Si une classe implémente une interface, mais que toutes les méthodes attendues ne sont pas définies, PHP lèvera une erreur. Une classe peut implémenter plusieurs interfaces à la fois, ce qui est différent de l'héritage, où une classe ne peut hériter que d'une seule classe. +Si une classe implémente une interface, mais que toutes les méthodes attendues ne sont pas définies, PHP lèvera une erreur. + +Une classe peut implémenter plusieurs interfaces à la fois, ce qui est différent de l'héritage, où une classe ne peut hériter que d'une seule classe : + +```php +interface Guardian +{ + function guardHouse(); +} + +class Dog implements Animal, Guardian +{ + public function makeSound() + { + echo 'Bark'; + } + + public function guardHouse() + { + echo 'Dog diligently guards the house'; + } +} +``` Classes abstraites .[#toc-abstract-classes] @@ -422,6 +462,8 @@ $instance->abstractMethod(); Dans cet exemple, nous avons une classe abstraite avec une méthode ordinaire et une méthode abstraite. Nous avons ensuite une classe `Child` qui hérite de `AbstractClass` et fournit une implémentation pour la méthode abstraite. +En quoi les interfaces et les classes abstraites sont-elles différentes ? Les classes abstraites peuvent contenir des méthodes abstraites et concrètes, tandis que les interfaces définissent uniquement les méthodes que la classe doit implémenter, mais ne fournissent aucune implémentation. Une classe ne peut hériter que d'une seule classe abstraite, mais peut implémenter un nombre quelconque d'interfaces. + Vérification du type .[#toc-type-checking] ------------------------------------------ @@ -450,7 +492,7 @@ class Person public function printAge(): void { - echo "This person is " . $this->age . " years old."; + echo "This person is {$this->age} years old."; } } @@ -465,6 +507,21 @@ function printPersonAge(Person $person): void De cette manière, nous nous assurons que notre code s'attend à ce que les données soient du bon type et qu'il fonctionne avec elles, ce qui nous permet d'éviter les erreurs potentielles. +Certains types ne peuvent pas être écrits directement en PHP. Dans ce cas, ils sont listés dans le commentaire phpDoc, qui est le format standard de documentation du code PHP, commençant par `/**` et se terminant par `*/`. Il vous permet d'ajouter des descriptions de classes, de méthodes, etc. Il permet également d'énumérer des types complexes à l'aide des annotations `@var`, `@param` et `@return`. Ces types sont ensuite utilisés par les outils d'analyse statique du code, mais ne sont pas vérifiés par PHP lui-même. + +```php +class Registry +{ + /** @var array indicates that it's an array of Person objects */ + private array $persons = []; + + public function addPerson(Person $person): void + { + $this->persons[] = $person; + } +} +``` + Comparaison et identité .[#toc-comparison-and-identity] ------------------------------------------------------- @@ -635,31 +692,47 @@ Les traits vous permettent de partager facilement et efficacement le code entre Exceptions ---------- -Les exceptions en POO nous permettent de traiter et de gérer les erreurs qui peuvent survenir au cours de l'exécution de notre code. Il s'agit essentiellement d'objets conçus pour enregistrer les erreurs ou les situations inattendues dans votre programme. +Les exceptions dans la POO nous permettent de gérer gracieusement les erreurs et les situations inattendues dans notre code. Il s'agit d'objets qui contiennent des informations sur une erreur ou une situation inhabituelle. -En PHP, nous disposons de la classe intégrée `Exception` pour ces objets. Elle possède plusieurs méthodes qui nous permettent d'obtenir plus d'informations sur l'exception, comme le message d'erreur, le fichier et la ligne où l'erreur s'est produite, etc. +En PHP, nous avons une classe intégrée `Exception`, qui sert de base à toutes les exceptions. Cette classe possède plusieurs méthodes qui nous permettent d'obtenir plus d'informations sur l'exception, comme le message d'erreur, le fichier et la ligne où l'erreur s'est produite, etc. -Lorsqu'un problème survient, nous pouvons "lancer" une exception (en utilisant `throw`). Si nous voulons "attraper" et traiter cette exception, nous utilisons les blocs `try` et `catch`. - -Voyons comment cela fonctionne : +Lorsqu'une erreur survient dans le code, nous pouvons "lancer" l'exception à l'aide du mot-clé `throw`. ```php -try { - throw new Exception('Message explaining the reason for the exception'); +function division(float $a, float $b): float +{ + if ($b === 0) { + throw new Exception('Division by zero!'); + } + return $a / $b; +} +``` - // This code won't execute - echo 'I am a message that nobody will read'; +Lorsque la fonction `division()` reçoit null comme deuxième argument, elle lance une exception avec le message d'erreur `'Division by zero!'`. Pour éviter que le programme ne se bloque lorsque l'exception est levée, nous la bloquons dans le bloc `try/catch`: +```php +try { + echo division(10, 0); } catch (Exception $e) { echo 'Exception caught: '. $e->getMessage(); } ``` -Il est important de noter qu'une exception peut être levée plus profondément, lors de l'appel à d'autres méthodes. +Le code qui peut lancer une exception est enveloppé dans un bloc `try`. Si l'exception est levée, l'exécution du code passe à un bloc `catch`, où nous pouvons gérer l'exception (par exemple, écrire un message d'erreur). -Pour un bloc `try`, plusieurs blocs `catch` peuvent être spécifiés si vous vous attendez à différents types d'exceptions. +Après les blocs `try` et `catch`, nous pouvons ajouter un bloc optionnel `finally`, qui est toujours exécuté, que l'exception ait été levée ou non (même si nous utilisons `return`, `break`, ou `continue` dans le bloc `try` ou `catch` ) : + +```php +try { + echo division(10, 0); +} catch (Exception $e) { + echo 'Exception caught: '. $e->getMessage(); +} finally { + // Code that is always executed whether the exception has been thrown or not +} +``` -Nous pouvons également créer une hiérarchie d'exceptions, où chaque classe d'exception hérite de la précédente. Prenons l'exemple d'une application bancaire simple qui autorise les dépôts et les retraits : +Nous pouvons également créer nos propres classes d'exception (hiérarchie) qui héritent de la classe Exception. Prenons l'exemple d'une application bancaire simple qui permet d'effectuer des dépôts et des retraits : ```php class BankingException extends Exception {} @@ -691,7 +764,11 @@ class BankAccount return $this->balance; } } +``` + +Plusieurs blocs `catch` peuvent être spécifiés pour un seul bloc `try` si vous vous attendez à différents types d'exceptions. +```php $account = new BankAccount; $account->deposit(500); @@ -709,6 +786,51 @@ try { Dans cet exemple, il est important de noter l'ordre des blocs `catch`. Étant donné que toutes les exceptions héritent de `BankingException`, si nous avions ce bloc en premier, toutes les exceptions seraient capturées dans ce bloc sans que le code n'atteigne les blocs `catch` suivants. Par conséquent, il est important que les exceptions plus spécifiques (c'est-à-dire celles qui héritent d'autres exceptions) soient placées plus haut dans l'ordre du bloc `catch` que leurs exceptions parentales. +Itérations .[#toc-iterations] +----------------------------- + +En PHP, vous pouvez parcourir des objets en utilisant la boucle `foreach`, de la même manière que vous parcourez un tableau. Pour que cela fonctionne, l'objet doit implémenter une interface spéciale. + +La première option consiste à implémenter l'interface `Iterator`, qui possède des méthodes `current()` renvoyant la valeur courante, `key()` renvoyant la clé, `next()` passant à la valeur suivante, `rewind()` passant au début, et `valid()` vérifiant si nous sommes déjà à la fin. + +L'autre option consiste à mettre en œuvre une interface `IteratorAggregate`, qui ne comporte qu'une seule méthode `getIterator()`. Celle-ci renvoie un objet de remplacement qui assurera la traversée, ou peut être un générateur, c'est-à-dire une fonction spéciale qui utilise `yield` pour renvoyer les clés et les valeurs de manière séquentielle : + +```php +class Person +{ + public function __construct( + public int $age, + ) { + } +} + +class Registry implements IteratorAggregate +{ + private array $people = []; + + public function addPerson(Person $person): void + { + $this->people[] = $person; + } + + public function getIterator(): Generator + { + foreach ($this->people as $person) { + yield $person; + } + } +} + +$list = new Registry; +$list->addPerson(new Person(30)); +$list->addPerson(new Person(25)); + +foreach ($list as $person) { + echo "Age: {$person->age} years\n"; +} +``` + + Meilleures pratiques .[#toc-best-practices] ------------------------------------------- diff --git a/nette/hu/introduction-to-object-oriented-programming.texy b/nette/hu/introduction-to-object-oriented-programming.texy index c1c8b23bba..92c8f98f91 100644 --- a/nette/hu/introduction-to-object-oriented-programming.texy +++ b/nette/hu/introduction-to-object-oriented-programming.texy @@ -52,7 +52,9 @@ $person = new Person(25); echo $person->howOldAreYou(); // Outputs: 25 ``` -Ebben a példában a `Person` osztály rendelkezik egy `$age` tulajdonsággal és egy konstruktorral, amely beállítja ezt a tulajdonságot. A `howOldAreYou()` metódus ezután hozzáférést biztosít a személy életkorához. +Ebben a példában a `Person` osztály rendelkezik egy `$age` tulajdonsággal (változóval) és egy konstruktorral, amely beállítja ezt a tulajdonságot. A `howOldAreYou()` metódus ezután hozzáférést biztosít a személy életkorához. + +A `$this` álváltozót az osztályon belül az objektum tulajdonságainak és metódusainak elérésére használjuk. A `new` kulcsszó egy osztály új példányának létrehozására szolgál. A fenti példában egy új, 25 éves személyt hoztunk létre. @@ -80,7 +82,7 @@ echo $person->howOldAreYou(); // Outputs: 20 Ebben a példában, ha a `Person` objektum létrehozásakor nem ad meg életkort, az alapértelmezett 20-as értéket fogja használni. -Végül a tulajdonság definíciója a konstruktoron keresztül történő inicializálással a következőképpen rövidíthető és egyszerűsíthető: +A szép dolog az, hogy a tulajdonság definíciója a konstruktoron keresztül történő inicializálással lerövidíthető és leegyszerűsíthető így: ```php class Person @@ -92,6 +94,8 @@ class Person } ``` +A teljesség kedvéért a konstruktorok mellett az objektumok rendelkezhetnek destruktorokkal ( `__destruct`), amelyeket az objektum memóriából való kikerülése előtt hívunk meg. + Névterek .[#toc-namespaces] --------------------------- @@ -152,9 +156,9 @@ class Person $this->age = $age; } - function howOldAreYou() + function printInformation() { - return $this->age; + echo "Age: {$this->age} years\n"; } } @@ -170,8 +174,8 @@ class Student extends Person function printInformation() { - echo 'Age of student: ', $this->howOldAreYou(); - echo 'Field of study: ', $this->fieldOfStudy; + parent::printInformation(); + echo "Field of study: {$this->fieldOfStudy} \n"; } } @@ -183,12 +187,26 @@ Hogyan működik ez a kód? - A `extends` kulcsszóval bővítettük a `Person` osztályt, ami azt jelenti, hogy a `Student` osztály minden metódust és tulajdonságot a `Person` osztályból örököl. -- A `parent::` kulcsszó lehetővé teszi számunkra, hogy a szülő osztály metódusait hívjuk. Ebben az esetben a `Person` osztály konstruktorát hívtuk meg, mielőtt a `Student` osztályhoz hozzáadtuk volna a saját funkcióinkat. +- A `parent::` kulcsszó lehetővé teszi számunkra, hogy a szülő osztály metódusait hívjuk. Ebben az esetben a `Person` osztály konstruktorát hívtuk meg, mielőtt a `Student` osztályhoz hozzáadtuk volna a saját funkcionalitásunkat. És hasonlóképpen a `printInformation()` felmenő osztály metódusát, mielőtt a tanulói adatokat listáznánk. Az öröklés olyan helyzetekre való, amikor az osztályok között "is a" kapcsolat van. Például egy `Student` egy `Person`. A macska egy állat. Lehetővé teszi számunkra, hogy olyan esetekben, amikor egy objektumot (pl. "Person") várunk a kódban, egy származtatott objektumot használjunk helyette (pl. "Student"). Lényeges felismerni, hogy az öröklés elsődleges célja **nem** a kódduplikáció megakadályozása. Éppen ellenkezőleg, az öröklés helytelen használata összetett és nehezen karbantartható kódhoz vezethet. Ha nincs "is a" kapcsolat az osztályok között, akkor az öröklés helyett a kompozíciót kell fontolóra vennünk. +Vegyük észre, hogy a `Person` és a `Student` osztályok `printInformation()` metódusai kissé eltérő információkat adnak ki. És hozzáadhatunk más osztályokat is (például `Employee`), amelyek ennek a metódusnak más megvalósításait biztosítják. A különböző osztályok objektumainak azt a képességét, hogy ugyanarra a metódusra különböző módon reagáljanak, polimorfizmusnak nevezzük: + +```php +$people = [ + new Person(30), + new Student(20, 'Computer Science'), + new Employee(45, 'Director'), +]; + +foreach ($people as $person) { + $person->printInformation(); +} +``` + Kompozíció .[#toc-composition] ------------------------------ @@ -202,7 +220,7 @@ class Engine { function start() { - echo "Engine is running."; + echo 'Engine is running.'; } } @@ -218,7 +236,7 @@ class Car function start() { $this->engine->start(); - echo "The car is ready to drive!"; + echo 'The car is ready to drive!'; } } @@ -386,7 +404,29 @@ $cat = new Cat; $cat->makeSound(); ``` -Ha egy osztály megvalósít egy interfészt, de nem minden elvárt metódus van definiálva, a PHP hibát fog dobni. Egy osztály egyszerre több interfészt is megvalósíthat, ami eltér az örökléstől, ahol egy osztály csak egy osztálytól örökölhet. +Ha egy osztály megvalósít egy interfészt, de nem minden elvárt metódus van definiálva, a PHP hibát fog dobni. + +Egy osztály egyszerre több interfészt is megvalósíthat, ami eltér az örökléstől, ahol egy osztály csak egy osztálytól örökölhet: + +```php +interface Guardian +{ + function guardHouse(); +} + +class Dog implements Animal, Guardian +{ + public function makeSound() + { + echo 'Bark'; + } + + public function guardHouse() + { + echo 'Dog diligently guards the house'; + } +} +``` Absztrakt osztályok .[#toc-abstract-classes] @@ -422,6 +462,8 @@ $instance->abstractMethod(); Ebben a példában egy absztrakt osztályunk van egy reguláris és egy absztrakt metódussal. Ezután van egy `Child` osztályunk, amely a `AbstractClass` osztályból örököl, és implementációt biztosít az absztrakt metódushoz. +Miben különböznek az interfészek és az absztrakt osztályok? Az absztrakt osztályok absztrakt és konkrét metódusokat is tartalmazhatnak, míg az interfészek csak azt határozzák meg, hogy az osztálynak milyen metódusokat kell implementálnia, de implementációt nem biztosítanak. Egy osztály csak egy absztrakt osztálytól örökölhet, de tetszőleges számú interfészt implementálhat. + Típusellenőrzés .[#toc-type-checking] ------------------------------------- @@ -450,7 +492,7 @@ class Person public function printAge(): void { - echo "This person is " . $this->age . " years old."; + echo "This person is {$this->age} years old."; } } @@ -465,6 +507,21 @@ function printPersonAge(Person $person): void Így biztosítjuk, hogy a kódunk a megfelelő típusú adatokat várja el és a megfelelő típusú adatokkal dolgozik, ami segít megelőzni a lehetséges hibákat. +Néhány típus nem írható közvetlenül PHP-ben. Ebben az esetben a phpDoc kommentben szerepelnek, ami a PHP kód dokumentálásának szabványos formátuma, a `/**` kezdődik és a `*/` végződik. Lehetővé teszi, hogy osztályok, metódusok stb. leírását adjuk hozzá. Valamint az összetett típusok felsorolását az úgynevezett annotációk segítségével `@var`, `@param` és `@return`. Ezeket a típusokat aztán a statikus kódelemző eszközök használják, de maga a PHP nem ellenőrzi őket. + +```php +class Registry +{ + /** @var array indicates that it's an array of Person objects */ + private array $persons = []; + + public function addPerson(Person $person): void + { + $this->persons[] = $person; + } +} +``` + Összehasonlítás és azonosság .[#toc-comparison-and-identity] ------------------------------------------------------------ @@ -635,31 +692,47 @@ A tulajdonságok lehetővé teszik az osztályok közötti egyszerű és hatéko Kivételek .[#toc-exceptions] ---------------------------- -A kivételek az OOP-ban lehetővé teszik számunkra a kódunk végrehajtása során felmerülő hibák kezelését és kezelését. Ezek lényegében olyan objektumok, amelyeket arra terveztek, hogy rögzítsék a programban előforduló hibákat vagy váratlan helyzeteket. +A kivételek az OOP-ban lehetővé teszik számunkra a hibák és váratlan helyzetek méltóságteljes kezelését a kódunkban. Ezek olyan objektumok, amelyek információt hordoznak egy hibáról vagy szokatlan helyzetről. -A PHP-ben ezekre az objektumokra a beépített `Exception` osztály áll rendelkezésünkre. Számos olyan metódussal rendelkezik, amelyek lehetővé teszik számunkra, hogy több információt kapjunk a kivételről, például a hibaüzenetet, a fájlt és a sort, ahol a hiba előfordult, stb. +A PHP-ben van egy beépített osztályunk, a `Exception`, amely az összes kivétel alapjául szolgál. Ez több olyan metódussal rendelkezik, amelyek lehetővé teszik számunkra, hogy több információt kapjunk a kivételről, például a hibaüzenetet, a fájlt és a sort, ahol a hiba történt, stb. -Ha probléma merül fel, "dobhatunk" egy kivételt (a `throw`) segítségével. Ha ezt a kivételt "el akarjuk kapni" és feldolgozni, akkor a `try` és a `catch` blokkokat használjuk. - -Lássuk, hogyan működik ez: +Ha hiba lép fel a kódban, a `throw` kulcsszóval "dobhatjuk" a kivételt. ```php -try { - throw new Exception('Message explaining the reason for the exception'); +function division(float $a, float $b): float +{ + if ($b === 0) { + throw new Exception('Division by zero!'); + } + return $a / $b; +} +``` - // This code won't execute - echo 'I am a message that nobody will read'; +Ha a `division()` függvény második argumentumként null értéket kap, akkor a `'Division by zero!'` hibaüzenetű kivételt dob. Annak érdekében, hogy a program ne essen össze a kivétel dobásakor, a `try/catch` blokkban csapdába ejtjük azt: +```php +try { + echo division(10, 0); } catch (Exception $e) { echo 'Exception caught: '. $e->getMessage(); } ``` -Fontos megjegyezni, hogy a kivétel mélyebben, más metódusok hívása közben is dobható. +Az olyan kódot, amely kivételt dobhat, egy blokkba csomagoljuk `try`. Ha a kivételt dobjuk, a kód végrehajtása átkerül a `catch` blokkba, ahol a kivételt kezelhetjük (pl. hibaüzenetet írhatunk). -Egy `try` blokkhoz több `catch` blokk is megadható, ha különböző típusú kivételekre számítunk. +A `try` és a `catch` blokkok után hozzáadhatunk egy opcionális `finally` blokkot, amely mindig végrehajtásra kerül, függetlenül attól, hogy a kivételt dobta-e vagy sem (még akkor is, ha a `return`, `break` vagy `continue` blokkot használjuk a `try` vagy `catch` blokkban): + +```php +try { + echo division(10, 0); +} catch (Exception $e) { + echo 'Exception caught: '. $e->getMessage(); +} finally { + // Code that is always executed whether the exception has been thrown or not +} +``` -Létrehozhatunk egy kivételhierarchiát is, ahol minden kivételosztály örökli az előzőt. Példaként tekintsünk egy egyszerű banki alkalmazást, amely lehetővé teszi a befizetéseket és a kifizetéseket: +Saját kivételosztályokat (hierarchiát) is létrehozhatunk, amelyek az Exception osztályból öröklődnek. Példaként tekintsünk egy egyszerű banki alkalmazást, amely lehetővé teszi a befizetéseket és a kifizetéseket: ```php class BankingException extends Exception {} @@ -691,7 +764,11 @@ class BankAccount return $this->balance; } } +``` + +Egyetlen `try` blokkhoz több `catch` blokk is megadható, ha különböző típusú kivételekre számít. +```php $account = new BankAccount; $account->deposit(500); @@ -709,6 +786,51 @@ try { Ebben a példában fontos megjegyezni a `catch` blokkok sorrendjét. Mivel minden kivétel a `BankingException`-tól öröklődik, ha ez a blokk lenne az első, akkor minden kivételt elkapnánk benne anélkül, hogy a kód elérné a következő `catch` blokkokat. Ezért fontos, hogy a specifikusabb (azaz másoktól öröklődő) kivételek a `catch` blokkok sorrendjében előrébb legyenek, mint a szülő kivételek. +Iterációk .[#toc-iterations] +---------------------------- + +A PHP-ben a `foreach` ciklus segítségével végighaladhat az objektumokon, hasonlóan a tömbökön való végighaladáshoz. Ahhoz, hogy ez működjön, az objektumnak egy speciális interfészt kell megvalósítania. + +Az első lehetőség a `Iterator` interfész implementálása, amely a `current()` metódusokkal rendelkezik, amelyek visszaadják az aktuális értéket, a `key()` metódus visszaadja a kulcsot, a `next()` metódus a következő értékre lép, a `rewind()` metódus az elejére lép, és a `valid()` metódus ellenőrzi, hogy a végén vagyunk-e már. + +A másik lehetőség a `IteratorAggregate` interfész implementálása, amelynek csak egy metódusa van: `getIterator()`. Ez vagy egy helyőrző objektumot ad vissza, amely a traverzálást biztosítja, vagy lehet egy generátor, ami egy speciális függvény, amely a `yield` segítségével adja vissza a kulcsokat és az értékeket egymás után: + +```php +class Person +{ + public function __construct( + public int $age, + ) { + } +} + +class Registry implements IteratorAggregate +{ + private array $people = []; + + public function addPerson(Person $person): void + { + $this->people[] = $person; + } + + public function getIterator(): Generator + { + foreach ($this->people as $person) { + yield $person; + } + } +} + +$list = new Registry; +$list->addPerson(new Person(30)); +$list->addPerson(new Person(25)); + +foreach ($list as $person) { + echo "Age: {$person->age} years\n"; +} +``` + + Legjobb gyakorlatok .[#toc-best-practices] ------------------------------------------ diff --git a/nette/it/introduction-to-object-oriented-programming.texy b/nette/it/introduction-to-object-oriented-programming.texy index f7a3452daf..415dcf0c7b 100644 --- a/nette/it/introduction-to-object-oriented-programming.texy +++ b/nette/it/introduction-to-object-oriented-programming.texy @@ -52,7 +52,9 @@ $person = new Person(25); echo $person->howOldAreYou(); // Outputs: 25 ``` -In questo esempio, la classe `Person` ha una proprietà `$age` e un costruttore che imposta questa proprietà. Il metodo `howOldAreYou()` consente di accedere all'età della persona. +In questo esempio, la classe `Person` ha una proprietà (variabile) `$age` e un costruttore che imposta questa proprietà. Il metodo `howOldAreYou()` consente di accedere all'età della persona. + +La pseudo-variabile `$this` viene utilizzata all'interno della classe per accedere alle proprietà e ai metodi dell'oggetto. La parola chiave `new` viene utilizzata per creare una nuova istanza di una classe. Nell'esempio precedente, abbiamo creato una nuova persona di 25 anni. @@ -80,7 +82,7 @@ echo $person->howOldAreYou(); // Outputs: 20 In questo esempio, se non si specifica l'età quando si crea un oggetto `Person`, verrà usato il valore predefinito di 20. -Infine, la definizione della proprietà con la sua inizializzazione tramite il costruttore può essere abbreviata e semplificata in questo modo: +La cosa bella è che la definizione della proprietà con la sua inizializzazione tramite il costruttore può essere accorciata e semplificata in questo modo: ```php class Person @@ -92,6 +94,8 @@ class Person } ``` +Per completezza, oltre ai costruttori, gli oggetti possono avere dei distruttori (metodo `__destruct`) che vengono chiamati prima che l'oggetto venga rilasciato dalla memoria. + Spazi dei nomi .[#toc-namespaces] --------------------------------- @@ -152,9 +156,9 @@ class Person $this->age = $age; } - function howOldAreYou() + function printInformation() { - return $this->age; + echo "Age: {$this->age} years\n"; } } @@ -170,8 +174,8 @@ class Student extends Person function printInformation() { - echo 'Age of student: ', $this->howOldAreYou(); - echo 'Field of study: ', $this->fieldOfStudy; + parent::printInformation(); + echo "Field of study: {$this->fieldOfStudy} \n"; } } @@ -183,12 +187,26 @@ Come funziona questo codice? - Abbiamo usato la parola chiave `extends` per estendere la classe `Person`, il che significa che la classe `Student` eredita tutti i metodi e le proprietà da `Person`. -- La parola chiave `parent::` ci consente di richiamare i metodi della classe padre. In questo caso, abbiamo richiamato il costruttore della classe `Person`, prima di aggiungere le nostre funzionalità alla classe `Student`. +- La parola chiave `parent::` consente di richiamare i metodi della classe padre. In questo caso, abbiamo richiamato il costruttore della classe `Person` prima di aggiungere la nostra funzionalità alla classe `Student`. E allo stesso modo, il metodo dell'antenato `printInformation()` prima di elencare le informazioni sugli studenti. L'ereditarietà è pensata per le situazioni in cui esiste una relazione "is a" tra le classi. Per esempio, un `Student` è un `Person`. Un gatto è un animale. Ci consente, nei casi in cui ci aspettiamo un oggetto (ad esempio, "Persona") nel codice, di utilizzare invece un oggetto derivato (ad esempio, "Studente"). È essenziale rendersi conto che lo scopo principale dell'ereditarietà **non** è quello di prevenire la duplicazione del codice. Al contrario, un uso improprio dell'ereditarietà può portare a codice complesso e difficile da mantenere. Se non c'è una relazione "è un" tra le classi, dovremmo considerare la composizione invece dell'ereditarietà. +Si noti che i metodi `printInformation()` delle classi `Person` e `Student` forniscono informazioni leggermente diverse. È possibile aggiungere altre classi (come `Employee`) che forniranno altre implementazioni di questo metodo. La capacità di oggetti di classi diverse di rispondere allo stesso metodo in modi diversi si chiama polimorfismo: + +```php +$people = [ + new Person(30), + new Student(20, 'Computer Science'), + new Employee(45, 'Director'), +]; + +foreach ($people as $person) { + $person->printInformation(); +} +``` + Composizione .[#toc-composition] -------------------------------- @@ -202,7 +220,7 @@ class Engine { function start() { - echo "Engine is running."; + echo 'Engine is running.'; } } @@ -218,7 +236,7 @@ class Car function start() { $this->engine->start(); - echo "The car is ready to drive!"; + echo 'The car is ready to drive!'; } } @@ -386,7 +404,29 @@ $cat = new Cat; $cat->makeSound(); ``` -Se una classe implementa un'interfaccia, ma non tutti i metodi previsti sono definiti, PHP lancia un errore. Una classe può implementare più interfacce contemporaneamente, a differenza dell'ereditarietà, dove una classe può ereditare solo da una classe. +Se una classe implementa un'interfaccia, ma non tutti i metodi previsti sono definiti, PHP lancia un errore. + +Una classe può implementare più interfacce contemporaneamente, a differenza dell'ereditarietà, dove una classe può ereditare solo da una classe: + +```php +interface Guardian +{ + function guardHouse(); +} + +class Dog implements Animal, Guardian +{ + public function makeSound() + { + echo 'Bark'; + } + + public function guardHouse() + { + echo 'Dog diligently guards the house'; + } +} +``` Classi astratte .[#toc-abstract-classes] @@ -422,6 +462,8 @@ $instance->abstractMethod(); In questo esempio, abbiamo una classe astratta con un metodo regolare e uno astratto. Poi abbiamo una classe `Child` che eredita da `AbstractClass` e fornisce un'implementazione per il metodo astratto. +In cosa differiscono le interfacce e le classi astratte? Le classi astratte possono contenere sia metodi astratti che concreti, mentre le interfacce definiscono solo quali metodi la classe deve implementare, ma non forniscono alcuna implementazione. Una classe può ereditare da una sola classe astratta, ma può implementare un numero qualsiasi di interfacce. + Verifica del tipo .[#toc-type-checking] --------------------------------------- @@ -450,7 +492,7 @@ class Person public function printAge(): void { - echo "This person is " . $this->age . " years old."; + echo "This person is {$this->age} years old."; } } @@ -465,6 +507,21 @@ function printPersonAge(Person $person): void In questo modo, ci assicuriamo che il nostro codice si aspetti e lavori con dati del tipo corretto, aiutandoci a prevenire potenziali errori. +Alcuni tipi non possono essere scritti direttamente in PHP. In questo caso, vengono elencati nel commento phpDoc, che è il formato standard per la documentazione del codice PHP, che inizia con `/**` e termina con `*/`. Esso consente di aggiungere descrizioni di classi, metodi e così via. E anche di elencare tipi complessi usando le cosiddette annotazioni `@var`, `@param` e `@return`. Questi tipi vengono poi utilizzati dagli strumenti di analisi statica del codice, ma non vengono controllati da PHP stesso. + +```php +class Registry +{ + /** @var array indicates that it's an array of Person objects */ + private array $persons = []; + + public function addPerson(Person $person): void + { + $this->persons[] = $person; + } +} +``` + Confronto e identità .[#toc-comparison-and-identity] ---------------------------------------------------- @@ -635,31 +692,47 @@ I tratti consentono di condividere facilmente ed efficacemente il codice tra le Eccezioni --------- -Le eccezioni in OOP consentono di gestire gli errori che possono verificarsi durante l'esecuzione del codice. Sono essenzialmente oggetti progettati per registrare errori o situazioni inaspettate nel programma. +Le eccezioni nell'OOP ci permettono di gestire con grazia gli errori e le situazioni inaspettate nel nostro codice. Sono oggetti che contengono informazioni su un errore o una situazione insolita. -In PHP, per questi oggetti esiste la classe `Exception`. Essa dispone di diversi metodi che consentono di ottenere ulteriori informazioni sull'eccezione, come il messaggio di errore, il file e la riga in cui si è verificato l'errore, ecc. +In PHP, abbiamo una classe incorporata `Exception`, che serve come base per tutte le eccezioni. Questa classe ha diversi metodi che ci permettono di ottenere ulteriori informazioni sull'eccezione, come il messaggio di errore, il file e la riga in cui si è verificato l'errore, ecc. -Quando si verifica un problema, possiamo "lanciare" un'eccezione (usando `throw`). Se vogliamo "catturare" ed elaborare questa eccezione, utilizziamo i blocchi `try` e `catch`. - -Vediamo come funziona: +Quando si verifica un errore nel codice, si può "lanciare" l'eccezione usando la parola chiave `throw`. ```php -try { - throw new Exception('Message explaining the reason for the exception'); +function division(float $a, float $b): float +{ + if ($b === 0) { + throw new Exception('Division by zero!'); + } + return $a / $b; +} +``` - // This code won't execute - echo 'I am a message that nobody will read'; +Quando la funzione `division()` riceve null come secondo argomento, lancia un'eccezione con il messaggio di errore `'Division by zero!'`. Per evitare che il programma si blocchi quando viene lanciata l'eccezione, la intrappoliamo nel blocco `try/catch`: +```php +try { + echo division(10, 0); } catch (Exception $e) { echo 'Exception caught: '. $e->getMessage(); } ``` -È importante notare che un'eccezione può essere lanciata più in profondità, durante la chiamata ad altri metodi. +Il codice che può lanciare un'eccezione viene avvolto in un blocco `try`. Se l'eccezione viene lanciata, l'esecuzione del codice passa a un blocco `catch`, dove è possibile gestire l'eccezione (ad esempio, scrivere un messaggio di errore). -Per un blocco `try`, si possono specificare più blocchi `catch`, se ci si aspetta diversi tipi di eccezioni. +Dopo i blocchi `try` e `catch`, si può aggiungere un blocco opzionale `finally`, che viene sempre eseguito, indipendentemente dal fatto che l'eccezione sia stata lanciata o meno (anche se si utilizzano `return`, `break`, o `continue` nel blocco `try` o `catch` ): + +```php +try { + echo division(10, 0); +} catch (Exception $e) { + echo 'Exception caught: '. $e->getMessage(); +} finally { + // Code that is always executed whether the exception has been thrown or not +} +``` -Si può anche creare una gerarchia di eccezioni, in cui ogni classe di eccezione eredita dalla precedente. A titolo di esempio, si consideri una semplice applicazione bancaria che consente depositi e prelievi: +Possiamo anche creare le nostre classi di eccezioni (gerarchia) che ereditano dalla classe Exception. A titolo di esempio, si consideri una semplice applicazione bancaria che consente depositi e prelievi: ```php class BankingException extends Exception {} @@ -691,7 +764,11 @@ class BankAccount return $this->balance; } } +``` + +È possibile specificare più blocchi `catch` per un singolo blocco `try` se si prevedono diversi tipi di eccezioni. +```php $account = new BankAccount; $account->deposit(500); @@ -709,6 +786,51 @@ try { In questo esempio, è importante notare l'ordine dei blocchi `catch`. Poiché tutte le eccezioni ereditano da `BankingException`, se avessimo questo blocco per primo, tutte le eccezioni verrebbero catturate in esso, senza che il codice raggiunga i successivi blocchi `catch`. Pertanto, è importante che le eccezioni più specifiche (cioè quelle che ereditano da altre) si trovino più in alto nell'ordine dei blocchi `catch` rispetto alle loro eccezioni padre. +Iterazioni .[#toc-iterations] +----------------------------- + +In PHP, è possibile eseguire un ciclo di oggetti utilizzando il ciclo `foreach`, proprio come si fa con un array. Perché funzioni, l'oggetto deve implementare un'interfaccia speciale. + +La prima opzione è implementare l'interfaccia `Iterator`, che ha i metodi `current()` che restituisce il valore corrente, `key()` che restituisce la chiave, `next()` che passa al valore successivo, `rewind()` che passa all'inizio e `valid()` che controlla se siamo già alla fine. + +L'altra opzione è implementare un'interfaccia `IteratorAggregate`, che ha un solo metodo `getIterator()`. Questo metodo può restituire un oggetto segnaposto che fornirà l'attraversamento, oppure può essere un generatore, cioè una funzione speciale che utilizza `yield` per restituire chiavi e valori in sequenza: + +```php +class Person +{ + public function __construct( + public int $age, + ) { + } +} + +class Registry implements IteratorAggregate +{ + private array $people = []; + + public function addPerson(Person $person): void + { + $this->people[] = $person; + } + + public function getIterator(): Generator + { + foreach ($this->people as $person) { + yield $person; + } + } +} + +$list = new Registry; +$list->addPerson(new Person(30)); +$list->addPerson(new Person(25)); + +foreach ($list as $person) { + echo "Age: {$person->age} years\n"; +} +``` + + Migliori pratiche .[#toc-best-practices] ---------------------------------------- diff --git a/nette/pl/introduction-to-object-oriented-programming.texy b/nette/pl/introduction-to-object-oriented-programming.texy index e3d31673e2..2862ba8895 100644 --- a/nette/pl/introduction-to-object-oriented-programming.texy +++ b/nette/pl/introduction-to-object-oriented-programming.texy @@ -52,7 +52,9 @@ $person = new Person(25); echo $person->howOldAreYou(); // Outputs: 25 ``` -W tym przykładzie klasa `Person` ma właściwość `$age` i konstruktor, który ustawia tę właściwość. Metoda `howOldAreYou()` zapewnia następnie dostęp do wieku osoby. +W tym przykładzie klasa `Person` ma właściwość (zmienną) `$age` i konstruktor, który ustawia tę właściwość. Metoda `howOldAreYou()` zapewnia następnie dostęp do wieku osoby. + +Pseudo-zmienna `$this` jest używana wewnątrz klasy w celu uzyskania dostępu do właściwości i metod obiektu. Słowo kluczowe `new` służy do tworzenia nowej instancji klasy. W powyższym przykładzie utworzyliśmy nową osobę w wieku 25 lat. @@ -80,7 +82,7 @@ echo $person->howOldAreYou(); // Outputs: 20 W tym przykładzie, jeśli nie określisz wieku podczas tworzenia obiektu `Person`, zostanie użyta domyślna wartość 20. -Wreszcie, definicję właściwości z jej inicjalizacją za pomocą konstruktora można skrócić i uprościć w następujący sposób: +Fajną rzeczą jest to, że definicję właściwości z jej inicjalizacją za pomocą konstruktora można skrócić i uprościć w następujący sposób: ```php class Person @@ -92,6 +94,8 @@ class Person } ``` +Dla kompletności, oprócz konstruktorów, obiekty mogą mieć destruktory (metoda `__destruct`), które są wywoływane przed zwolnieniem obiektu z pamięci. + Przestrzenie nazw .[#toc-namespaces] ------------------------------------ @@ -152,9 +156,9 @@ class Person $this->age = $age; } - function howOldAreYou() + function printInformation() { - return $this->age; + echo "Age: {$this->age} years\n"; } } @@ -170,8 +174,8 @@ class Student extends Person function printInformation() { - echo 'Age of student: ', $this->howOldAreYou(); - echo 'Field of study: ', $this->fieldOfStudy; + parent::printInformation(); + echo "Field of study: {$this->fieldOfStudy} \n"; } } @@ -183,12 +187,26 @@ Jak działa ten kod? - Użyliśmy słowa kluczowego `extends`, aby rozszerzyć klasę `Person`, co oznacza, że klasa `Student` dziedziczy wszystkie metody i właściwości z `Person`. -- Słowo kluczowe `parent::` pozwala nam wywoływać metody z klasy nadrzędnej. W tym przypadku wywołaliśmy konstruktor z klasy `Person` przed dodaniem naszej własnej funkcjonalności do klasy `Student`. +- Słowo kluczowe `parent::` pozwala nam wywoływać metody z klasy nadrzędnej. W tym przypadku wywołaliśmy konstruktor z klasy `Person` przed dodaniem naszej własnej funkcjonalności do klasy `Student`. I podobnie, metodę przodka `printInformation()` przed wyświetleniem informacji o uczniu. Dziedziczenie jest przeznaczone dla sytuacji, w których istnieje relacja "is a" między klasami. Na przykład, klasa `Student` jest klasą `Person`. Kot jest zwierzęciem. Pozwala nam to w przypadkach, w których oczekujemy jednego obiektu (np. "Osoba") w kodzie na użycie obiektu pochodnego (np. "Student"). Ważne jest, aby zdać sobie sprawę, że głównym celem dziedziczenia **nie jest** zapobieganie powielaniu kodu. Wręcz przeciwnie, niewłaściwe wykorzystanie dziedziczenia może prowadzić do skomplikowanego i trudnego w utrzymaniu kodu. Jeśli między klasami nie ma relacji "is a", powinniśmy rozważyć kompozycję zamiast dziedziczenia. +Należy zauważyć, że metody `printInformation()` w klasach `Person` i `Student` wyświetlają nieco inne informacje. Możemy też dodać inne klasy (takie jak `Employee`), które zapewnią inne implementacje tej metody. Zdolność obiektów różnych klas do reagowania na tę samą metodę na różne sposoby nazywana jest polimorfizmem: + +```php +$people = [ + new Person(30), + new Student(20, 'Computer Science'), + new Employee(45, 'Director'), +]; + +foreach ($people as $person) { + $person->printInformation(); +} +``` + Kompozycja .[#toc-composition] ------------------------------ @@ -202,7 +220,7 @@ class Engine { function start() { - echo "Engine is running."; + echo 'Engine is running.'; } } @@ -218,7 +236,7 @@ class Car function start() { $this->engine->start(); - echo "The car is ready to drive!"; + echo 'The car is ready to drive!'; } } @@ -386,7 +404,29 @@ $cat = new Cat; $cat->makeSound(); ``` -Jeśli klasa implementuje interfejs, ale nie wszystkie oczekiwane metody są zdefiniowane, PHP zgłosi błąd. Klasa może implementować wiele interfejsów jednocześnie, co różni się od dziedziczenia, gdzie klasa może dziedziczyć tylko z jednej klasy. +Jeśli klasa implementuje interfejs, ale nie wszystkie oczekiwane metody są zdefiniowane, PHP zgłosi błąd. + +Klasa może implementować wiele interfejsów jednocześnie, co różni się od dziedziczenia, gdzie klasa może dziedziczyć tylko z jednej klasy: + +```php +interface Guardian +{ + function guardHouse(); +} + +class Dog implements Animal, Guardian +{ + public function makeSound() + { + echo 'Bark'; + } + + public function guardHouse() + { + echo 'Dog diligently guards the house'; + } +} +``` Klasy abstrakcyjne .[#toc-abstract-classes] @@ -422,6 +462,8 @@ $instance->abstractMethod(); W tym przykładzie mamy klasę abstrakcyjną z jedną zwykłą i jedną abstrakcyjną metodą. Następnie mamy klasę `Child`, która dziedziczy po `AbstractClass` i zapewnia implementację metody abstrakcyjnej. +Czym różnią się interfejsy od klas abstrakcyjnych? Klasy abstrakcyjne mogą zawierać zarówno metody abstrakcyjne, jak i konkretne, podczas gdy interfejsy definiują tylko metody, które klasa musi zaimplementować, ale nie zapewniają implementacji. Klasa może dziedziczyć tylko z jednej klasy abstrakcyjnej, ale może implementować dowolną liczbę interfejsów. + Sprawdzanie typu .[#toc-type-checking] -------------------------------------- @@ -450,7 +492,7 @@ class Person public function printAge(): void { - echo "This person is " . $this->age . " years old."; + echo "This person is {$this->age} years old."; } } @@ -465,6 +507,21 @@ function printPersonAge(Person $person): void W ten sposób upewniamy się, że nasz kod oczekuje i działa z danymi odpowiedniego typu, pomagając nam zapobiegać potencjalnym błędom. +Niektóre typy nie mogą być zapisane bezpośrednio w PHP. W takim przypadku są one wymienione w komentarzu phpDoc, który jest standardowym formatem dokumentowania kodu PHP, zaczynając od `/**` i kończąc na `*/`. Pozwala on na dodawanie opisów klas, metod itp. A także wylistować złożone typy za pomocą tak zwanych adnotacji `@var`, `@param` i `@return`. Typy te są następnie wykorzystywane przez narzędzia do statycznej analizy kodu, ale nie są sprawdzane przez sam PHP. + +```php +class Registry +{ + /** @var array indicates that it's an array of Person objects */ + private array $persons = []; + + public function addPerson(Person $person): void + { + $this->persons[] = $person; + } +} +``` + Porównanie i tożsamość .[#toc-comparison-and-identity] ------------------------------------------------------ @@ -635,31 +692,47 @@ Cechy pozwalają na łatwe i efektywne współdzielenie kodu pomiędzy klasami. Wyjątki ------- -Wyjątki w OOP pozwalają nam obsługiwać i zarządzać błędami, które mogą pojawić się podczas wykonywania naszego kodu. Zasadniczo są to obiekty zaprojektowane do rejestrowania błędów lub nieoczekiwanych sytuacji w programie. - -W PHP mamy wbudowaną klasę `Exception` dla tych obiektów. Posiada ona kilka metod, które pozwalają nam uzyskać więcej informacji o wyjątku, takich jak komunikat o błędzie, plik i wiersz, w którym wystąpił błąd itp. +Wyjątki w OOP pozwalają nam z wdziękiem obsługiwać błędy i nieoczekiwane sytuacje w naszym kodzie. Są to obiekty, które przenoszą informacje o błędzie lub nietypowej sytuacji. -Kiedy pojawia się problem, możemy "rzucić" wyjątek (używając `throw`). Jeśli chcemy "złapać" i przetworzyć ten wyjątek, używamy bloków `try` i `catch`. +W PHP mamy wbudowaną klasę `Exception`, która służy jako podstawa dla wszystkich wyjątków. Ma ona kilka metod, które pozwalają nam uzyskać więcej informacji o wyjątku, takich jak komunikat o błędzie, plik i linia, w której wystąpił błąd itp. -Zobaczmy, jak to działa: +Gdy w kodzie wystąpi błąd, możemy "rzucić" wyjątek za pomocą słowa kluczowego `throw`. ```php -try { - throw new Exception('Message explaining the reason for the exception'); +function division(float $a, float $b): float +{ + if ($b === 0) { + throw new Exception('Division by zero!'); + } + return $a / $b; +} +``` - // This code won't execute - echo 'I am a message that nobody will read'; +Gdy funkcja `division()` otrzyma null jako drugi argument, rzuca wyjątek z komunikatem o błędzie `'Division by zero!'`. Aby zapobiec awarii programu, gdy wyjątek zostanie rzucony, uwięzimy go w bloku `try/catch`: +```php +try { + echo division(10, 0); } catch (Exception $e) { echo 'Exception caught: '. $e->getMessage(); } ``` -Ważne jest, aby pamiętać, że wyjątek może zostać rzucony głębiej, podczas wywoływania innych metod. +Kod, który może rzucić wyjątek, jest zawijany w blok `try`. Jeśli wyjątek zostanie rzucony, wykonanie kodu przenosi się do bloku `catch`, gdzie możemy obsłużyć wyjątek (np. napisać komunikat o błędzie). + +Po blokach `try` i `catch` możemy dodać opcjonalny blok `finally`, który jest zawsze wykonywany niezależnie od tego, czy wyjątek został rzucony, czy nie (nawet jeśli użyjemy `return`, `break` lub `continue` w bloku `try` lub `catch` ): -Dla jednego bloku `try` można określić wiele bloków `catch`, jeśli spodziewane są różne typy wyjątków. +```php +try { + echo division(10, 0); +} catch (Exception $e) { + echo 'Exception caught: '. $e->getMessage(); +} finally { + // Code that is always executed whether the exception has been thrown or not +} +``` -Możemy również utworzyć hierarchię wyjątków, w której każda klasa wyjątków dziedziczy po poprzedniej. Jako przykład rozważmy prostą aplikację bankową, która umożliwia wpłaty i wypłaty: +Możemy również tworzyć własne klasy wyjątków (hierarchie), które dziedziczą po klasie Exception. Jako przykład rozważmy prostą aplikację bankową, która umożliwia wpłaty i wypłaty: ```php class BankingException extends Exception {} @@ -691,7 +764,11 @@ class BankAccount return $this->balance; } } +``` + +Można określić wiele bloków `catch` dla pojedynczego bloku `try`, jeśli spodziewane są różne typy wyjątków. +```php $account = new BankAccount; $account->deposit(500); @@ -709,6 +786,51 @@ try { W tym przykładzie ważne jest, aby zwrócić uwagę na kolejność bloków `catch`. Ponieważ wszystkie wyjątki dziedziczą z `BankingException`, gdybyśmy mieli ten blok jako pierwszy, wszystkie wyjątki zostałyby w nim przechwycone, a kod nie dotarłby do kolejnych bloków `catch`. Dlatego ważne jest, aby bardziej specyficzne wyjątki (tj. te, które dziedziczą po innych) znajdowały się wyżej w kolejności bloków `catch` niż ich wyjątki nadrzędne. +Iteracje .[#toc-iterations] +--------------------------- + +W PHP można przechodzić przez obiekty za pomocą pętli `foreach`, podobnie jak przez tablice. Aby to działało, obiekt musi implementować specjalny interfejs. + +Pierwszą opcją jest zaimplementowanie interfejsu `Iterator`, który ma metody `current()` zwracające bieżącą wartość, `key()` zwracające klucz, `next()` przechodzące do następnej wartości, `rewind()` przechodzące do początku i `valid()` sprawdzające, czy jesteśmy już na końcu. + +Inną opcją jest zaimplementowanie interfejsu `IteratorAggregate`, który ma tylko jedną metodę `getIterator()`. Zwraca ona albo obiekt zastępczy, który zapewni przechodzenie, albo może być generatorem, który jest specjalną funkcją, która używa `yield` do sekwencyjnego zwracania kluczy i wartości: + +```php +class Person +{ + public function __construct( + public int $age, + ) { + } +} + +class Registry implements IteratorAggregate +{ + private array $people = []; + + public function addPerson(Person $person): void + { + $this->people[] = $person; + } + + public function getIterator(): Generator + { + foreach ($this->people as $person) { + yield $person; + } + } +} + +$list = new Registry; +$list->addPerson(new Person(30)); +$list->addPerson(new Person(25)); + +foreach ($list as $person) { + echo "Age: {$person->age} years\n"; +} +``` + + Najlepsze praktyki .[#toc-best-practices] ----------------------------------------- diff --git a/nette/pt/introduction-to-object-oriented-programming.texy b/nette/pt/introduction-to-object-oriented-programming.texy index 41c4ffb88f..f5a70b6a5f 100644 --- a/nette/pt/introduction-to-object-oriented-programming.texy +++ b/nette/pt/introduction-to-object-oriented-programming.texy @@ -52,7 +52,9 @@ $person = new Person(25); echo $person->howOldAreYou(); // Outputs: 25 ``` -Neste exemplo, a classe `Person` tem uma propriedade `$age` e um construtor que define essa propriedade. O método `howOldAreYou()` fornece acesso à idade da pessoa. +Neste exemplo, a classe `Person` tem uma propriedade (variável) `$age` e um construtor que define essa propriedade. O método `howOldAreYou()` fornece acesso à idade da pessoa. + +A pseudovariável `$this` é usada dentro da classe para acessar as propriedades e os métodos do objeto. A palavra-chave `new` é usada para criar uma nova instância de uma classe. No exemplo acima, criamos uma nova pessoa com 25 anos. @@ -80,7 +82,7 @@ echo $person->howOldAreYou(); // Outputs: 20 Neste exemplo, se você não especificar uma idade ao criar um objeto `Person`, o valor padrão de 20 será usado. -Por fim, a definição da propriedade com sua inicialização por meio do construtor pode ser encurtada e simplificada da seguinte forma: +O bom é que a definição da propriedade com sua inicialização por meio do construtor pode ser encurtada e simplificada da seguinte forma: ```php class Person @@ -92,6 +94,8 @@ class Person } ``` +Para ser mais completo, além dos construtores, os objetos podem ter destrutores (método `__destruct`) que são chamados antes de o objeto ser liberado da memória. + Namespaces .[#toc-namespaces] ----------------------------- @@ -152,9 +156,9 @@ class Person $this->age = $age; } - function howOldAreYou() + function printInformation() { - return $this->age; + echo "Age: {$this->age} years\n"; } } @@ -170,8 +174,8 @@ class Student extends Person function printInformation() { - echo 'Age of student: ', $this->howOldAreYou(); - echo 'Field of study: ', $this->fieldOfStudy; + parent::printInformation(); + echo "Field of study: {$this->fieldOfStudy} \n"; } } @@ -183,12 +187,26 @@ Como esse código funciona? - Usamos a palavra-chave `extends` para estender a classe `Person`, o que significa que a classe `Student` herda todos os métodos e propriedades de `Person`. -- A palavra-chave `parent::` nos permite chamar métodos da classe pai. Nesse caso, chamamos o construtor da classe `Person` antes de adicionar nossa própria funcionalidade à classe `Student`. +- A palavra-chave `parent::` nos permite chamar métodos da classe principal. Nesse caso, chamamos o construtor da classe `Person` antes de adicionar nossa própria funcionalidade à classe `Student`. E, da mesma forma, o método ancestral `printInformation()` antes de listar as informações do aluno. A herança é destinada a situações em que há um relacionamento "é um" entre as classes. Por exemplo, um `Student` é um `Person`. Um gato é um animal. Ela nos permite, nos casos em que esperamos um objeto (por exemplo, "Person") no código, usar um objeto derivado (por exemplo, "Student"). É essencial perceber que o objetivo principal da herança **não** é evitar a duplicação de código. Pelo contrário, o uso incorreto da herança pode levar a um código complexo e de difícil manutenção. Se não houver uma relação "é um" entre as classes, devemos considerar a composição em vez da herança. +Observe que os métodos `printInformation()` nas classes `Person` e `Student` produzem informações ligeiramente diferentes. E podemos adicionar outras classes (como `Employee`) que fornecerão outras implementações desse método. A capacidade de objetos de classes diferentes responderem ao mesmo método de maneiras diferentes é chamada de polimorfismo: + +```php +$people = [ + new Person(30), + new Student(20, 'Computer Science'), + new Employee(45, 'Director'), +]; + +foreach ($people as $person) { + $person->printInformation(); +} +``` + Composição .[#toc-composition] ------------------------------ @@ -202,7 +220,7 @@ class Engine { function start() { - echo "Engine is running."; + echo 'Engine is running.'; } } @@ -218,7 +236,7 @@ class Car function start() { $this->engine->start(); - echo "The car is ready to drive!"; + echo 'The car is ready to drive!'; } } @@ -386,7 +404,29 @@ $cat = new Cat; $cat->makeSound(); ``` -Se uma classe implementar uma interface, mas nem todos os métodos esperados estiverem definidos, o PHP lançará um erro. Uma classe pode implementar várias interfaces de uma vez, o que é diferente da herança, em que uma classe só pode herdar de uma classe. +Se uma classe implementar uma interface, mas nem todos os métodos esperados estiverem definidos, o PHP lançará um erro. + +Uma classe pode implementar várias interfaces de uma vez, o que é diferente da herança, em que uma classe só pode herdar de uma classe: + +```php +interface Guardian +{ + function guardHouse(); +} + +class Dog implements Animal, Guardian +{ + public function makeSound() + { + echo 'Bark'; + } + + public function guardHouse() + { + echo 'Dog diligently guards the house'; + } +} +``` Classes abstratas .[#toc-abstract-classes] @@ -422,6 +462,8 @@ $instance->abstractMethod(); Neste exemplo, temos uma classe abstrata com um método regular e um método abstrato. Em seguida, temos uma classe `Child` que herda de `AbstractClass` e fornece uma implementação para o método abstrato. +Qual é a diferença entre interfaces e classes abstratas? As classes abstratas podem conter métodos abstratos e concretos, enquanto as interfaces definem apenas os métodos que a classe deve implementar, mas não fornecem nenhuma implementação. Uma classe pode herdar de apenas uma classe abstrata, mas pode implementar qualquer número de interfaces. + Verificação de tipo .[#toc-type-checking] ----------------------------------------- @@ -450,7 +492,7 @@ class Person public function printAge(): void { - echo "This person is " . $this->age . " years old."; + echo "This person is {$this->age} years old."; } } @@ -465,6 +507,21 @@ function printPersonAge(Person $person): void Dessa forma, garantimos que nosso código espera e trabalha com dados do tipo correto, o que nos ajuda a evitar possíveis erros. +Alguns tipos não podem ser escritos diretamente no PHP. Nesse caso, eles são listados no comentário phpDoc, que é o formato padrão para documentar o código PHP, começando com `/**` e terminando com `*/`. Ele permite que você adicione descrições de classes, métodos e assim por diante. E também para listar tipos complexos usando as chamadas anotações `@var`, `@param` e `@return`. Esses tipos são usados por ferramentas de análise de código estático, mas não são verificados pelo próprio PHP. + +```php +class Registry +{ + /** @var array indicates that it's an array of Person objects */ + private array $persons = []; + + public function addPerson(Person $person): void + { + $this->persons[] = $person; + } +} +``` + Comparação e identidade .[#toc-comparison-and-identity] ------------------------------------------------------- @@ -635,31 +692,47 @@ As características permitem o compartilhamento fácil e eficiente de código en Exceções -------- -As exceções em OOP nos permitem tratar e gerenciar erros que possam surgir durante a execução do nosso código. Basicamente, elas são objetos projetados para registrar erros ou situações inesperadas no programa. - -No PHP, temos a classe `Exception` integrada para esses objetos. Ela tem vários métodos que nos permitem obter mais informações sobre a exceção, como a mensagem de erro, o arquivo e a linha em que o erro ocorreu etc. +As exceções na OOP nos permitem lidar com erros e situações inesperadas em nosso código. Elas são objetos que contêm informações sobre um erro ou uma situação incomum. -Quando surge um problema, podemos "lançar" uma exceção (usando `throw`). Se quisermos "capturar" e processar essa exceção, usaremos os blocos `try` e `catch`. +No PHP, temos uma classe interna `Exception`, que serve de base para todas as exceções. Ela tem vários métodos que nos permitem obter mais informações sobre a exceção, como a mensagem de erro, o arquivo e a linha em que o erro ocorreu etc. -Vamos ver como isso funciona: +Quando ocorre um erro no código, podemos "lançar" a exceção usando a palavra-chave `throw`. ```php -try { - throw new Exception('Message explaining the reason for the exception'); +function division(float $a, float $b): float +{ + if ($b === 0) { + throw new Exception('Division by zero!'); + } + return $a / $b; +} +``` - // This code won't execute - echo 'I am a message that nobody will read'; +Quando a função `division()` recebe null como seu segundo argumento, ela lança uma exceção com a mensagem de erro `'Division by zero!'`. Para evitar que o programa seja interrompido quando a exceção for lançada, nós a capturamos no bloco `try/catch`: +```php +try { + echo division(10, 0); } catch (Exception $e) { echo 'Exception caught: '. $e->getMessage(); } ``` -É importante observar que uma exceção pode ser lançada mais profundamente, durante a chamada para outros métodos. +O código que pode lançar uma exceção é envolvido em um bloco `try`. Se a exceção for lançada, a execução do código será movida para um bloco `catch`, onde poderemos tratar a exceção (por exemplo, escrever uma mensagem de erro). + +Após os blocos `try` e `catch`, podemos adicionar um bloco opcional `finally`, que é sempre executado, independentemente de a exceção ter sido lançada ou não (mesmo se usarmos `return`, `break` ou `continue` no bloco `try` ou `catch` ): -Para um bloco `try`, vários blocos `catch` podem ser especificados se você espera diferentes tipos de exceções. +```php +try { + echo division(10, 0); +} catch (Exception $e) { + echo 'Exception caught: '. $e->getMessage(); +} finally { + // Code that is always executed whether the exception has been thrown or not +} +``` -Também podemos criar uma hierarquia de exceções, em que cada classe de exceção herda da anterior. Como exemplo, considere um aplicativo bancário simples que permite depósitos e saques: +Também podemos criar nossas próprias classes de exceção (hierarquia) que herdam da classe Exception. Como exemplo, considere um aplicativo bancário simples que permite depósitos e saques: ```php class BankingException extends Exception {} @@ -691,7 +764,11 @@ class BankAccount return $this->balance; } } +``` + +Vários blocos `catch` podem ser especificados para um único bloco `try` se você espera diferentes tipos de exceções. +```php $account = new BankAccount; $account->deposit(500); @@ -709,6 +786,51 @@ try { Nesse exemplo, é importante observar a ordem dos blocos `catch`. Como todas as exceções são herdadas de `BankingException`, se tivéssemos esse bloco primeiro, todas as exceções seriam capturadas nele sem que o código chegasse aos blocos `catch` subsequentes. Portanto, é importante que as exceções mais específicas (ou seja, aquelas que herdam de outras) estejam em uma posição mais alta na ordem do bloco `catch` do que suas exceções pai. +Iterações .[#toc-iterations] +---------------------------- + +No PHP, você pode percorrer objetos usando o loop `foreach`, da mesma forma que percorre uma matriz. Para que isso funcione, o objeto deve implementar uma interface especial. + +A primeira opção é implementar a interface `Iterator`, que tem os métodos `current()` que retorna o valor atual, `key()` que retorna a chave, `next()` que passa para o próximo valor, `rewind()` que passa para o início e `valid()` que verifica se já estamos no final. + +A outra opção é implementar uma interface `IteratorAggregate`, que tem apenas um método `getIterator()`. Ele retorna um objeto de espaço reservado que fornecerá a passagem ou pode ser um gerador, que é uma função especial que usa `yield` para retornar chaves e valores sequencialmente: + +```php +class Person +{ + public function __construct( + public int $age, + ) { + } +} + +class Registry implements IteratorAggregate +{ + private array $people = []; + + public function addPerson(Person $person): void + { + $this->people[] = $person; + } + + public function getIterator(): Generator + { + foreach ($this->people as $person) { + yield $person; + } + } +} + +$list = new Registry; +$list->addPerson(new Person(30)); +$list->addPerson(new Person(25)); + +foreach ($list as $person) { + echo "Age: {$person->age} years\n"; +} +``` + + Melhores práticas .[#toc-best-practices] ---------------------------------------- diff --git a/nette/ro/introduction-to-object-oriented-programming.texy b/nette/ro/introduction-to-object-oriented-programming.texy index 8fb5e33237..f8cb3c4f75 100644 --- a/nette/ro/introduction-to-object-oriented-programming.texy +++ b/nette/ro/introduction-to-object-oriented-programming.texy @@ -52,7 +52,9 @@ $person = new Person(25); echo $person->howOldAreYou(); // Outputs: 25 ``` -În acest exemplu, clasa `Person` are o proprietate `$age` și un constructor care stabilește această proprietate. Metoda `howOldAreYou()` oferă apoi acces la vârsta persoanei. +În acest exemplu, clasa `Person` are o proprietate (variabilă) `$age` și un constructor care stabilește această proprietate. Metoda `howOldAreYou()` oferă apoi acces la vârsta persoanei. + +Pseudo-variabila `$this` este utilizată în interiorul clasei pentru a accesa proprietățile și metodele obiectului. Cuvântul cheie `new` este utilizat pentru a crea o nouă instanță a unei clase. În exemplul de mai sus, am creat o nouă persoană în vârstă de 25 de ani. @@ -80,7 +82,7 @@ echo $person->howOldAreYou(); // Outputs: 20 În acest exemplu, dacă nu se specifică o vârstă la crearea unui obiect `Person`, se va utiliza valoarea implicită de 20 de ani. -În cele din urmă, definirea proprietății cu inițializarea acesteia prin intermediul constructorului poate fi scurtată și simplificată astfel: +Lucrul bun este că definiția proprietății cu inițializarea acesteia prin intermediul constructorului poate fi scurtată și simplificată astfel: ```php class Person @@ -92,6 +94,8 @@ class Person } ``` +Pentru a fi complet, pe lângă constructori, obiectele pot avea și destructori (metoda `__destruct`) care sunt apelați înainte ca obiectul să fie eliberat din memorie. + Spații de nume .[#toc-namespaces] --------------------------------- @@ -152,9 +156,9 @@ class Person $this->age = $age; } - function howOldAreYou() + function printInformation() { - return $this->age; + echo "Age: {$this->age} years\n"; } } @@ -170,8 +174,8 @@ class Student extends Person function printInformation() { - echo 'Age of student: ', $this->howOldAreYou(); - echo 'Field of study: ', $this->fieldOfStudy; + parent::printInformation(); + echo "Field of study: {$this->fieldOfStudy} \n"; } } @@ -183,12 +187,26 @@ Cum funcționează acest cod? - Am folosit cuvântul cheie `extends` pentru a extinde clasa `Person`, ceea ce înseamnă că clasa `Student` moștenește toate metodele și proprietățile de la `Person`. -- Cuvântul cheie `parent::` ne permite să apelăm metode din clasa părinte. În acest caz, am apelat constructorul din clasa `Person` înainte de a adăuga propria noastră funcționalitate la clasa `Student`. +- Cuvântul cheie `parent::` ne permite să apelăm metode din clasa părinte. În acest caz, am apelat constructorul din clasa `Person` înainte de a adăuga propria noastră funcționalitate la clasa `Student`. Și, în mod similar, metoda strămoșului `printInformation()` înainte de a lista informațiile despre elev. Moștenirea este destinată situațiilor în care există o relație "este o" între clase. De exemplu, un `Student` este un `Person`. O pisică este un animal. Ne permite ca în cazurile în care ne așteptăm ca un obiect (de exemplu, "Persoană") din cod să folosim în schimb un obiect derivat (de exemplu, "Student"). Este esențial să ne dăm seama că scopul principal al moștenirii **nu este** acela de a preveni duplicarea codului. Dimpotrivă, utilizarea greșită a moștenirii poate duce la un cod complex și greu de întreținut. În cazul în care nu există o relație "este un" între clase, ar trebui să luăm în considerare compoziția în locul moștenirii. +Rețineți că metodele `printInformation()` din clasele `Person` și `Student` furnizează informații ușor diferite. Și putem adăuga alte clase (cum ar fi `Employee`) care vor furniza alte implementări ale acestei metode. Capacitatea obiectelor din clase diferite de a răspunde la aceeași metodă în moduri diferite se numește polimorfism: + +```php +$people = [ + new Person(30), + new Student(20, 'Computer Science'), + new Employee(45, 'Director'), +]; + +foreach ($people as $person) { + $person->printInformation(); +} +``` + Compoziția .[#toc-composition] ------------------------------ @@ -202,7 +220,7 @@ class Engine { function start() { - echo "Engine is running."; + echo 'Engine is running.'; } } @@ -218,7 +236,7 @@ class Car function start() { $this->engine->start(); - echo "The car is ready to drive!"; + echo 'The car is ready to drive!'; } } @@ -386,7 +404,29 @@ $cat = new Cat; $cat->makeSound(); ``` -În cazul în care o clasă implementează o interfață, dar nu sunt definite toate metodele așteptate, PHP va genera o eroare. O clasă poate implementa mai multe interfețe în același timp, ceea ce este diferit de moștenire, unde o clasă poate moșteni doar de la o singură clasă. +În cazul în care o clasă implementează o interfață, dar nu sunt definite toate metodele așteptate, PHP va genera o eroare. + +O clasă poate implementa mai multe interfețe în același timp, ceea ce este diferit de moștenire, unde o clasă poate moșteni doar de la o singură clasă: + +```php +interface Guardian +{ + function guardHouse(); +} + +class Dog implements Animal, Guardian +{ + public function makeSound() + { + echo 'Bark'; + } + + public function guardHouse() + { + echo 'Dog diligently guards the house'; + } +} +``` Clase abstracte .[#toc-abstract-classes] @@ -422,6 +462,8 @@ $instance->abstractMethod(); În acest exemplu, avem o clasă abstractă cu o metodă obișnuită și una abstractă. Apoi avem o clasă `Child` care moștenește din `AbstractClass` și oferă o implementare pentru metoda abstractă. +Prin ce se deosebesc interfețele și clasele abstracte? Clasele abstracte pot conține atât metode abstracte, cât și metode concrete, în timp ce interfețele definesc doar metodele pe care clasa trebuie să le implementeze, dar nu oferă nicio implementare. O clasă poate moșteni dintr-o singură clasă abstractă, dar poate implementa un număr nelimitat de interfețe. + Verificarea tipurilor .[#toc-type-checking] ------------------------------------------- @@ -450,7 +492,7 @@ class Person public function printAge(): void { - echo "This person is " . $this->age . " years old."; + echo "This person is {$this->age} years old."; } } @@ -465,6 +507,21 @@ function printPersonAge(Person $person): void În acest fel, ne asigurăm că codul nostru așteaptă și lucrează cu date de tipul corect, ceea ce ne ajută să prevenim eventualele erori. +Unele tipuri nu pot fi scrise direct în PHP. În acest caz, ele sunt listate în comentariul phpDoc, care este formatul standard pentru documentarea codului PHP, începând cu `/**` și terminând cu `*/`. Acesta vă permite să adăugați descrieri ale claselor, metodelor și așa mai departe. Și, de asemenea, de a enumera tipurile complexe folosind așa-numitele adnotări `@var`, `@param` și `@return`. Aceste tipuri sunt apoi utilizate de instrumentele de analiză statică a codului, dar nu sunt verificate de PHP însuși. + +```php +class Registry +{ + /** @var array indicates that it's an array of Person objects */ + private array $persons = []; + + public function addPerson(Person $person): void + { + $this->persons[] = $person; + } +} +``` + Comparație și identitate .[#toc-comparison-and-identity] -------------------------------------------------------- @@ -635,31 +692,47 @@ Trăsăturile vă permit să partajați ușor și eficient codul între clase. E Excepții -------- -Excepțiile în OOP ne permit să gestionăm și să tratăm erorile care pot apărea în timpul execuției codului nostru. Ele sunt, în esență, obiecte concepute pentru a înregistra erorile sau situațiile neașteptate din programul dumneavoastră. - -În PHP, avem clasa integrată `Exception` pentru aceste obiecte. Aceasta are mai multe metode care ne permit să obținem mai multe informații despre excepție, cum ar fi mesajul de eroare, fișierul și linia în care a apărut eroarea etc. +Excepțiile din OOP ne permit să gestionăm cu grație erorile și situațiile neașteptate din codul nostru. Acestea sunt obiecte care conțin informații despre o eroare sau o situație neobișnuită. -Atunci când apare o problemă, putem "arunca" o excepție (folosind `throw`). Dacă dorim să "capturăm" și să procesăm această excepție, folosim blocurile `try` și `catch`. +În PHP, avem o clasă încorporată `Exception`, care servește drept bază pentru toate excepțiile. Aceasta are mai multe metode care ne permit să obținem mai multe informații despre excepție, cum ar fi mesajul de eroare, fișierul și linia în care a apărut eroarea etc. -Să vedem cum funcționează: +Atunci când apare o eroare în cod, putem "arunca" excepția folosind cuvântul cheie `throw`. ```php -try { - throw new Exception('Message explaining the reason for the exception'); +function division(float $a, float $b): float +{ + if ($b === 0) { + throw new Exception('Division by zero!'); + } + return $a / $b; +} +``` - // This code won't execute - echo 'I am a message that nobody will read'; +Atunci când funcția `division()` primește null ca al doilea argument, se aruncă o excepție cu mesajul de eroare `'Division by zero!'`. Pentru a preveni blocarea programului atunci când este lansată excepția, o blocăm în blocul `try/catch`: +```php +try { + echo division(10, 0); } catch (Exception $e) { echo 'Exception caught: '. $e->getMessage(); } ``` -Este important să rețineți că o excepție poate fi aruncată mai adânc, în timpul apelării altor metode. +Codul care poate arunca o excepție este inclus într-un bloc `try`. În cazul în care excepția este lansată, execuția codului se mută într-un bloc `catch`, unde putem gestiona excepția (de exemplu, scriind un mesaj de eroare). + +După blocurile `try` și `catch`, putem adăuga un bloc opțional `finally`, care este întotdeauna executat, indiferent dacă excepția a fost sau nu lansată (chiar dacă folosim `return`, `break` sau `continue` în blocul `try` sau `catch` ): -Pentru un singur bloc `try`, pot fi specificate mai multe blocuri `catch` dacă vă așteptați la diferite tipuri de excepții. +```php +try { + echo division(10, 0); +} catch (Exception $e) { + echo 'Exception caught: '. $e->getMessage(); +} finally { + // Code that is always executed whether the exception has been thrown or not +} +``` -De asemenea, putem crea o ierarhie a excepțiilor, în care fiecare clasă de excepții moștenește din cea anterioară. Ca exemplu, să luăm în considerare o aplicație bancară simplă care permite depuneri și retrageri: +Putem, de asemenea, să ne creăm propriile clase de excepții (ierarhie) care moștenesc din clasa Exception. Ca exemplu, să considerăm o aplicație bancară simplă care permite depuneri și retrageri: ```php class BankingException extends Exception {} @@ -691,7 +764,11 @@ class BankAccount return $this->balance; } } +``` + +Se pot specifica mai multe blocuri `catch` pentru un singur bloc `try` dacă se așteaptă diferite tipuri de excepții. +```php $account = new BankAccount; $account->deposit(500); @@ -709,6 +786,51 @@ try { În acest exemplu, este important să rețineți ordinea blocurilor `catch`. Deoarece toate excepțiile moștenesc de la `BankingException`, dacă am avea acest bloc primul, toate excepțiile ar fi prinse în el fără ca codul să ajungă la blocurile `catch` ulterioare. Prin urmare, este important ca excepțiile mai specifice (adică cele care moștenesc de la altele) să fie mai sus în ordinea blocului `catch` decât excepțiile părinte. +Iterații .[#toc-iterations] +--------------------------- + +În PHP, puteți parcurge obiectele în buclă folosind bucla `foreach`, la fel cum parcurgeți o matrice. Pentru ca acest lucru să funcționeze, obiectul trebuie să implementeze o interfață specială. + +Prima opțiune este să implementați interfața `Iterator`, care are metodele `current()` care returnează valoarea curentă, `key()` care returnează cheia, `next()` care trece la următoarea valoare, `rewind()` care trece la început și `valid()` care verifică dacă am ajuns deja la sfârșit. + +Cealaltă opțiune este să implementăm o interfață `IteratorAggregate`, care are o singură metodă `getIterator()`. Aceasta fie returnează un obiect de tip "placeholder" care va furniza traversarea, fie poate fi un generator, care este o funcție specială care utilizează `yield` pentru a returna chei și valori în mod secvențial: + +```php +class Person +{ + public function __construct( + public int $age, + ) { + } +} + +class Registry implements IteratorAggregate +{ + private array $people = []; + + public function addPerson(Person $person): void + { + $this->people[] = $person; + } + + public function getIterator(): Generator + { + foreach ($this->people as $person) { + yield $person; + } + } +} + +$list = new Registry; +$list->addPerson(new Person(30)); +$list->addPerson(new Person(25)); + +foreach ($list as $person) { + echo "Age: {$person->age} years\n"; +} +``` + + Cele mai bune practici .[#toc-best-practices] --------------------------------------------- diff --git a/nette/ru/introduction-to-object-oriented-programming.texy b/nette/ru/introduction-to-object-oriented-programming.texy index d79be5714a..a8ab9c61e5 100644 --- a/nette/ru/introduction-to-object-oriented-programming.texy +++ b/nette/ru/introduction-to-object-oriented-programming.texy @@ -52,7 +52,9 @@ $person = new Person(25); echo $person->howOldAreYou(); // Outputs: 25 ``` -В данном примере класс `Person` имеет свойство `$age` и конструктор, который устанавливает это свойство. Затем метод `howOldAreYou()` предоставляет доступ к возрасту человека. +В данном примере класс `Person` имеет свойство (переменную) `$age` и конструктор, который устанавливает это свойство. Затем метод `howOldAreYou()` предоставляет доступ к возрасту человека. + +Псевдопеременная `$this` используется внутри класса для доступа к свойствам и методам объекта. Ключевое слово `new` используется для создания нового экземпляра класса. В приведенном примере мы создали нового человека в возрасте 25 лет. @@ -80,7 +82,7 @@ echo $person->howOldAreYou(); // Outputs: 20 В данном примере, если при создании объекта `Person` не указать возраст, будет использовано значение по умолчанию 20. -Наконец, определение свойства с его инициализацией через конструктор можно сократить и упростить следующим образом: +Приятно то, что определение свойства с его инициализацией через конструктор можно сократить и упростить следующим образом: ```php class Person @@ -92,6 +94,8 @@ class Person } ``` +Для полноты картины, в дополнение к конструкторам, объекты могут иметь деструкторы (метод `__destruct`), которые вызываются перед освобождением объекта из памяти. + Пространства имен .[#toc-namespaces] ------------------------------------ @@ -152,9 +156,9 @@ class Person $this->age = $age; } - function howOldAreYou() + function printInformation() { - return $this->age; + echo "Age: {$this->age} years\n"; } } @@ -170,8 +174,8 @@ class Student extends Person function printInformation() { - echo 'Age of student: ', $this->howOldAreYou(); - echo 'Field of study: ', $this->fieldOfStudy; + parent::printInformation(); + echo "Field of study: {$this->fieldOfStudy} \n"; } } @@ -183,12 +187,26 @@ $student->printInformation(); - Мы использовали ключевое слово `extends` для расширения класса `Person`, то есть класс `Student` наследует все методы и свойства от `Person`. -- Ключевое слово `parent::` позволяет нам вызывать методы из родительского класса. В данном случае мы вызвали конструктор из класса `Person`, а затем добавили собственную функциональность в класс `Student`. +- Ключевое слово `parent::` позволяет нам вызывать методы из родительского класса. В данном случае мы вызвали конструктор из класса `Person`, прежде чем добавить собственную функциональность в класс `Student`. И аналогично, метод предка `printInformation()` перед выводом информации о студентах. Наследование предназначено для ситуаций, когда между классами существует связь "есть". Например, `Student` - это `Person`. Кошка - это животное. Это позволяет нам в случаях, когда в коде ожидается один объект (например, "Person"), использовать вместо него производный объект (например, "Student"). Важно понимать, что основная цель наследования **не** заключается в предотвращении дублирования кода. Напротив, неправильное использование наследования может привести к появлению сложного и трудноразрешимого кода. Если между классами нет отношения "является", то вместо наследования следует рассмотреть композицию. +Обратите внимание, что методы `printInformation()` в классах `Person` и `Student` выводят немного другую информацию. И мы можем добавить другие классы (например, `Employee`), которые будут предоставлять другие реализации этого метода. Способность объектов разных классов по-разному реагировать на один и тот же метод называется полиморфизмом: + +```php +$people = [ + new Person(30), + new Student(20, 'Computer Science'), + new Employee(45, 'Director'), +]; + +foreach ($people as $person) { + $person->printInformation(); +} +``` + Композиция .[#toc-composition] ------------------------------ @@ -202,7 +220,7 @@ class Engine { function start() { - echo "Engine is running."; + echo 'Engine is running.'; } } @@ -218,7 +236,7 @@ class Car function start() { $this->engine->start(); - echo "The car is ready to drive!"; + echo 'The car is ready to drive!'; } } @@ -386,7 +404,29 @@ $cat = new Cat; $cat->makeSound(); ``` -Если класс реализует интерфейс, но не все ожидаемые методы определены, то PHP выдаст ошибку. Класс может реализовывать несколько интерфейсов одновременно, что отличается от наследования, при котором класс может наследоваться только от одного класса. +Если класс реализует интерфейс, но не все ожидаемые методы определены, PHP выдаст ошибку. + +Класс может реализовывать несколько интерфейсов одновременно, что отличается от наследования, когда класс может наследоваться только от одного класса: + +```php +interface Guardian +{ + function guardHouse(); +} + +class Dog implements Animal, Guardian +{ + public function makeSound() + { + echo 'Bark'; + } + + public function guardHouse() + { + echo 'Dog diligently guards the house'; + } +} +``` Абстрактные классы .[#toc-abstract-classes] @@ -422,6 +462,8 @@ $instance->abstractMethod(); В данном примере мы имеем абстрактный класс с одним обычным и одним абстрактным методом. Затем у нас есть класс `Child`, который наследуется от `AbstractClass` и предоставляет реализацию абстрактного метода. +Чем отличаются интерфейсы и абстрактные классы? Абстрактные классы могут содержать как абстрактные, так и конкретные методы, в то время как интерфейсы только определяют, какие методы должен реализовать класс, но не предоставляют никакой реализации. Класс может наследоваться только от одного абстрактного класса, но может реализовать любое количество интерфейсов. + Проверка типа .[#toc-type-checking] ----------------------------------- @@ -450,7 +492,7 @@ class Person public function printAge(): void { - echo "This person is " . $this->age . " years old."; + echo "This person is {$this->age} years old."; } } @@ -465,6 +507,21 @@ function printPersonAge(Person $person): void Таким образом, мы гарантируем, что наш код ожидает и работает с данными правильного типа, что помогает нам предотвратить возможные ошибки. +Некоторые типы не могут быть написаны непосредственно в PHP. В этом случае они перечисляются в комментариях phpDoc - это стандартный формат документирования PHP-кода, начинающийся с `/**` и заканчивающийся `*/`. Он позволяет добавлять описания классов, методов и так далее. А также перечислять сложные типы с помощью так называемых аннотаций `@var`, `@param` и `@return`. Эти типы затем используются инструментами статического анализа кода, но не проверяются самим PHP. + +```php +class Registry +{ + /** @var array indicates that it's an array of Person objects */ + private array $persons = []; + + public function addPerson(Person $person): void + { + $this->persons[] = $person; + } +} +``` + Сравнение и идентичность .[#toc-comparison-and-identity] -------------------------------------------------------- @@ -635,31 +692,47 @@ $truck->honk(); // Also outputs 'Beep beep!' Исключения ---------- -Исключения в ООП позволяют обрабатывать и управлять ошибками, которые могут возникнуть в процессе выполнения кода. По сути, это объекты, предназначенные для регистрации ошибок или неожиданных ситуаций в вашей программе. - -В PHP для таких объектов существует встроенный класс `Exception`. Он имеет несколько методов, позволяющих получить дополнительную информацию об исключении, например, сообщение об ошибке, файл, строку, в которой произошла ошибка, и т.д. +Исключения в ООП позволяют нам изящно обрабатывать ошибки и неожиданные ситуации в нашем коде. Они представляют собой объекты, которые несут информацию об ошибке или необычной ситуации. -При возникновении проблемы мы можем "выбросить" исключение (используя `throw`). Если мы хотим "поймать" и обработать это исключение, мы используем блоки `try` и `catch`. +В PHP есть встроенный класс `Exception`, который служит основой для всех исключений. Он имеет несколько методов, которые позволяют получить дополнительную информацию об исключении, например, сообщение об ошибке, файл и строку, в которой произошла ошибка, и т.д. -Давайте посмотрим, как это работает: +Когда в коде возникает ошибка, мы можем "выбросить" исключение, используя ключевое слово `throw`. ```php -try { - throw new Exception('Message explaining the reason for the exception'); +function division(float $a, float $b): float +{ + if ($b === 0) { + throw new Exception('Division by zero!'); + } + return $a / $b; +} +``` - // This code won't execute - echo 'I am a message that nobody will read'; +Когда функция `division()` получает null в качестве второго аргумента, она выбрасывает исключение с сообщением об ошибке `'Division by zero!'`. Чтобы предотвратить аварийное завершение программы при возникновении исключения, мы перехватываем его в блоке `try/catch`: +```php +try { + echo division(10, 0); } catch (Exception $e) { echo 'Exception caught: '. $e->getMessage(); } ``` -Важно отметить, что исключение может быть выброшено и глубже, во время вызова других методов. +Код, который может выбросить исключение, оборачивается в блок `try`. Если исключение выброшено, выполнение кода переходит в блок `catch`, где мы можем обработать исключение (например, написать сообщение об ошибке). + +После блоков `try` и `catch` можно добавить необязательный блок `finally`, который выполняется всегда, независимо от того, было ли выброшено исключение или нет (даже если мы используем `return`, `break` или `continue` в блоке `try` или `catch` ): -Для одного блока `try` можно указать несколько блоков `catch`, если ожидаются различные типы исключений. +```php +try { + echo division(10, 0); +} catch (Exception $e) { + echo 'Exception caught: '. $e->getMessage(); +} finally { + // Code that is always executed whether the exception has been thrown or not +} +``` -Можно также создать иерархию исключений, в которой каждый класс исключений наследуется от предыдущего. В качестве примера рассмотрим простое банковское приложение, позволяющее вносить и снимать деньги: +Мы также можем создавать собственные классы исключений (иерархию), которые наследуются от класса Exception. В качестве примера рассмотрим простое банковское приложение, которое позволяет вносить и снимать деньги: ```php class BankingException extends Exception {} @@ -691,7 +764,11 @@ class BankAccount return $this->balance; } } +``` + +Для одного блока `try` можно указать несколько блоков `catch`, если вы ожидаете различные типы исключений. +```php $account = new BankAccount; $account->deposit(500); @@ -709,6 +786,51 @@ try { В этом примере важно обратить внимание на порядок следования блоков `catch`. Поскольку все исключения наследуются от `BankingException`, то если бы этот блок был первым, то все исключения были бы пойманы в нем, а код не дошел бы до последующих блоков `catch`. Поэтому важно, чтобы более специфические исключения (т.е. те, которые наследуются от других) располагались выше в порядке блоков `catch`, чем их родительские исключения. +Итерации .[#toc-iterations] +--------------------------- + +В PHP вы можете перебирать объекты с помощью цикла `foreach`, подобно тому, как вы перебираете массивы. Чтобы это работало, объект должен реализовать специальный интерфейс. + +Первый вариант - реализовать интерфейс `Iterator`, в котором есть методы `current()`, возвращающие текущее значение, `key()`, возвращающие ключ, `next()`, переходящие к следующему значению, `rewind()`, переходящие к началу, и `valid()`, проверяющие, дошли ли мы до конца. + +Другой вариант - реализовать интерфейс `IteratorAggregate`, который имеет только один метод `getIterator()`. Он либо возвращает объект-заполнитель, который обеспечит обход, либо может быть генератором, то есть специальной функцией, которая использует `yield` для последовательного возврата ключей и значений: + +```php +class Person +{ + public function __construct( + public int $age, + ) { + } +} + +class Registry implements IteratorAggregate +{ + private array $people = []; + + public function addPerson(Person $person): void + { + $this->people[] = $person; + } + + public function getIterator(): Generator + { + foreach ($this->people as $person) { + yield $person; + } + } +} + +$list = new Registry; +$list->addPerson(new Person(30)); +$list->addPerson(new Person(25)); + +foreach ($list as $person) { + echo "Age: {$person->age} years\n"; +} +``` + + Лучшие практики .[#toc-best-practices] -------------------------------------- diff --git a/nette/sl/introduction-to-object-oriented-programming.texy b/nette/sl/introduction-to-object-oriented-programming.texy index b322b6dd76..0e9f227fa2 100644 --- a/nette/sl/introduction-to-object-oriented-programming.texy +++ b/nette/sl/introduction-to-object-oriented-programming.texy @@ -52,7 +52,9 @@ $person = new Person(25); echo $person->howOldAreYou(); // Outputs: 25 ``` -V tem primeru ima razred `Person` lastnost `$age` in konstruktor, ki to lastnost nastavi. Metoda `howOldAreYou()` nato omogoča dostop do starosti osebe. +V tem primeru ima razred `Person` lastnost (spremenljivko) `$age` in konstruktor, ki to lastnost nastavi. Metoda `howOldAreYou()` nato omogoča dostop do starosti osebe. + +Psevdopremenljivka `$this` se uporablja znotraj razreda za dostop do lastnosti in metod objekta. Ključna beseda `new` se uporablja za ustvarjanje novega primerka razreda. V zgornjem primeru smo ustvarili novo osebo, staro 25 let. @@ -80,7 +82,7 @@ echo $person->howOldAreYou(); // Outputs: 20 Če pri ustvarjanju predmeta `Person` ne določite starosti, bo uporabljena privzeta vrednost 20. -Nazadnje lahko opredelitev lastnosti z njeno inicializacijo prek konstruktorja skrajšate in poenostavite na naslednji način: +Lepo je, da lahko definicijo lastnosti z njeno inicializacijo prek konstruktorja skrajšamo in poenostavimo na naslednji način: ```php class Person @@ -92,6 +94,8 @@ class Person } ``` +Za popolnost dodajmo, da imajo lahko objekti poleg konstruktorjev tudi destruktorje (metoda `__destruct`), ki se kličejo, preden se objekt sprosti iz pomnilnika. + Prostori imen .[#toc-namespaces] -------------------------------- @@ -152,9 +156,9 @@ class Person $this->age = $age; } - function howOldAreYou() + function printInformation() { - return $this->age; + echo "Age: {$this->age} years\n"; } } @@ -170,8 +174,8 @@ class Student extends Person function printInformation() { - echo 'Age of student: ', $this->howOldAreYou(); - echo 'Field of study: ', $this->fieldOfStudy; + parent::printInformation(); + echo "Field of study: {$this->fieldOfStudy} \n"; } } @@ -183,12 +187,26 @@ Kako deluje ta koda? - S ključno besedo `extends` smo razširili razred `Person`, kar pomeni, da razred `Student` podeduje vse metode in lastnosti od razreda `Person`. -- Ključna beseda `parent::` nam omogoča, da kličemo metode iz nadrejenega razreda. V tem primeru smo poklicali konstruktor iz razreda `Person`, preden smo v razred `Student` dodali svojo funkcionalnost. +- Ključna beseda `parent::` nam omogoča klicanje metod iz nadrejenega razreda. V tem primeru smo poklicali konstruktor iz razreda `Person`, preden smo v razred `Student` dodali svojo funkcionalnost. In podobno tudi metodo razreda `printInformation()` prednika, preden smo izpisali podatke o učencu. Dedovanje je namenjeno situacijam, v katerih med razredi obstaja razmerje "is a". Na primer, razred `Student` je razred `Person`. Mačka je žival. Omogoča nam, da v primerih, ko v kodi pričakujemo en objekt (npr. "Oseba"), namesto njega uporabimo izpeljani objekt (npr. "Študent"). Bistveno se je zavedati, da glavni namen dedovanja **ni** preprečevanje podvajanja kode. Ravno nasprotno, napačna uporaba dedovanja lahko privede do zapletene in težko vzdrževane kode. Če med razredi ni razmerja "je a", moramo namesto dedovanja razmisliti o kompoziciji. +Upoštevajte, da metode `printInformation()` v razredih `Person` in `Student` prikazujejo nekoliko drugačne informacije. Dodamo lahko tudi druge razrede (na primer `Employee`), ki bodo zagotovili druge izvedbe te metode. Sposobnost objektov različnih razredov, da se na isto metodo odzivajo na različne načine, se imenuje polimorfizem: + +```php +$people = [ + new Person(30), + new Student(20, 'Computer Science'), + new Employee(45, 'Director'), +]; + +foreach ($people as $person) { + $person->printInformation(); +} +``` + Sestavljanje .[#toc-composition] -------------------------------- @@ -202,7 +220,7 @@ class Engine { function start() { - echo "Engine is running."; + echo 'Engine is running.'; } } @@ -218,7 +236,7 @@ class Car function start() { $this->engine->start(); - echo "The car is ready to drive!"; + echo 'The car is ready to drive!'; } } @@ -386,7 +404,29 @@ $cat = new Cat; $cat->makeSound(); ``` -Če razred implementira vmesnik, vendar niso definirane vse pričakovane metode, PHP vrže napako. Razred lahko implementira več vmesnikov hkrati, kar se razlikuje od dedovanja, pri katerem lahko razred deduje samo od enega razreda. +Če razred implementira vmesnik, vendar niso definirane vse pričakovane metode, PHP vrže napako. + +Razred lahko implementira več vmesnikov hkrati, kar se razlikuje od dedovanja, pri katerem lahko razred deduje samo od enega razreda: + +```php +interface Guardian +{ + function guardHouse(); +} + +class Dog implements Animal, Guardian +{ + public function makeSound() + { + echo 'Bark'; + } + + public function guardHouse() + { + echo 'Dog diligently guards the house'; + } +} +``` Abstraktni razredi .[#toc-abstract-classes] @@ -422,6 +462,8 @@ $instance->abstractMethod(); V tem primeru imamo abstraktni razred z eno redno in eno abstraktno metodo. Nato imamo razred `Child`, ki podeduje od `AbstractClass` in zagotavlja implementacijo abstraktne metode. +V čem se vmesniki in abstraktni razredi razlikujejo? Abstraktni razredi lahko vsebujejo tako abstraktne kot konkretne metode, medtem ko vmesniki le določajo, katere metode mora razred implementirati, ne zagotavljajo pa implementacije. Razred lahko podeduje le en abstraktni razred, implementira pa lahko poljubno število vmesnikov. + Preverjanje tipa .[#toc-type-checking] -------------------------------------- @@ -450,7 +492,7 @@ class Person public function printAge(): void { - echo "This person is " . $this->age . " years old."; + echo "This person is {$this->age} years old."; } } @@ -465,6 +507,21 @@ function printPersonAge(Person $person): void Na ta način zagotovimo, da naša koda pričakuje in dela s podatki pravilne vrste, kar nam pomaga preprečiti morebitne napake. +Nekaterih vrst ni mogoče neposredno zapisati v PHP. V tem primeru so navedeni v komentarju phpDoc, ki je standardna oblika za dokumentiranje kode PHP in se začne s `/**` in konča s `*/`. Omogoča dodajanje opisov razredov, metod itd. Prav tako pa tudi za navajanje kompleksnih tipov s tako imenovanimi opombami `@var`, `@param` in `@return`. Te vrste nato uporabljajo orodja za statično analizo kode, vendar jih PHP sam ne preverja. + +```php +class Registry +{ + /** @var array indicates that it's an array of Person objects */ + private array $persons = []; + + public function addPerson(Person $person): void + { + $this->persons[] = $person; + } +} +``` + Primerjava in identiteta .[#toc-comparison-and-identity] -------------------------------------------------------- @@ -635,31 +692,47 @@ Značilnosti omogočajo enostavno in učinkovito izmenjavo kode med razredi. Ne Izjeme ------ -Izjeme v OOP nam omogočajo obravnavo in upravljanje napak, ki se lahko pojavijo med izvajanjem naše kode. V bistvu so predmeti, namenjeni beleženju napak ali nepričakovanih situacij v vašem programu. - -V PHP je za te predmete vgrajen razred `Exception`. Ima več metod, ki nam omogočajo, da pridobimo več informacij o izjemi, kot so sporočilo o napaki, datoteka in vrstica, v kateri se je napaka pojavila, itd. +Izjeme v OOP nam omogočajo elegantno obravnavanje napak in nepričakovanih situacij v naši kodi. So predmeti, ki nosijo informacije o napaki ali nenavadni situaciji. -Ko se pojavi težava, lahko "vržemo" izjemo (z uporabo razreda `throw`). Če želimo to izjemo "ujeti" in obdelati, uporabimo bloka `try` in `catch`. +V jeziku PHP imamo vgrajen razred `Exception`, ki služi kot osnova za vse izjeme. Ta ima več metod, s katerimi lahko pridobimo več informacij o izjemi, kot so sporočilo o napaki, datoteka in vrstica, v kateri se je napaka pojavila, itd. -Oglejmo si, kako to deluje: +Ko se v kodi pojavi napaka, lahko izjemo "vržemo" z uporabo ključne besede `throw`. ```php -try { - throw new Exception('Message explaining the reason for the exception'); +function division(float $a, float $b): float +{ + if ($b === 0) { + throw new Exception('Division by zero!'); + } + return $a / $b; +} +``` - // This code won't execute - echo 'I am a message that nobody will read'; +Ko funkcija `division()` kot drugi argument prejme ničlo, vrže izjemo s sporočilom o napaki `'Division by zero!'`. Da bi preprečili sesutje programa, ko se vrže izjema, jo ujamemo v blok `try/catch`: +```php +try { + echo division(10, 0); } catch (Exception $e) { echo 'Exception caught: '. $e->getMessage(); } ``` -Pomembno je opozoriti, da se izjema lahko vrže globlje, med klicem drugih metod. +Koda, ki lahko vrže izjemo, je zavita v blok `try`. Če je izjema vržena, se izvajanje kode premakne v blok `catch`, kjer lahko obravnavamo izjemo (npr. napišemo sporočilo o napaki). + +Za blokoma `try` in `catch` lahko dodamo neobvezni blok `finally`, ki se vedno izvede ne glede na to, ali je bila izjema vržena ali ne (tudi če v bloku `try` ali `catch` uporabimo `return`, `break` ali `continue` ): -Za en blok `try` lahko določite več blokov `catch`, če pričakujete različne vrste izjem. +```php +try { + echo division(10, 0); +} catch (Exception $e) { + echo 'Exception caught: '. $e->getMessage(); +} finally { + // Code that is always executed whether the exception has been thrown or not +} +``` -Ustvarimo lahko tudi hierarhijo izjem, kjer vsak razred izjem podeduje od prejšnjega. Kot primer si oglejmo preprosto bančno aplikacijo, ki omogoča vplačila in izplačila: +Ustvarimo lahko tudi lastne razrede izjem (hierarhijo), ki dedujejo po razredu Exception. Kot primer si oglejmo preprosto bančno aplikacijo, ki omogoča vplačila in izplačila: ```php class BankingException extends Exception {} @@ -691,7 +764,11 @@ class BankAccount return $this->balance; } } +``` + +Če pričakujete različne vrste izjem, lahko za en sam blok `try` določite več blokov `catch`. +```php $account = new BankAccount; $account->deposit(500); @@ -709,6 +786,51 @@ try { V tem primeru je pomembno upoštevati vrstni red blokov `catch`. Ker vse izjeme dedujejo od `BankingException`, bi se, če bi imeli ta blok prvi, vse izjeme ujele v njem, ne da bi koda dosegla naslednje bloke `catch`. Zato je pomembno, da so bolj specifične izjeme (tj. tiste, ki dedujejo od drugih) višje v vrstnem redu blokov `catch` kot njihove nadrejene izjeme. +Iteracije .[#toc-iterations] +---------------------------- + +V jeziku PHP lahko z zanko `foreach` krožite po predmetih, podobno kot krožite po polju. Da bi to delovalo, mora objekt implementirati poseben vmesnik. + +Prva možnost je implementacija vmesnika `Iterator`, ki ima metode `current()`, ki vrača trenutno vrednost, `key()`, ki vrača ključ, `next()`, ki se premakne na naslednjo vrednost, `rewind()`, ki se premakne na začetek, in `valid()`, ki preveri, ali smo že na koncu. + +Druga možnost je, da implementiramo vmesnik `IteratorAggregate`, ki ima samo eno metodo `getIterator()`. Ta bodisi vrne nadomestni objekt, ki bo zagotovil prehod, bodisi je lahko generator, ki je posebna funkcija, ki uporablja `yield` za zaporedno vračanje ključev in vrednosti: + +```php +class Person +{ + public function __construct( + public int $age, + ) { + } +} + +class Registry implements IteratorAggregate +{ + private array $people = []; + + public function addPerson(Person $person): void + { + $this->people[] = $person; + } + + public function getIterator(): Generator + { + foreach ($this->people as $person) { + yield $person; + } + } +} + +$list = new Registry; +$list->addPerson(new Person(30)); +$list->addPerson(new Person(25)); + +foreach ($list as $person) { + echo "Age: {$person->age} years\n"; +} +``` + + Najboljše prakse .[#toc-best-practices] --------------------------------------- diff --git a/nette/tr/introduction-to-object-oriented-programming.texy b/nette/tr/introduction-to-object-oriented-programming.texy index 68c194847c..3ce739c184 100644 --- a/nette/tr/introduction-to-object-oriented-programming.texy +++ b/nette/tr/introduction-to-object-oriented-programming.texy @@ -52,7 +52,9 @@ $person = new Person(25); echo $person->howOldAreYou(); // Outputs: 25 ``` -Bu örnekte, `Person` sınıfının bir `$age` özelliği ve bu özelliği ayarlayan bir kurucusu vardır. Daha sonra `howOldAreYou()` yöntemi kişinin yaşına erişim sağlar. +Bu örnekte, `Person` sınıfının bir özelliği (değişkeni) `$age` ve bu özelliği ayarlayan bir kurucusu vardır. Daha sonra `howOldAreYou()` yöntemi kişinin yaşına erişim sağlar. + + `$this` sözde değişkeni, nesnenin özelliklerine ve yöntemlerine erişmek için sınıf içinde kullanılır. `new` anahtar sözcüğü bir sınıfın yeni bir örneğini oluşturmak için kullanılır. Yukarıdaki örnekte, 25 yaşında yeni bir kişi oluşturduk. @@ -80,7 +82,7 @@ echo $person->howOldAreYou(); // Outputs: 20 Bu örnekte, bir `Person` nesnesi oluştururken bir yaş belirtmezseniz, varsayılan değer olan 20 kullanılacaktır. -Son olarak, yapıcı aracılığıyla başlatılmasıyla birlikte özellik tanımı şu şekilde kısaltılabilir ve basitleştirilebilir: +Güzel olan şey, yapıcı aracılığıyla başlatılmasıyla birlikte özellik tanımının bu şekilde kısaltılabilmesi ve basitleştirilebilmesidir: ```php class Person @@ -92,6 +94,8 @@ class Person } ``` +Bütünlük için, kuruculara ek olarak, nesneler bellekten serbest bırakılmadan önce çağrılan yıkıcılara (yöntem `__destruct`) sahip olabilir. + İsim Alanları .[#toc-namespaces] -------------------------------- @@ -152,9 +156,9 @@ class Person $this->age = $age; } - function howOldAreYou() + function printInformation() { - return $this->age; + echo "Age: {$this->age} years\n"; } } @@ -170,8 +174,8 @@ class Student extends Person function printInformation() { - echo 'Age of student: ', $this->howOldAreYou(); - echo 'Field of study: ', $this->fieldOfStudy; + parent::printInformation(); + echo "Field of study: {$this->fieldOfStudy} \n"; } } @@ -183,12 +187,26 @@ Bu kod nasıl çalışıyor? - `Person` sınıfını genişletmek için `extends` anahtar sözcüğünü kullandık, yani `Student` sınıfı tüm yöntemleri ve özellikleri `Person` sınıfından devralır. -- `parent::` anahtar sözcüğü, üst sınıftaki yöntemleri çağırmamızı sağlar. Bu durumda, `Student` sınıfına kendi işlevselliğimizi eklemeden önce `Person` sınıfından kurucuyu çağırdık. +- `parent::` anahtar sözcüğü, üst sınıftaki yöntemleri çağırmamızı sağlar. Bu durumda, `Student` sınıfına kendi işlevselliğimizi eklemeden önce `Person` sınıfından kurucuyu çağırdık. Ve benzer şekilde, öğrenci bilgilerini listelemeden önce `printInformation()` ata yöntemini çağırdık. Kalıtım, sınıflar arasında "is a" ilişkisinin olduğu durumlar içindir. Örneğin, bir `Student` bir `Person`. Bir kedi bir hayvandır. Kodda bir nesne (örn. "Kişi") beklediğimiz durumlarda bunun yerine türetilmiş bir nesne (örn. "Öğrenci") kullanmamızı sağlar. Kalıtımın birincil amacının **kod tekrarını önlemek** olmadığının farkına varmak çok önemlidir. Aksine, kalıtımın yanlış kullanımı karmaşık ve bakımı zor kodlara yol açabilir. Sınıflar arasında "is a" ilişkisi yoksa, kalıtım yerine bileşimi düşünmeliyiz. +`Person` ve `Student` sınıflarındaki `printInformation()` yöntemlerinin biraz farklı bilgiler verdiğine dikkat edin. Ve bu yöntemin başka uygulamalarını sağlayacak başka sınıflar ( `Employee` gibi) ekleyebiliriz. Farklı sınıflardaki nesnelerin aynı yönteme farklı şekillerde yanıt verebilmesine çok biçimlilik denir: + +```php +$people = [ + new Person(30), + new Student(20, 'Computer Science'), + new Employee(45, 'Director'), +]; + +foreach ($people as $person) { + $person->printInformation(); +} +``` + Kompozisyon .[#toc-composition] ------------------------------- @@ -202,7 +220,7 @@ class Engine { function start() { - echo "Engine is running."; + echo 'Engine is running.'; } } @@ -218,7 +236,7 @@ class Car function start() { $this->engine->start(); - echo "The car is ready to drive!"; + echo 'The car is ready to drive!'; } } @@ -386,7 +404,29 @@ $cat = new Cat; $cat->makeSound(); ``` -Bir sınıf bir arayüzü uygular, ancak beklenen tüm yöntemler tanımlanmamışsa, PHP bir hata verir. Bir sınıf aynı anda birden fazla arayüzü uygulayabilir; bu, bir sınıfın yalnızca bir sınıftan miras alabildiği kalıtımdan farklıdır. +Eğer bir sınıf bir arayüzü uyguluyor, ancak beklenen tüm yöntemler tanımlanmamışsa, PHP bir hata verir. + +Bir sınıf aynı anda birden fazla arayüzü uygulayabilir; bu, bir sınıfın yalnızca bir sınıftan miras alabildiği kalıtımdan farklıdır: + +```php +interface Guardian +{ + function guardHouse(); +} + +class Dog implements Animal, Guardian +{ + public function makeSound() + { + echo 'Bark'; + } + + public function guardHouse() + { + echo 'Dog diligently guards the house'; + } +} +``` Soyut Sınıflar .[#toc-abstract-classes] @@ -422,6 +462,8 @@ $instance->abstractMethod(); Bu örnekte, bir normal ve bir soyut yöntemi olan soyut bir sınıfımız var. Ardından, `AbstractClass` adresinden miras alan ve soyut yöntem için bir uygulama sağlayan bir `Child` sınıfımız var. +Arayüzler ve soyut sınıflar nasıl farklıdır? Soyut sınıflar hem soyut hem de somut yöntemler içerebilirken, arayüzler yalnızca sınıfın hangi yöntemleri uygulaması gerektiğini tanımlar, ancak hiçbir uygulama sağlamaz. Bir sınıf yalnızca bir soyut sınıftan miras alabilir, ancak herhangi bir sayıda arayüzü uygulayabilir. + Tip Kontrolü .[#toc-type-checking] ---------------------------------- @@ -450,7 +492,7 @@ class Person public function printAge(): void { - echo "This person is " . $this->age . " years old."; + echo "This person is {$this->age} years old."; } } @@ -465,6 +507,21 @@ function printPersonAge(Person $person): void Bu şekilde, kodumuzun doğru türdeki verileri beklediğinden ve bunlarla çalıştığından emin olarak olası hataları önlememize yardımcı oluruz. +Bazı türler PHP'de doğrudan yazılamaz. Bu durumda, PHP kodunu belgelemek için standart biçim olan phpDoc yorumunda listelenirler, `/**` ile başlar ve `*/` ile biter. Sınıfların, yöntemlerin vb. açıklamalarını eklemenize olanak tanır. Ayrıca `@var`, `@param` ve `@return` ek açıklamalarını kullanarak karmaşık türleri listelemenizi sağlar. Bu tipler daha sonra statik kod analiz araçları tarafından kullanılır, ancak PHP'nin kendisi tarafından kontrol edilmez. + +```php +class Registry +{ + /** @var array indicates that it's an array of Person objects */ + private array $persons = []; + + public function addPerson(Person $person): void + { + $this->persons[] = $person; + } +} +``` + Karşılaştırma ve Kimlik .[#toc-comparison-and-identity] ------------------------------------------------------- @@ -495,9 +552,8 @@ var_dump($car1 === $car3); // true, because $car3 is the same instance as $car1 ``` - - `instanceof` Operatör .[#toc-the-instanceof-operator] -------------------------- +`instanceof` Operatör .[#toc-the-instanceof-operator] +----------------------------------------------------- `instanceof` operatörü, belirli bir nesnenin belirli bir sınıfın örneği olup olmadığını, bu sınıfın soyundan gelip gelmediğini veya belirli bir arayüzü uygulayıp uygulamadığını belirlemenizi sağlar. @@ -562,9 +618,8 @@ Bu örnekte, `setFrom()`, `setRecipient()`, ve `setMessage()` yöntemleri ilgili Akıcı arayüzler sayesinde sezgisel ve kolay okunabilir kodlar yazabiliyoruz. - - `clone` ile kopyalama .[#toc-copying-with-clone] --------------------- +`clone` ile kopyalama .[#toc-copying-with-clone] +------------------------------------------------ PHP'de `clone` operatörünü kullanarak bir nesnenin kopyasını oluşturabiliriz. Bu şekilde, aynı içeriğe sahip yeni bir örnek elde ederiz. @@ -597,9 +652,9 @@ Bu örnekte, bir özelliği `$name` olan bir `Sheep` sınıfımız var. Bu sın Özellikler .[#toc-traits] -PHP'deki özellikler, sınıflar arasında yöntemlerin, özelliklerin ve sabitlerin paylaşılmasını sağlayan ve kod tekrarını önleyen bir araçtır. Bunları, bir özelliğin içeriğinin sınıflara "yapıştırıldığı" bir "kopyala ve yapıştır" mekanizması (Ctrl-C ve Ctrl-V) olarak düşünebilirsiniz. Bu, karmaşık sınıf hiyerarşileri oluşturmak zorunda kalmadan kodu yeniden kullanmanıza olanak tanır. +------------------------- -PHP'deki özellikler, sınıflar arasında yöntemlerin paylaşılmasını sağlayan ve kod tekrarını önleyen bir araçtır. Bunları, bir özelliğin içeriğinin sınıflara "yapıştırıldığı" bir "kopyala ve yapıştır" mekanizması (Ctrl-C ve Ctrl-V) olarak düşünebilirsiniz. Bu, karmaşık sınıf hiyerarşileri oluşturmak zorunda kalmadan kodu yeniden kullanmanıza olanak tanır. +PHP'deki özellikler, sınıflar arasında yöntemlerin, özelliklerin ve sabitlerin paylaşılmasını sağlayan ve kod tekrarını önleyen bir araçtır. Bunları, bir özelliğin içeriğinin sınıflara "yapıştırıldığı" bir "kopyala ve yapıştır" mekanizması (Ctrl-C ve Ctrl-V) olarak düşünebilirsiniz. Bu, karmaşık sınıf hiyerarşileri oluşturmak zorunda kalmadan kodu yeniden kullanmanıza olanak tanır. PHP'de özelliklerin nasıl kullanılacağına dair basit bir örneğe göz atalım: @@ -634,38 +689,50 @@ Bu örnekte, bir yöntem içeren `Honking` adlı bir özelliğimiz var `honk()`. Özellikler, sınıflar arasında kolay ve verimli bir şekilde kod paylaşımı yapmanızı sağlar. Kalıtım hiyerarşisine girmezler, yani `$car instanceof Honking`, `false` döndürür. -İstisnalar ----------- - +İstisnalar .[#toc-exceptions] +----------------------------- -OOP'de İstisnalar .[#toc-exceptions-in-oop] -------------------------------------------- +OOP'deki istisnalar, kodumuzdaki hataları ve beklenmedik durumları zarif bir şekilde ele almamızı sağlar. Bunlar, bir hata veya olağandışı durum hakkında bilgi taşıyan nesnelerdir. -OOP'deki istisnalar, kodumuzun yürütülmesi sırasında ortaya çıkabilecek hataları ele almamızı ve yönetmemizi sağlar. Bunlar esasen programınızdaki hataları veya beklenmedik durumları kaydetmek için tasarlanmış nesnelerdir. +PHP'de, tüm istisnalar için temel teşkil eden yerleşik bir `Exception` sınıfımız vardır. Bunun, hata mesajı, hatanın oluştuğu dosya ve satır gibi istisna hakkında daha fazla bilgi almamızı sağlayan çeşitli yöntemleri vardır. -PHP'de, bu nesneler için yerleşik `Exception` sınıfına sahibiz. Hata mesajı, dosya ve hatanın oluştuğu satır gibi istisna hakkında daha fazla bilgi almamızı sağlayan birkaç yöntemi vardır. +Kodda bir hata oluştuğunda, `throw` anahtar sözcüğünü kullanarak istisnayı "atabiliriz". -Bir sorun ortaya çıktığında, bir istisna "atabiliriz" ( `throw` kullanarak). Bu istisnayı "yakalamak" ve işlemek istiyorsak, `try` ve `catch` bloklarını kullanırız. +```php +function division(float $a, float $b): float +{ + if ($b === 0) { + throw new Exception('Division by zero!'); + } + return $a / $b; +} +``` -Nasıl çalıştığını görelim: +`division()` fonksiyonu ikinci argüman olarak null aldığında, `'Division by zero!'` hata mesajını içeren bir istisna fırlatır. İstisna fırlatıldığında programın çökmesini önlemek için, istisnayı `try/catch` bloğuna hapsediyoruz: ```php try { - throw new Exception('Message explaining the reason for the exception'); - - // This code won't execute - echo 'I am a message that nobody will read'; - + echo division(10, 0); } catch (Exception $e) { echo 'Exception caught: '. $e->getMessage(); } ``` -Bir istisnanın daha derinde, diğer yöntemlere çağrı sırasında atılabileceğine dikkat etmek önemlidir. +İstisna fırlatabilen kod bir blok `try` içine sarılır. İstisna atılırsa, kod yürütmesi istisnayı ele alabileceğimiz (örneğin, bir hata mesajı yazabileceğimiz) bir bloğa `catch` taşınır. -Bir `try` bloğu için, farklı türde istisnalar bekliyorsanız birden fazla `catch` bloğu belirtilebilir. + `try` ve `catch` bloklarından sonra, istisna atılsa da atılmasa da her zaman çalıştırılan isteğe bağlı bir `finally` bloğu ekleyebiliriz ( `try` veya `catch` bloğunda `return`, `break` veya `continue` kullansak bile): + +```php +try { + echo division(10, 0); +} catch (Exception $e) { + echo 'Exception caught: '. $e->getMessage(); +} finally { + // Code that is always executed whether the exception has been thrown or not +} +``` -Her istisna sınıfının bir öncekinden miras aldığı bir istisna hiyerarşisi de oluşturabiliriz. Örnek olarak, para yatırma ve çekme işlemlerine izin veren basit bir bankacılık uygulaması düşünün: +Exception sınıfından miras alan kendi istisna sınıflarımızı (hiyerarşi) da oluşturabiliriz. Örnek olarak, para yatırma ve çekme işlemlerine izin veren basit bir bankacılık uygulaması düşünün: ```php class BankingException extends Exception {} @@ -697,7 +764,11 @@ class BankAccount return $this->balance; } } +``` +Farklı türde istisnalar bekliyorsanız, tek bir `try` bloğu için birden fazla `catch` bloğu belirtilebilir. + +```php $account = new BankAccount; $account->deposit(500); @@ -712,6 +783,53 @@ try { } ``` +Bu örnekte, `catch` bloklarının sırasına dikkat etmek önemlidir. Tüm istisnalar `BankingException`dan miras alındığından, bu bloğu ilk olarak kullansaydık, kod sonraki `catch` bloklarına ulaşmadan tüm istisnalar bu blokta yakalanırdı. Bu nedenle, daha spesifik istisnaların (yani diğerlerinden miras kalanların) `catch` bloğu sıralamasında ana istisnalardan daha üstte olması önemlidir. + + +Yinelemeler .[#toc-iterations] +------------------------------ + +PHP'de, `foreach` döngüsünü kullanarak, bir dizi içinde döngü yapar gibi nesneler arasında döngü yapabilirsiniz. Bunun çalışması için nesnenin özel bir arayüz uygulaması gerekir. + +İlk seçenek, `current()` mevcut değeri döndüren, `key()` anahtarı döndüren, `next()` bir sonraki değere geçen, `rewind()` başa geçen ve `valid()` henüz sona gelip gelmediğimizi kontrol eden yöntemlere sahip `Iterator` arayüzünü uygulamaktır. + +Diğer seçenek ise sadece bir metodu olan `IteratorAggregate` arayüzünü uygulamaktır `getIterator()`. Bu, çapraz geçişi sağlayacak bir yer tutucu nesne döndürür ya da anahtarları ve değerleri sırayla döndürmek için `yield` kullanan özel bir işlev olan bir üreteç olabilir: + +```php +class Person +{ + public function __construct( + public int $age, + ) { + } +} + +class Registry implements IteratorAggregate +{ + private array $people = []; + + public function addPerson(Person $person): void + { + $this->people[] = $person; + } + + public function getIterator(): Generator + { + foreach ($this->people as $person) { + yield $person; + } + } +} + +$list = new Registry; +$list->addPerson(new Person(30)); +$list->addPerson(new Person(25)); + +foreach ($list as $person) { + echo "Age: {$person->age} years\n"; +} +``` + En İyi Uygulamalar .[#toc-best-practices] ----------------------------------------- @@ -721,5 +839,3 @@ Nesne yönelimli programlamanın temel ilkelerini öğrendikten sonra, OOP'deki 1) **İlgilerin Ayrılması**: Her sınıfın açıkça tanımlanmış bir sorumluluğu olmalı ve yalnızca bir birincil görevi ele almalıdır. Bir sınıf çok fazla şey yapıyorsa, onu daha küçük, uzmanlaşmış sınıflara bölmek uygun olabilir. 2) **Kapsülleme**: Veri ve yöntemler mümkün olduğunca gizli olmalı ve yalnızca tanımlanmış bir arayüz aracılığıyla erişilebilir olmalıdır. Bu, kodun geri kalanını etkilemeden bir sınıfın dahili uygulamasını değiştirmenize olanak tanır. 3) **Dependency Injection**: Bağımlılıkları doğrudan bir sınıfın içinde oluşturmak yerine, onları dışarıdan "enjekte etmelisiniz". Bu prensibi daha iyi anlamak için [Bağımlılık Enjeksiyonu bölümünü |dependency-injection:introduction] okumanızı tavsiye ederiz. - -Bu örnekte, `catch` bloklarının sırasına dikkat etmek önemlidir. Tüm istisnalar `BankingException` adresinden miras alındığından, bu bloğu ilk olarak kullansaydık, kod sonraki `catch` bloklarına ulaşmadan tüm istisnalar bu blokta yakalanırdı. Bu nedenle, daha spesifik istisnaların (yani diğerlerinden miras kalanların) `catch` blok sıralamasında ana istisnalardan daha yukarıda olması önemlidir. diff --git a/nette/uk/introduction-to-object-oriented-programming.texy b/nette/uk/introduction-to-object-oriented-programming.texy index 4416380652..5934433158 100644 --- a/nette/uk/introduction-to-object-oriented-programming.texy +++ b/nette/uk/introduction-to-object-oriented-programming.texy @@ -52,7 +52,9 @@ $person = new Person(25); echo $person->howOldAreYou(); // Outputs: 25 ``` -У цьому прикладі клас `Person` має властивість `$age` і конструктор, який встановлює цю властивість. Метод `howOldAreYou()` надає доступ до віку людини. +У цьому прикладі клас `Person` має властивість (змінну) `$age` і конструктор, який встановлює цю властивість. Метод `howOldAreYou()` надає доступ до віку людини. + +Псевдозмінна `$this` використовується всередині класу для доступу до властивостей і методів об'єкта. Ключове слово `new` використовується для створення нового екземпляра класу. У наведеному вище прикладі ми створили нову особу віком 25 років. @@ -80,7 +82,7 @@ echo $person->howOldAreYou(); // Outputs: 20 У цьому прикладі, якщо не вказати вік при створенні об'єкта `Person`, буде використано значення за замовчуванням 20. -Нарешті, визначення властивості з її ініціалізацією через конструктор можна скоротити і спростити таким чином: +Приємно те, що визначення властивості з її ініціалізацією через конструктор можна скоротити і спростити таким чином: ```php class Person @@ -92,6 +94,8 @@ class Person } ``` +Для повноти, окрім конструкторів, об'єкти можуть мати деструктори (метод `__destruct`), які викликаються перед звільненням об'єкта з пам'яті. + Простори імен .[#toc-namespaces] -------------------------------- @@ -152,9 +156,9 @@ class Person $this->age = $age; } - function howOldAreYou() + function printInformation() { - return $this->age; + echo "Age: {$this->age} years\n"; } } @@ -170,8 +174,8 @@ class Student extends Person function printInformation() { - echo 'Age of student: ', $this->howOldAreYou(); - echo 'Field of study: ', $this->fieldOfStudy; + parent::printInformation(); + echo "Field of study: {$this->fieldOfStudy} \n"; } } @@ -183,12 +187,26 @@ $student->printInformation(); - Ми використали ключове слово `extends` для розширення класу `Person`, тобто клас `Student` успадковує всі методи та властивості від `Person`. -- Ключове слово `parent::` дозволяє нам викликати методи з батьківського класу. У цьому випадку ми викликали конструктор з класу `Person` перед тим, як додати власну функціональність до класу `Student`. +- Ключове слово `parent::` дозволяє нам викликати методи з батьківського класу. У цьому випадку ми викликали конструктор з класу `Person` перед тим, як додати власну функціональність до класу `Student`. І аналогічно, метод предка `printInformation()` перед виведенням інформації про студента. Спадкування призначене для ситуацій, коли між класами існує відношення "є". Наприклад, `Student` є `Person`. Кіт - це тварина. Це дозволяє нам у випадках, коли ми очікуємо один об'єкт (наприклад, "Людина") в коді, використовувати замість нього похідний об'єкт (наприклад, "Студент"). Важливо розуміти, що основною метою успадкування **не є** запобігання дублюванню коду. Навпаки, зловживання успадкуванням може призвести до створення складного і важкого для супроводу коду. Якщо між класами немає відношення "є", то замість успадкування слід розглядати композицію. +Зверніть увагу, що методи `printInformation()` у класах `Person` та `Student` виводять дещо різну інформацію. І ми можемо додати інші класи (наприклад, `Employee`), які будуть надавати інші реалізації цього методу. Здатність об'єктів різних класів по-різному реагувати на один і той самий метод називається поліморфізмом: + +```php +$people = [ + new Person(30), + new Student(20, 'Computer Science'), + new Employee(45, 'Director'), +]; + +foreach ($people as $person) { + $person->printInformation(); +} +``` + Композиція .[#toc-composition] ------------------------------ @@ -202,7 +220,7 @@ class Engine { function start() { - echo "Engine is running."; + echo 'Engine is running.'; } } @@ -218,7 +236,7 @@ class Car function start() { $this->engine->start(); - echo "The car is ready to drive!"; + echo 'The car is ready to drive!'; } } @@ -386,7 +404,29 @@ $cat = new Cat; $cat->makeSound(); ``` -Якщо клас реалізує інтерфейс, але не всі очікувані методи визначені, PHP видасть помилку. Клас може реалізовувати декілька інтерфейсів одночасно, що відрізняється від успадкування, де клас може успадковувати тільки від одного класу. +Якщо клас реалізує інтерфейс, але не всі очікувані методи визначені, PHP видасть помилку. + +Клас може реалізовувати декілька інтерфейсів одночасно, що відрізняється від успадкування, де клас може успадковувати тільки від одного класу: + +```php +interface Guardian +{ + function guardHouse(); +} + +class Dog implements Animal, Guardian +{ + public function makeSound() + { + echo 'Bark'; + } + + public function guardHouse() + { + echo 'Dog diligently guards the house'; + } +} +``` Абстрактні класи .[#toc-abstract-classes] @@ -422,6 +462,8 @@ $instance->abstractMethod(); У цьому прикладі ми маємо абстрактний клас з одним звичайним і одним абстрактним методом. Потім у нас є клас `Child`, який успадковується від `AbstractClass` і надає реалізацію для абстрактного методу. +Чим відрізняються інтерфейси від абстрактних класів? Абстрактні класи можуть містити як абстрактні, так і конкретні методи, в той час як інтерфейси лише визначають, які методи повинен реалізовувати клас, але не надають їх реалізації. Клас може успадковувати лише один абстрактний клас, але може реалізовувати будь-яку кількість інтерфейсів. + Перевірка типів .[#toc-type-checking] ------------------------------------- @@ -450,7 +492,7 @@ class Person public function printAge(): void { - echo "This person is " . $this->age . " years old."; + echo "This person is {$this->age} years old."; } } @@ -465,6 +507,21 @@ function printPersonAge(Person $person): void Таким чином, ми гарантуємо, що наш код очікує і працює з даними правильного типу, що допоможе нам запобігти потенційним помилкам. +Деякі типи не можуть бути написані безпосередньо в PHP. В такому випадку вони перераховуються в коментарі phpDoc, який є стандартним форматом для документування PHP-коду, починаючи з `/**` і закінчуючи `*/`. Він дозволяє додавати описи класів, методів і так далі. А також перераховувати складні типи за допомогою так званих анотацій `@var`, `@param` і `@return`. Ці типи потім використовуються інструментами статичного аналізу коду, але не перевіряються самим PHP. + +```php +class Registry +{ + /** @var array indicates that it's an array of Person objects */ + private array $persons = []; + + public function addPerson(Person $person): void + { + $this->persons[] = $person; + } +} +``` + Порівняння та ідентифікація .[#toc-comparison-and-identity] ----------------------------------------------------------- @@ -635,31 +692,47 @@ $truck->honk(); // Also outputs 'Beep beep!' Винятки ------- -Винятки в ООП дозволяють нам обробляти та керувати помилками, які можуть виникнути під час виконання нашого коду. По суті, це об'єкти, призначені для запису помилок або неочікуваних ситуацій у вашій програмі. - -У PHP для цих об'єктів є вбудований клас `Exception`. Він має кілька методів, які дозволяють отримати більше інформації про виняток, наприклад, повідомлення про помилку, файл, рядок, в якому виникла помилка, тощо. +Винятки в ООП дозволяють нам витончено обробляти помилки та непередбачувані ситуації в нашому коді. Це об'єкти, які несуть інформацію про помилку або нестандартну ситуацію. -Коли виникає проблема, ми можемо "згенерувати" виключення (використовуючи `throw`). Якщо ми хочемо "перехопити" і обробити цей виняток, ми використовуємо блоки `try` і `catch`. +У PHP є вбудований клас `Exception`, який служить основою для всіх винятків. Він має кілька методів, які дозволяють отримати більше інформації про виняток, наприклад, повідомлення про помилку, файл і рядок, де сталася помилка, тощо. -Давайте подивимося, як це працює: +Коли в коді виникає помилка, ми можемо "згенерувати" виключення за допомогою ключового слова `throw`. ```php -try { - throw new Exception('Message explaining the reason for the exception'); +function division(float $a, float $b): float +{ + if ($b === 0) { + throw new Exception('Division by zero!'); + } + return $a / $b; +} +``` - // This code won't execute - echo 'I am a message that nobody will read'; +Коли функція `division()` отримує другим аргументом null, вона генерує виключення з повідомленням про помилку `'Division by zero!'`. Щоб запобігти аварійному завершенню роботи програми при виникненні виключення, ми перехоплюємо його у блоці `try/catch`: +```php +try { + echo division(10, 0); } catch (Exception $e) { echo 'Exception caught: '. $e->getMessage(); } ``` -Важливо зазначити, що виключення може бути згенероване і глибше, під час виклику інших методів. +Код, що може згенерувати виключення, обгорнутий в блок `try`. Якщо виняток згенеровано, виконання коду переходить до блоку `catch`, де ми можемо обробити виняток (наприклад, написати повідомлення про помилку). + +Після блоків `try` і `catch` можна додати необов'язковий блок `finally`, який завжди виконується незалежно від того, чи було згенеровано виключення чи ні (навіть якщо ми використовуємо `return`, `break` або `continue` в блоці `try` або `catch` ): -Для одного блоку `try` можна вказати декілька блоків `catch`, якщо ви очікуєте різні типи винятків. +```php +try { + echo division(10, 0); +} catch (Exception $e) { + echo 'Exception caught: '. $e->getMessage(); +} finally { + // Code that is always executed whether the exception has been thrown or not +} +``` -Ми також можемо створити ієрархію винятків, де кожен клас винятків успадковує попередній. Як приклад, розглянемо простий банківський додаток, який дозволяє вносити та знімати кошти: +Ми також можемо створювати власні класи винятків (ієрархію), які успадковуються від класу Exception. Як приклад, розглянемо простий банківський додаток, який дозволяє вносити та знімати кошти: ```php class BankingException extends Exception {} @@ -691,7 +764,11 @@ class BankAccount return $this->balance; } } +``` + +Для одного блоку `try` можна вказати кілька блоків `catch`, якщо ви очікуєте різні типи виключень. +```php $account = new BankAccount; $account->deposit(500); @@ -709,6 +786,51 @@ try { У цьому прикладі важливо звернути увагу на порядок розташування блоків `catch`. Оскільки всі винятки успадковуються від `BankingException`, якби цей блок був першим, то всі винятки були б перехоплені в ньому без того, щоб код дійшов до наступних блоків `catch`. Тому важливо, щоб більш специфічні винятки (тобто ті, що успадковуються від інших) були вище в порядку блоків `catch`, ніж їхні батьківські винятки. +Ітерації .[#toc-iterations] +--------------------------- + +У PHP ви можете циклічно перебирати об'єкти за допомогою циклу `foreach`, подібно до того, як ви перебираєте масив. Щоб це працювало, об'єкт повинен реалізовувати спеціальний інтерфейс. + +Перший варіант - реалізувати інтерфейс `Iterator`, який має методи `current()`, що повертає поточне значення, `key()`, що повертає ключ, `next()`, що переходить до наступного значення, `rewind()`, що переходить на початок, і `valid()`, що перевіряє, чи ми ще не дійшли до кінця. + +Інший варіант - реалізувати інтерфейс `IteratorAggregate`, який має лише один метод `getIterator()`. Він або повертає об'єкт-заповнювач, який забезпечить обхід, або може бути генератором, тобто спеціальною функцією, яка використовує `yield` для послідовного повернення ключів і значень: + +```php +class Person +{ + public function __construct( + public int $age, + ) { + } +} + +class Registry implements IteratorAggregate +{ + private array $people = []; + + public function addPerson(Person $person): void + { + $this->people[] = $person; + } + + public function getIterator(): Generator + { + foreach ($this->people as $person) { + yield $person; + } + } +} + +$list = new Registry; +$list->addPerson(new Person(30)); +$list->addPerson(new Person(25)); + +foreach ($list as $person) { + echo "Age: {$person->age} years\n"; +} +``` + + Кращі практики .[#toc-best-practices] ------------------------------------- From f33c95ae1922e2a9de045b74a16af0b1b901eb5e Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 11 Mar 2024 22:57:42 +0100 Subject: [PATCH 059/137] nette/application 3.2.1 --- application/bg/configuration.texy | 16 ++++++++++++---- application/bg/modules.texy | 5 ++--- application/cs/configuration.texy | 14 +++++++++++--- application/cs/modules.texy | 5 ++--- application/de/configuration.texy | 16 ++++++++++++---- application/de/modules.texy | 5 ++--- application/el/configuration.texy | 16 ++++++++++++---- application/el/modules.texy | 5 ++--- application/en/configuration.texy | 14 +++++++++++--- application/en/modules.texy | 5 ++--- application/es/configuration.texy | 14 +++++++++++--- application/es/modules.texy | 5 ++--- application/fr/configuration.texy | 16 ++++++++++++---- application/fr/modules.texy | 5 ++--- application/hu/configuration.texy | 14 +++++++++++--- application/hu/modules.texy | 5 ++--- application/it/configuration.texy | 16 ++++++++++++---- application/it/modules.texy | 5 ++--- application/pl/configuration.texy | 16 ++++++++++++---- application/pl/modules.texy | 5 ++--- application/pt/configuration.texy | 16 ++++++++++++---- application/pt/modules.texy | 5 ++--- application/ro/configuration.texy | 16 ++++++++++++---- application/ro/modules.texy | 5 ++--- application/ru/configuration.texy | 16 ++++++++++++---- application/ru/modules.texy | 5 ++--- application/sl/configuration.texy | 16 ++++++++++++---- application/sl/modules.texy | 5 ++--- application/tr/configuration.texy | 16 ++++++++++++---- application/tr/modules.texy | 5 ++--- application/uk/configuration.texy | 16 ++++++++++++---- application/uk/modules.texy | 5 ++--- 32 files changed, 220 insertions(+), 108 deletions(-) diff --git a/application/bg/configuration.texy b/application/bg/configuration.texy index c017613f9c..584883c9e9 100644 --- a/application/bg/configuration.texy +++ b/application/bg/configuration.texy @@ -13,11 +13,12 @@ application: # показва раздела "Nette Application" на синия екран на Tracy? debugger: ... # (bool) по подразбиране е true - # ще бъде ли извикан презентаторът на грешки в случай на грешка? - catchExceptions: ... # (bool) по подразбиране е true на "battle" сървър + # Ще се извика ли error-presenter при грешка? + # има ефект само в режим за разработчици + catchExceptions: ... # (bool) по подразбиране е true # име на водещ на грешка - errorPresenter: Error # (string) по подразбиране е 'Nette:Error' + errorPresenter: Error # (string|array) по подразбиране е 'Nette:Error' # дефинира правила за съпоставяне на името на водещия с клас mapping: ... @@ -27,7 +28,14 @@ application: silentLinks: ... # (bool) по подразбиране е false ``` -Тъй като в режим на разработка презентаторите на грешки не се извикват по подразбиране, а грешките се показват от Tracy, промяната на стойността на `catchExceptions` на `true` помага да се провери дали презентаторите на грешки работят правилно по време на разработката. +От версия 3.2 на `nette/application` е възможно да се дефинира двойка представящи грешки: + +```neon +application: + errorPresenter: + 4xx: Error4xx # за Nette\Application\BadRequestException + 5xx: Error5xx # за други изключения +``` Опцията `silentLinks` определя как Nette да се държи в режим на разработчик, когато генерирането на връзки е неуспешно (например поради липса на презентатор и т.н.). Стойността по подразбиране `false` означава, че Nette работи `E_USER_WARNING`. Задаването на `true` потиска това съобщение за грешка. В производствена среда винаги се извиква `E_USER_WARNING`. Можем също така да повлияем на това поведение, като зададем променливата на водещия [$invalidLinkMode |creating-links#Invalid-Links]. diff --git a/application/bg/modules.texy b/application/bg/modules.texy index 622fd48b2e..ddecd3f1a8 100644 --- a/application/bg/modules.texy +++ b/application/bg/modules.texy @@ -108,8 +108,7 @@ class DashboardPresenter extends Nette\Application\UI\Presenter ```neon application: - mapping: - *: App\Presenters\*Presenter + mapping: App\Presenters\*Presenter ``` Името на водещия се заменя със звездичка и резултатът е името на класа. Лесно! @@ -145,4 +144,4 @@ application: *: [App\Modules, *, Presenters\*Presenter] ``` -Стойността по подразбиране е `*: *Module\*Presenter`. +Стойността по подразбиране е `*Module\*Presenter`. diff --git a/application/cs/configuration.texy b/application/cs/configuration.texy index 6f258ecc63..3aaade80d5 100644 --- a/application/cs/configuration.texy +++ b/application/cs/configuration.texy @@ -14,10 +14,11 @@ application: debugger: ... # (bool) výchozí je true # bude se při chybě volat error-presenter? - catchExceptions: ... # (bool) výchozí je true v produkčním režimu + # má efekt pouze ve vývojářském režimu + catchExceptions: ... # (bool) výchozí je true # název error-presenteru - errorPresenter: Error # (string) výchozí je 'Nette:Error' + errorPresenter: Error # (string|array) výchozí je 'Nette:Error' # definuje pravidla pro překlad názvu presenteru na třídu mapping: ... @@ -27,7 +28,14 @@ application: silentLinks: ... # (bool) výchozí je false ``` -Protože ve vývojovém režimu se error-presentery standardně nevolají a chybu zobrazí až Tracy, změnou hodnoty `catchExceptions` na `true` můžeme při vývoji ověřit jejich správnou funkčnost. +Od `nette/application` verze 3.2 lze definovat dvojici error-presenterů: + +```neon +application: + errorPresenter: + 4xx: Error4xx # pro výjimku Nette\Application\BadRequestException + 5xx: Error5xx # pro ostatní výjimky +``` Volba `silentLinks` určuje, jak se Nette zachová ve vývojářském režimu, když selže generování odkazu (třeba proto, že neexistuje presenter, atd). Výchozí hodnota `false` znamená, že Nette vyhodí `E_USER_WARNING` chybu. Nastavením na `true` dojde k potlačení této chybové hlášky. V produkčním prostředí se `E_USER_WARNING` vyvolá vždy. Toto chování můžeme také ovlivnit nastavením proměnné presenteru [$invalidLinkMode|creating-links#neplatne-odkazy]. diff --git a/application/cs/modules.texy b/application/cs/modules.texy index 2cb3e42719..dd58b910d4 100644 --- a/application/cs/modules.texy +++ b/application/cs/modules.texy @@ -108,8 +108,7 @@ Začněme ukázkou, která moduly nepoužívá. Budeme jen chtít, aby třídy p ```neon application: - mapping: - *: App\Presenters\*Presenter + mapping: App\Presenters\*Presenter ``` Název presenteru se nahradí za hvezdičku v masce třídy a výsledkem je název třídy. Snadné! @@ -145,4 +144,4 @@ application: *: [App\Modules, *, Presenters\*Presenter] ``` -Výchozí hodnotou je `*: *Module\*Presenter`. +Výchozí hodnotou je `*Module\*Presenter`. diff --git a/application/de/configuration.texy b/application/de/configuration.texy index da3a0fcebf..17fb1ccc00 100644 --- a/application/de/configuration.texy +++ b/application/de/configuration.texy @@ -13,11 +13,12 @@ Anwendung: # zeigt das Feld "Nette Anwendung" in Tracy BlueScreen? debugger: ... # (bool) standardmäßig true - # wird der error-presenter im Fehlerfall aufgerufen? - catchExceptions: ... # (bool) steht im Produktionsmodus standardmäßig auf true + # wird error-presenter im Fehlerfall aufgerufen? + # hat nur im Entwicklermodus Auswirkungen + catchExceptions: ... # (bool) ist standardmäßig true # Name des Fehlermelders - errorPresenter: Error # (string) Standardwert ist 'Nette:Error' + errorPresenter: Error # (string|array) Standardwert ist 'Nette:Error' # definiert die Regeln für die Auflösung des Presenter-Namens in eine Klasse mapping: ... @@ -27,7 +28,14 @@ Anwendung: silentLinks: ... # (bool) ist standardmäßig auf false eingestellt ``` -Da Fehlerpräsenter im Entwicklungsmodus standardmäßig nicht aufgerufen werden und die Fehler von Tracy angezeigt werden, hilft das Ändern des Wertes `catchExceptions` in `true` dabei, zu überprüfen, ob die Fehlerpräsenter während der Entwicklung korrekt funktionieren. +Ab `nette/application` Version 3.2 ist es möglich, ein Paar von Fehlerpräsentern zu definieren: + +```neon +application: + errorPresenter: + 4xx: Error4xx # für Nette\Application\BadRequestException + 5xx: Error5xx # für andere Ausnahmen +``` Die Option `silentLinks` legt fest, wie sich Nette im Entwicklermodus verhält, wenn die Link-Generierung fehlschlägt (z. B. weil kein Presenter vorhanden ist usw.). Der Standardwert `false` bedeutet, dass Nette `E_USER_WARNING` auslöst. Die Einstellung `true` unterdrückt diese Fehlermeldung. In einer Produktionsumgebung wird immer `E_USER_WARNING` aufgerufen. Wir können dieses Verhalten auch beeinflussen, indem wir die Presenter-Variable [$invalidLinkMode |creating-links#Invalid Links] setzen. diff --git a/application/de/modules.texy b/application/de/modules.texy index fcdf4331c4..090bd4702e 100644 --- a/application/de/modules.texy +++ b/application/de/modules.texy @@ -108,8 +108,7 @@ Beginnen wir mit einem Beispiel, das keine Module verwendet. Wir wollen nur, das ```neon application: - mapping: - *: App\Presenters\*Presenter + mapping: App\Presenters\*Presenter ``` Der Name des Presenters wird durch das Sternchen in der Klassenmaske ersetzt und das Ergebnis ist der Klassenname. Einfach! @@ -145,4 +144,4 @@ application: *: [App\Modules, *, Presenters\*Presenter] ``` -Der Standardwert ist `*: *Module\*Presenter`. +Der Standardwert ist `*Module\*Presenter`. diff --git a/application/el/configuration.texy b/application/el/configuration.texy index 01b036704b..8b29cf2cc6 100644 --- a/application/el/configuration.texy +++ b/application/el/configuration.texy @@ -13,11 +13,12 @@ application: # δείχνει τον πίνακα "Nette Application" στο Tracy BlueScreen? debugger: ... # (bool) προεπιλογή true - # θα καλείται ο παρουσιαστής σφαλμάτων σε περίπτωση σφάλματος; - catchExceptions: ... # (bool) προεπιλεγμένη τιμή true σε κατάσταση παραγωγής + # θα κληθεί ο παρουσιαστής σφαλμάτων στο σφάλμα; + # έχει αποτέλεσμα μόνο σε λειτουργία προγραμματιστή + catchExceptions: ... # (bool) προεπιλογή true # όνομα του error-presenter - errorPresenter: Error # (string) προεπιλογή 'Nette:Error' + errorPresenter: Error # (string|array) προεπιλογή 'Nette:Error' # ορίζει τους κανόνες για την επίλυση του ονόματος του παρουσιαστή σε μια κλάση mapping: ... @@ -27,7 +28,14 @@ application: silentLinks: ... # (bool) προεπιλογή σε false ``` -Επειδή οι παρουσιαστές σφαλμάτων δεν καλούνται εξ ορισμού σε κατάσταση ανάπτυξης και τα σφάλματα εμφανίζονται από το Tracy, η αλλαγή της τιμής `catchExceptions` σε `true` βοηθάει στην επαλήθευση της σωστής λειτουργίας των παρουσιαστών σφαλμάτων κατά την ανάπτυξη. +Από την έκδοση 3.2 του `nette/application` είναι δυνατό να ορίσετε ένα ζεύγος παρουσιαστών σφαλμάτων: + +```neon +application: + errorPresenter: + 4xx: Error4xx # για την εξαίρεση Nette\Application\BadRequestException + 5xx: Error5xx # για άλλες εξαιρέσεις +``` Η επιλογή `silentLinks` καθορίζει τον τρόπο με τον οποίο η Nette συμπεριφέρεται στη λειτουργία ανάπτυξης όταν η δημιουργία συνδέσμων αποτυγχάνει (για παράδειγμα, επειδή δεν υπάρχει παρουσιαστής κ.λπ.). Η προεπιλεγμένη τιμή `false` σημαίνει ότι η Nette ενεργοποιεί το `E_USER_WARNING`. Η ρύθμιση σε `true` καταστέλλει αυτό το μήνυμα σφάλματος. Σε περιβάλλον παραγωγής, το `E_USER_WARNING` ενεργοποιείται πάντα. Μπορούμε επίσης να επηρεάσουμε αυτή τη συμπεριφορά θέτοντας τη μεταβλητή του παρουσιαστή [$invalidLinkMode |creating-links#Invalid Links]. diff --git a/application/el/modules.texy b/application/el/modules.texy index b2bb1dffd0..3277cccce0 100644 --- a/application/el/modules.texy +++ b/application/el/modules.texy @@ -108,8 +108,7 @@ class DashboardPresenter extends Nette\Application\UI\Presenter ```neon application: - mapping: - *: App\Presenters\*Presenter + mapping: App\Presenters\*Presenter ``` Το όνομα του παρουσιαστή αντικαθίσταται με τον αστερίσκο στη μάσκα κλάσης και το αποτέλεσμα είναι το όνομα της κλάσης. Εύκολο! @@ -145,4 +144,4 @@ application: *: [App\Modules, *, Presenters\*Presenter] ``` -Η προεπιλεγμένη τιμή είναι `*: *Module\*Presenter`. +Η προεπιλεγμένη τιμή είναι `*Module\*Presenter`. diff --git a/application/en/configuration.texy b/application/en/configuration.texy index 208194e78f..89036a69a8 100644 --- a/application/en/configuration.texy +++ b/application/en/configuration.texy @@ -14,10 +14,11 @@ application: debugger: ... # (bool) defaults to true # will error-presenter be called on error? - catchExceptions: ... # (bool) defaults to true in production mode + # has effect only in developer mode + catchExceptions: ... # (bool) defaults to true # name of error-presenter - errorPresenter: Error # (string) defaults to 'Nette:Error' + errorPresenter: Error # (string|array) defaults to 'Nette:Error' # defines the rules for resolving the presenter name to a class mapping: ... @@ -27,7 +28,14 @@ application: silentLinks: ... # (bool) defaults to false ``` -Because error-presenters are not called by default in development mode and the errors are displayed by Tracy, changing the value `catchExceptions` to `true` helps to verify that error-presenters works correct during development. +As of `nette/application` version 3.2 it is possible to define a pair of error-presenters: + +```neon +application: + errorPresenter: + 4xx: Error4xx # for Nette\Application\BadRequestException + 5xx: Error5xx # for other exceptions +``` Option `silentLinks` determines how Nette behaves in developer mode when link generation fails (for example, because there is no presenter, etc). The default value `false` means that Nette triggers `E_USER_WARNING`. Setting to `true` suppresses this error message. In a production environment, `E_USER_WARNING` is always invoked. We can also influence this behavior by setting the presenter variable [$invalidLinkMode |creating-links#Invalid Links]. diff --git a/application/en/modules.texy b/application/en/modules.texy index 6312143fdd..376ac872b9 100644 --- a/application/en/modules.texy +++ b/application/en/modules.texy @@ -108,8 +108,7 @@ Let's start with a sample that doesn't use modules. We'll just want the presente ```neon application: - mapping: - *: App\Presenters\*Presenter + mapping: App\Presenters\*Presenter ``` The presenter name is replaced with the asterisk in the class mask and the result is the class name. Easy! @@ -145,4 +144,4 @@ application: *: [App\Modules, *, Presenters\*Presenter] ``` -The default value is `*: *Module\*Presenter`. +The default value is `*Module\*Presenter`. diff --git a/application/es/configuration.texy b/application/es/configuration.texy index 5dfa60ab36..0aa01db958 100644 --- a/application/es/configuration.texy +++ b/application/es/configuration.texy @@ -14,10 +14,11 @@ application: debugger: ... # (bool) por defecto true # ¿se llamará al presentador de errores en caso de error? - catchExceptions: ... # (bool) por defecto a true en modo producción + # sólo tiene efecto en modo desarrollador + catchExceptions: ... # (bool) por defecto true # nombre del presentador de errores - errorPresenter: Error # (string) por defecto 'Nette:Error' + errorPresenter: Error # (string|array) por defecto 'Nette:Error' # define las reglas para resolver el nombre del presentador a una clase mapping: ... @@ -27,7 +28,14 @@ application: silentLinks: ... # (bool) por defecto false ``` -Debido a que los presentadores de errores no son llamados por defecto en modo desarrollo y los errores son mostrados por Tracy, cambiar el valor `catchExceptions` a `true` ayuda a verificar que los presentadores de errores funcionan correctamente durante el desarrollo. +A partir de la versión 3.2 de `nette/application` es posible definir un par de presentadores de errores: + +```neon +application: + errorPresenter: + 4xx: Error4xx # para Nette\Application\BadRequestException + 5xx: Error5xx # para otras excepciones +``` La opción `silentLinks` determina cómo se comporta Nette en modo desarrollo cuando falla la generación de enlaces (por ejemplo, porque no hay presentador, etc). El valor por defecto `false` significa que Nette activa `E_USER_WARNING`. El valor `true` suprime este mensaje de error. En un entorno de producción, siempre se invoca `E_USER_WARNING`. También podemos influir en este comportamiento configurando la variable del presentador [$invalidLinkMode |creating-links#Invalid Links]. diff --git a/application/es/modules.texy b/application/es/modules.texy index e183346e5f..644cab5c1f 100644 --- a/application/es/modules.texy +++ b/application/es/modules.texy @@ -108,8 +108,7 @@ Empecemos con un ejemplo que no utiliza módulos. Sólo querremos que las clases ```neon application: - mapping: - *: App\Presenters\*Presenter + mapping: App\Presenters\*Presenter ``` El nombre del presentador se sustituye por el asterisco en la máscara de clase y el resultado es el nombre de la clase. Muy fácil. @@ -145,4 +144,4 @@ application: *: [App\Modules, *, Presenters\*Presenter] ``` -El valor por defecto es `*: *Module\*Presenter`. +El valor por defecto es `*Module\*Presenter`. diff --git a/application/fr/configuration.texy b/application/fr/configuration.texy index b358ce1617..cd0c4f07c0 100644 --- a/application/fr/configuration.texy +++ b/application/fr/configuration.texy @@ -13,11 +13,12 @@ application: # affiche le panneau "Nette Application" dans Tracy BlueScreen ? debugger: ... # (bool) par défaut à true - # le présentateur d'erreur sera-t-il appelé en cas d'erreur ? - catchExceptions: ... # (bool) vaut true par défaut en mode production + # le présentateur d'erreurs sera-t-il appelé en cas d'erreur ? + # n'a d'effet qu'en mode développeur +catchExceptions : ... # (bool) valeur par défaut : true # nom du présentateur d'erreur - errorPresenter: Error # (string) vaut par défaut 'Nette:Error'. + errorPresenter: Error # (string|array) vaut par défaut 'Nette:Error'. # définit les règles pour résoudre le nom du présentateur vers une classe mapping: ... @@ -27,7 +28,14 @@ application: silentLinks: ... # (bool) valeur par défaut: false ``` -Comme les présentateurs d'erreurs ne sont pas appelés par défaut en mode développement et que les erreurs sont affichées par Tracy, le fait de changer la valeur `catchExceptions` en `true` permet de vérifier que les présentateurs d'erreurs fonctionnent correctement pendant le développement. +Depuis la version 3.2 de `nette/application`, il est possible de définir une paire de présentateurs d'erreurs : + +```neon +application: + errorPresenter: + 4xx: Error4xx # pour NetteApplicationBadRequestException + 5xx: Error5xx # pour les autres exceptions +``` L'option `silentLinks` détermine comment Nette se comporte en mode développeur lorsque la génération de liens échoue (par exemple, parce qu'il n'y a pas de présentateur, etc). La valeur par défaut `false` signifie que Nette déclenche `E_USER_WARNING`. Le réglage sur `true` supprime ce message d'erreur. Dans un environnement de production, `E_USER_WARNING` est toujours invoqué. Nous pouvons également influencer ce comportement en définissant la variable du présentateur [$invalidLinkMode |creating-links#Invalid Links]. diff --git a/application/fr/modules.texy b/application/fr/modules.texy index ade58f61b9..754e97b5ad 100644 --- a/application/fr/modules.texy +++ b/application/fr/modules.texy @@ -108,8 +108,7 @@ Commençons par un exemple qui n'utilise pas de modules. Nous voulons simplement ```neon application: - mapping: - *: App\Presenters\*Presenter + mapping: App\Presenters\*Presenter ``` Le nom du présentateur est remplacé par l'astérisque dans le masque de classe et le résultat est le nom de la classe. Facile ! @@ -145,4 +144,4 @@ application: *: [App\Modules, *, Presenters\*Presenter] ``` -La valeur par défaut est `*: *Module\*Presenter`. +La valeur par défaut est `*Module\*Presenter`. diff --git a/application/hu/configuration.texy b/application/hu/configuration.texy index fc96b2a039..4daecdf769 100644 --- a/application/hu/configuration.texy +++ b/application/hu/configuration.texy @@ -14,10 +14,11 @@ application: debugger: ... # (bool) alapértelmezett értéke true # error-presenter meghívásra kerül hiba esetén? - catchExceptions: ... # (bool) alapértelmezés szerint true termelési üzemmódban. + # csak fejlesztői módban van hatása + catchExceptions: ... # (bool) alapértelmezés szerint true # error-presenter neve - errorPresenter: Error # (string) alapértelmezett értéke 'Nette:Error'. + errorPresenter: Error # (string|array) alapértelmezett értéke 'Nette:Error'. # meghatározza a prezenter nevének egy osztályra való feloldására vonatkozó szabályokat. mapping: ... @@ -27,7 +28,14 @@ application: silentLinks: ... # (bool) alapértelmezett értéke false ``` -Mivel a hiba-bemutatókat alapértelmezés szerint nem hívja meg a program fejlesztési módban, és a hibákat a Tracy jeleníti meg, a `catchExceptions` érték `true` -re történő módosítása segít ellenőrizni, hogy a hiba-bemutatók helyesen működnek-e a fejlesztés során. +A `nette/application` 3.2-es verziójától kezdve lehetőség van hiba-bemutatók párjának definiálására: + +```neon +application: + errorPresenter: + 4xx: Error4xx # Nette\Application\BadRequestException esetében + 5xx: Error5xx # egyéb kivételek esetén +``` A `silentLinks` opció határozza meg, hogy a Nette hogyan viselkedjen fejlesztői módban, ha a linkgenerálás sikertelen (például mert nincs prezenter stb.). Az alapértelmezett `false` érték azt jelenti, hogy a Nette a `E_USER_WARNING` opciót váltja ki. A `true` beállítása elnyomja ezt a hibaüzenetet. Gyártási környezetben a `E_USER_WARNING` mindig meghívásra kerül. Ezt a viselkedést a [$invalidLinkMode |creating-links#Invalid Links] prezenter változó beállításával is befolyásolhatjuk. diff --git a/application/hu/modules.texy b/application/hu/modules.texy index 5dde2d1a36..e4ec0d80aa 100644 --- a/application/hu/modules.texy +++ b/application/hu/modules.texy @@ -108,8 +108,7 @@ Kezdjük egy olyan példával, amely nem használ modulokat. Csak azt akarjuk, h ```neon application: - mapping: - *: App\Presenters\*Presenter + mapping: App\Presenters\*Presenter ``` Az osztálymaszkban a prezenter nevét csillaggal helyettesítjük, és az eredmény az osztály neve lesz. Easy! @@ -145,4 +144,4 @@ application: *: [App\Modules, *, Presenters\*Presenter] ``` -Az alapértelmezett érték a `*: *Module\*Presenter`. +Az alapértelmezett érték a `*Module\*Presenter`. diff --git a/application/it/configuration.texy b/application/it/configuration.texy index 2fc47b2fab..b51348623a 100644 --- a/application/it/configuration.texy +++ b/application/it/configuration.texy @@ -13,11 +13,12 @@ application: # mostra il pannello "Applicazione Nette" in Tracy BlueScreen? debugger: ... # (bool) predefinito a true - # Il presentatore di errori sarà chiamato in caso di errore? - catchExceptions: ... # (bool) predefinito a true in modalità di produzione + # Il presentatore di errori sarà chiamato su un errore? + # ha effetto solo in modalità sviluppatore + catchExceptions: ... # (bool) predefinito a true # nome del presentatore di errori - errorPresenter: Error # (string) predefinito a 'Nette:Error'. + errorPresenter: Error # (string|array) predefinito a 'Nette:Error'. # definisce le regole per risolvere il nome del presentatore in una classe mapping: ... @@ -27,7 +28,14 @@ application: silentLinks: ... # (bool) predefinito a false ``` -Poiché i presentatori di errori non vengono richiamati per impostazione predefinita in modalità di sviluppo e gli errori vengono visualizzati da Tracy, la modifica del valore `catchExceptions` a `true` aiuta a verificare che i presentatori di errori funzionino correttamente durante lo sviluppo. +Dalla versione 3.2 di `nette/application` è possibile definire una coppia di presentatori di errori: + +```neon +application: + errorPresenter: + 4xx: Error4xx # per NetteApplicationBadRequestException + 5xx: Error5xx # per altre eccezioni +``` L'opzione `silentLinks` determina il comportamento di Nette in modalità sviluppatore quando la generazione dei collegamenti fallisce (ad esempio, perché non c'è un presentatore, ecc.). Il valore predefinito `false` significa che Nette attiva `E_USER_WARNING`. L'impostazione di `true` sopprime questo messaggio di errore. In un ambiente di produzione, `E_USER_WARNING` viene sempre invocato. Si può anche influenzare questo comportamento impostando la variabile del presentatore [$invalidLinkMode |creating-links#Invalid Links]. diff --git a/application/it/modules.texy b/application/it/modules.texy index 55ee0c0696..76b8af4e23 100644 --- a/application/it/modules.texy +++ b/application/it/modules.texy @@ -108,8 +108,7 @@ Cominciamo con un esempio che non usa moduli. Vogliamo solo che le classi del pr ```neon application: - mapping: - *: App\Presenters\*Presenter + mapping: App\Presenters\*Presenter ``` Il nome del presentatore viene sostituito con l'asterisco nella maschera della classe e il risultato è il nome della classe. Facile! @@ -145,4 +144,4 @@ application: *: [App\Modules, *, Presenters\*Presenter] ``` -Il valore predefinito è `*: *Module\*Presenter`. +Il valore predefinito è `*Module\*Presenter`. diff --git a/application/pl/configuration.texy b/application/pl/configuration.texy index 243df5360c..e7de3cf4b9 100644 --- a/application/pl/configuration.texy +++ b/application/pl/configuration.texy @@ -13,11 +13,12 @@ application: # pokazać panel "Nette Application" w Tracy BlueScreen? debugger: ... # (bool) domyślnie jest true - # czy error-presenter zostanie wywołany na błędzie? - catchExceptions: ... # (bool) domyślnie przyjmuje wartość true w trybie produkcyjnym + # czy error-presenter będzie wywoływany przy błędzie? + # działa tylko w trybie deweloperskim + catchExceptions: ... # (bool) domyślnie true # error-presenter name - errorPresenter: Error # (string) domyślnie 'Nette:Error' + errorPresenter: Error # (string|array) domyślnie 'Nette:Error' # definiuje zasady rozwiązywania nazwy prezentera do klasy mapping: ... @@ -27,7 +28,14 @@ application: silentLinks: ... # (bool) domyślnie jest false ``` -Ponieważ prezentery błędów nie są domyślnie wywoływane w trybie deweloperskim, a błąd jest wyświetlany tylko przez Tracy, zmiana wartości `catchExceptions` na `true` pozwala nam zweryfikować ich poprawną funkcjonalność w trakcie rozwoju. +Od wersji `nette/application` 3.2 możliwe jest zdefiniowanie pary prezenterów błędów: + +```neon +application: + errorPresenter: + 4xx: Error4xx # dla wyjątku Nette\Application\BadRequestException + 5xx: Error5xx # dla innych wyjątków +``` Opcja `silentLinks` określa, jak Nette zachowuje się w trybie rozwoju, gdy generowanie linków nie powiedzie się (np. z powodu braku prezentera itp.). Domyślna wartość `false` oznacza, że Nette rzuci błąd `E_USER_WARNING`. Ustawienie go na `true` spowoduje wyeliminowanie tego komunikatu o błędzie. W środowisku produkcyjnym, `E_USER_WARNING` jest zawsze podniesiony. Na to zachowanie można również wpłynąć poprzez ustawienie zmiennej prezentera [$invalidLinkMode |creating-links#Invalid-Links]. diff --git a/application/pl/modules.texy b/application/pl/modules.texy index a2a4480132..488d8f50a3 100644 --- a/application/pl/modules.texy +++ b/application/pl/modules.texy @@ -108,8 +108,7 @@ Zacznijmy od próbki, która nie korzysta z modułów. Będziemy chcieli, aby kl ```neon application: - mapping: - *: App\Presenters\*Presenter + mapping: App\Presenters\*Presenter ``` Zastąp nazwę prezentera gwiazdką w masce klasy, a wynikiem będzie nazwa klasy. Spokojnie! @@ -145,4 +144,4 @@ application: *: [App\Modules, *, Presenters\*Presenter] ``` -Wartość domyślna to `*: *Module\*Presenter`. +Wartość domyślna to `*Module\*Presenter`. diff --git a/application/pt/configuration.texy b/application/pt/configuration.texy index b4561d709c..fa13aa7950 100644 --- a/application/pt/configuration.texy +++ b/application/pt/configuration.texy @@ -13,11 +13,12 @@ application: # mostra painel "Aplicação Nette" em Tracy BlueScreen? debugger: ... # (bool) por omissão - # será que o apresentador de erro será chamado por erro? - catchExceptions: ... # (bool) é o padrão verdadeiro no modo de produção + # O apresentador de erros será chamado no erro? + # tem efeito somente no modo de desenvolvedor + catchExceptions: ... # (bool) tem como padrão true # nome do apresentador de erro - errorPresenter: Error # (string) padrão para 'Nette:Erro'. + errorPresenter: Error # (string|array) padrão para 'Nette:Erro'. # define as regras para resolver o nome do apresentador para uma classe mapping: ... @@ -27,7 +28,14 @@ application: silentLinks: ... # (bool) falha em falso ``` -Como os apresentadores de erros não são chamados por padrão no modo de desenvolvimento e os erros são exibidos por Tracy, alterar o valor `catchExceptions` para `true` ajuda a verificar se os apresentadores de erros funcionam corretamente durante o desenvolvimento. +A partir da versão 3.2 do site `nette/application`, é possível definir um par de apresentadores de erros: + +```neon +application: + errorPresenter: + 4xx: Error4xx # para Nette\Application\BadRequestException + 5xx: Error5xx # para outras exceções +``` A opção `silentLinks` determina como Nette se comporta em modo desenvolvedor quando a geração de links falha (por exemplo, porque não há apresentador, etc.). O valor padrão `false` significa que a Nette aciona `E_USER_WARNING`. A configuração para `true` suprime esta mensagem de erro. Em um ambiente de produção, `E_USER_WARNING` é sempre invocado. Também podemos influenciar este comportamento definindo a variável apresentadora [$invalidLinkMode |creating-links#Invalid Links]. diff --git a/application/pt/modules.texy b/application/pt/modules.texy index 35ee3786d3..372dd0e467 100644 --- a/application/pt/modules.texy +++ b/application/pt/modules.texy @@ -108,8 +108,7 @@ Vamos começar com uma amostra que não utiliza módulos. Queremos apenas que as ```neon application: - mapping: - *: App\Presenters\*Presenter + mapping: App\Presenters\*Presenter ``` O nome do apresentador é substituído pelo asterisco na máscara da classe e o resultado é o nome da classe. Fácil! @@ -145,4 +144,4 @@ application: *: [App\Modules, *, Presenters\*Presenter] ``` -O valor padrão é `*: *Module\*Presenter`. +O valor padrão é `*Module\*Presenter`. diff --git a/application/ro/configuration.texy b/application/ro/configuration.texy index e1ce662525..a4c1e61233 100644 --- a/application/ro/configuration.texy +++ b/application/ro/configuration.texy @@ -13,11 +13,12 @@ application: # afișează panoul "Nette Application" în Tracy BlueScreen? debugger: ... # (bool) valoarea implicită este true - # error-presenter va fi apelat în caz de eroare? - catchExceptions: ... # (bool) implicit la true în modul de producție + # va fi apelat error-presenter la eroare? + # are efect numai în modul dezvoltator + catchExceptions: ... # (bool) implicit la true # numele prezentatorului de erori - errorPresenter: Error # (string) valoarea implicită este "Nette:Error" (Nette:Error) + errorPresenter: Error # (string|array) valoarea implicită este "Nette:Error" (Nette:Error) # definește regulile de rezolvare a numelui prezentatorului la o clasă mapping: ... @@ -27,7 +28,14 @@ application: silentLinks: ... # (bool) valoarea implicită este false ``` -Deoarece error-presenters nu este apelat în mod implicit în modul de dezvoltare, iar erorile sunt afișate de Tracy, schimbarea valorii `catchExceptions` în `true` ajută la verificarea funcționării corecte a error-presenters în timpul dezvoltării. +Începând cu `nette/application` versiunea 3.2, este posibilă definirea unei perechi de prezentatori de erori: + +```neon +application: + errorPresenter: + 4xx: Error4xx # pentru Nette\Application\BadRequestException + 5xx: Error5xx # pentru alte excepții +``` Opțiunea `silentLinks` determină modul în care se comportă Nette în modul de dezvoltare atunci când generarea legăturilor eșuează (de exemplu, pentru că nu există un prezentator etc.). Valoarea implicită `false` înseamnă că Nette declanșează `E_USER_WARNING`. Setarea la `true` suprimă acest mesaj de eroare. Într-un mediu de producție, `E_USER_WARNING` este întotdeauna invocat. De asemenea, putem influența acest comportament prin setarea variabilei presenter [$invalidLinkMode |creating-links#Invalid Links]. diff --git a/application/ro/modules.texy b/application/ro/modules.texy index bc8e11b0d2..1e7cd0fee4 100644 --- a/application/ro/modules.texy +++ b/application/ro/modules.texy @@ -108,8 +108,7 @@ Să începem cu un exemplu care nu folosește module. Vom dori doar ca clasele d ```neon application: - mapping: - *: App\Presenters\*Presenter + mapping: App\Presenters\*Presenter ``` Numele prezentatorului este înlocuit cu un asterisc în masca clasei, iar rezultatul este numele clasei. Ușor! @@ -145,4 +144,4 @@ application: *: [App\Modules, *, Presenters\*Presenter] ``` -Valoarea implicită este `*: *Module\*Presenter`. +Valoarea implicită este `*Module\*Presenter`. diff --git a/application/ru/configuration.texy b/application/ru/configuration.texy index 0216233dfd..0d3382d5ac 100644 --- a/application/ru/configuration.texy +++ b/application/ru/configuration.texy @@ -13,11 +13,12 @@ application: # отображает вкладку "Nette Application" на синем экране Tracy? debugger: ... # (bool) по умолчанию true - # будет ли вызываться презентер ошибок при ошибке? - catchExceptions: ... # (bool) по умолчанию true на «боевом» сервере + # будет ли вызываться error-presenter при ошибке? + # имеет значение только в режиме разработчика + catchExceptions: ... # (bool) по умолчанию равно true # имя презентера ошибок - errorPresenter: Error # (string) по умолчанию 'Nette:Error' + errorPresenter: Error # (string|array) по умолчанию 'Nette:Error' # определяет правила для преобразования имени ведущего в класс mapping: ... @@ -27,7 +28,14 @@ application: silentLinks: ... # (bool) по умолчанию false ``` -Поскольку в режиме разработки презентеры ошибок по умолчанию не вызываются, а ошибки отображаются Tracy, изменение значения `catchExceptions` на `true` помогает проверить корректность работы презентеров ошибок во время разработки. +Начиная с версии `nette/application` 3.2 можно определить пару презентеров ошибок: + +```neon +application: + errorPresenter: + 4xx: Error4xx # для Nette\Application\BadRequestException + 5xx: Error5xx # для других исключений +``` Опция `silentLinks` определяет, как Nette ведет себя в режиме разработчика, когда генерация ссылок не удается (например, из-за отсутствия презентера и т. д.). Значение по умолчанию `false` означает, что Nette запускает `E_USER_WARNING`. Установка значения `true` подавляет это сообщение об ошибке. В производственной среде всегда вызывается `E_USER_WARNING`. Мы также можем повлиять на это поведение, установив переменную презентера [$invalidLinkMode |creating-links#Invalid-Links]. diff --git a/application/ru/modules.texy b/application/ru/modules.texy index b8d3e626c2..e7a6b8b277 100644 --- a/application/ru/modules.texy +++ b/application/ru/modules.texy @@ -108,8 +108,7 @@ class DashboardPresenter extends Nette\Application\UI\Presenter ```neon application: - mapping: - *: App\Presenters\*Presenter + mapping: App\Presenters\*Presenter ``` Имя презентера заменяется звездочкой, и в результате получается название класса. Легко! @@ -145,4 +144,4 @@ application: *: [App\Modules, *, Presenters\*Presenter] ``` -Значение по умолчанию - `*: *Module\*Presenter`. +Значение по умолчанию - `*Module\*Presenter`. diff --git a/application/sl/configuration.texy b/application/sl/configuration.texy index e05f269f44..8111f98635 100644 --- a/application/sl/configuration.texy +++ b/application/sl/configuration.texy @@ -13,11 +13,12 @@ application: # prikazuje ploščo "Nette Application" v programu Tracy BlueScreen? debugger: ... # (bool) privzeto je true - # ali se ob napaki pokliče error-presenter? - catchExceptions: ... # (bool) privzeto true v produkcijskem načinu + # se bo ob napaki poklical predstavnik napak? + # učinkuje samo v načinu za razvijalce + catchExceptions: ... # (bool) privzeto true # ime programa error-presenter - errorPresenter: Error # (string) privzeto 'Nette:Error' + errorPresenter: Error # (string|array) privzeto 'Nette:Error' # določa pravila za razrešitev imena predstavnika na razred mapping: ... @@ -27,7 +28,14 @@ application: silentLinks: ... # (bool) privzeto je false ``` -Ker se v razvojnem načinu predstavniki napak privzeto ne kličejo, napake pa prikazuje Tracy, sprememba vrednosti `catchExceptions` v `true` pomaga preveriti, ali predstavniki napak med razvojem delujejo pravilno. +Od različice `nette/application` 3.2 je mogoče določiti par predstavnikov napak: + +```neon +application: + errorPresenter: + 4xx: Error4xx # za Nette\Application\BadRequestException + 5xx: Error5xx # za druge izjeme +``` Možnost `silentLinks` določa, kako se Nette obnaša v razvojnem načinu, ko generiranje povezav ne uspe (na primer ker ni predstavnika itd.). Privzeta vrednost `false` pomeni, da Nette sproži `E_USER_WARNING`. Nastavitev na `true` to sporočilo o napaki odpravi. V produkcijskem okolju se vedno sproži `E_USER_WARNING`. Na to obnašanje lahko vplivamo tudi z nastavitvijo spremenljivke presenterja [$invalidLinkMode |creating-links#Invalid Links]. diff --git a/application/sl/modules.texy b/application/sl/modules.texy index d37ea342b1..c0c01ae28d 100644 --- a/application/sl/modules.texy +++ b/application/sl/modules.texy @@ -108,8 +108,7 @@ Začnimo z vzorcem, ki ne uporablja modulov. Želeli bomo le, da imajo razredi p ```neon application: - mapping: - *: App\Presenters\*Presenter + mapping: App\Presenters\*Presenter ``` V maski razreda se ime predvajalnika nadomesti z zvezdico, rezultat pa je ime razreda. Enostavno! @@ -145,4 +144,4 @@ application: *: [App\Modules, *, Presenters\*Presenter] ``` -Privzeta vrednost je `*: *Module\*Presenter`. +Privzeta vrednost je `*Module\*Presenter`. diff --git a/application/tr/configuration.texy b/application/tr/configuration.texy index 8949e7d7e8..14027ca069 100644 --- a/application/tr/configuration.texy +++ b/application/tr/configuration.texy @@ -13,11 +13,12 @@ application: # Tracy BlueScreen'de "Nette Application" panelini gösterir? debugger: ... # (bool) varsayılan olarak true - # error-presenter hata durumunda çağrılacak mı? - catchExceptions: ... # (bool) üretim modunda varsayılan olarak true + # error-presenter hata üzerine çağrılacak mı? + # sadece geliştirici modunda etkilidir + catchExceptions: ... # (bool) varsayılan olarak true # hata sunucusunun adı - errorPresenter: Error # (string) varsayılan olarak 'Nette:Error' + errorPresenter: Error # (string|array) varsayılan olarak 'Nette:Error' # sunum yapan kişinin adını bir sınıfa çözümlemek için kuralları tanımlar mapping: ... @@ -27,7 +28,14 @@ application: silentLinks: ... # (bool) varsayılan değer false ``` -Hata sunucuları geliştirme modunda varsayılan olarak çağrılmadığından ve hatalar Tracy tarafından görüntülendiğinden, `catchExceptions` değerini `true` olarak değiştirmek, hata sunucularının geliştirme sırasında doğru çalıştığını doğrulamaya yardımcı olur. +`nette/application` sürüm 3.2'den itibaren bir çift hata sunucusu tanımlamak mümkündür: + +```neon +application: + errorPresenter: + 4xx: Error4xx # Nette\Application\BadRequestException için + 5xx: Error5xx # diğer istisnalar için +``` `silentLinks` seçeneği, bağlantı oluşturma başarısız olduğunda (örneğin, sunum yapan kişi olmadığından vb.) Nette'in geliştirici modunda nasıl davranacağını belirler. Varsayılan değer olan `false`, Nette'in `E_USER_WARNING` adresini tetikleyeceği anlamına gelir. `true` olarak ayarlanması bu hata mesajını bastırır. Bir üretim ortamında, `E_USER_WARNING` her zaman çağrılır. Bu davranışı, sunum yapan değişken [$invalidLinkMode'u |creating-links#Invalid Links] ayarlayarak da etkileyebiliriz. diff --git a/application/tr/modules.texy b/application/tr/modules.texy index e447d581bd..63da6e9e48 100644 --- a/application/tr/modules.texy +++ b/application/tr/modules.texy @@ -108,8 +108,7 @@ Modül kullanmayan bir örnekle başlayalım. Sadece sunum yapan sınıfların ` ```neon application: - mapping: - *: App\Presenters\*Presenter + mapping: App\Presenters\*Presenter ``` Sunum yapan kişinin adı sınıf maskesindeki yıldız işaretiyle değiştirilir ve sonuç sınıf adı olur. Kolay! @@ -145,4 +144,4 @@ application: *: [App\Modules, *, Presenters\*Presenter] ``` -Varsayılan değer `*: *Module\*Presenter`'dur. +Varsayılan değer `*Module\*Presenter`'dur. diff --git a/application/uk/configuration.texy b/application/uk/configuration.texy index 650875ec58..c6c1fe55bf 100644 --- a/application/uk/configuration.texy +++ b/application/uk/configuration.texy @@ -13,11 +13,12 @@ application: # відображає вкладку "Nette Application" на синьому екрані Tracy? debugger: ... # (bool) за замовчуванням true - # чи буде викликатися презентер помилок у разі помилки? - catchExceptions: ... # (bool) за замовчуванням true на "бойовому" сервері + # чи буде викликано error-presenter при помилці? + # має ефект тільки в режимі розробника + catchExceptions: ... # (bool) за замовчуванням дорівнює true # ім'я презентера помилок - errorPresenter: Error # (string) за замовчуванням 'Nette:Error' + errorPresenter: Error # (string|array) за замовчуванням 'Nette:Error' # визначає правила для перетворення імені ведучого в клас mapping: ... @@ -27,7 +28,14 @@ application: silentLinks: ... # (bool) за замовчуванням false ``` -Оскільки в режимі розробки презентери помилок за замовчуванням не викликаються, а помилки відображаються Tracy, зміна значення `catchExceptions` на `true` допомагає перевірити коректність роботи презентерів помилок під час розробки. +Починаючи з версії 3.2 `nette/application` можна визначити пару презентувальників помилок: + +```neon +application: + errorPresenter: + 4xx: Error4xx # для виключення Nette\Application\BadRequestException + 5xx: Error5xx # для інших винятків +``` Опція `silentLinks` визначає, як Nette поводиться в режимі розробника, коли генерація посилань не вдається (наприклад, через відсутність презентера тощо). Значення за замовчуванням `false` означає, що Nette запускає `E_USER_WARNING`. Встановлення значення `true` пригнічує це повідомлення про помилку. У виробничому середовищі завжди викликається `E_USER_WARNING`. Ми також можемо вплинути на цю поведінку, встановивши змінну презентера [$invalidLinkMode |creating-links#Invalid-Links]. diff --git a/application/uk/modules.texy b/application/uk/modules.texy index 5503142028..e660553440 100644 --- a/application/uk/modules.texy +++ b/application/uk/modules.texy @@ -108,8 +108,7 @@ class DashboardPresenter extends Nette\Application\UI\Presenter ```neon application: - mapping: - *: App\Presenters\*Presenter + mapping: App\Presenters\*Presenter ``` Ім'я презентера замінюється зірочкою, і в результаті виходить назва класу. Легко! @@ -145,4 +144,4 @@ application: *: [App\Modules, *, Presenters\*Presenter] ``` -Значення за замовчуванням - `*: *Module\*Presenter`. +Значення за замовчуванням - `*Module\*Presenter`. From 0195403f92ae74e7f32f4dbf399cd61e120caf0a Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 12 Mar 2024 17:03:07 +0100 Subject: [PATCH 060/137] floats: note about precision --- utils/bg/floats.texy | 3 +++ utils/cs/floats.texy | 3 +++ utils/de/floats.texy | 3 +++ utils/el/floats.texy | 3 +++ utils/en/floats.texy | 3 +++ utils/es/floats.texy | 3 +++ utils/fr/floats.texy | 3 +++ utils/hu/floats.texy | 3 +++ utils/it/floats.texy | 3 +++ utils/pl/floats.texy | 3 +++ utils/pt/floats.texy | 3 +++ utils/ro/floats.texy | 3 +++ utils/ru/floats.texy | 3 +++ utils/sl/floats.texy | 3 +++ utils/tr/floats.texy | 3 +++ utils/uk/floats.texy | 3 +++ 16 files changed, 48 insertions(+) diff --git a/utils/bg/floats.texy b/utils/bg/floats.texy index bb50d2f0ba..8842030811 100644 --- a/utils/bg/floats.texy +++ b/utils/bg/floats.texy @@ -42,6 +42,9 @@ echo Floats::areEqual($a, $b) ? 'same' : 'not same'; // same При опит за сравняване на `NAN` се получава изключение `\LogicException`. +.[tip] +Класът `Floats` толерира разлики, по-малки от `1e-10`. Ако трябва да работите с по-голяма точност, използвайте вместо това библиотеката BCMath. + Сравнение на плаващи стойности .[#toc-float-comparison] ======================================================= diff --git a/utils/cs/floats.texy b/utils/cs/floats.texy index b8d71ef7e2..6616523bba 100644 --- a/utils/cs/floats.texy +++ b/utils/cs/floats.texy @@ -42,6 +42,9 @@ echo Floats::areEqual($a, $b) ? 'same' : 'not same'; // same Při pokusu porovnávat `NAN` vyhodí výjimku `\LogicException`. +.[tip] +Třída `Floats` toleruje rozdíly menší než `1e-10`. Pokud potřebujete pracovat s větší přesností, použijte raději knihovnu BCMath. + Porovnávání floatů ================== diff --git a/utils/de/floats.texy b/utils/de/floats.texy index 89fe22cfa3..31d68bc1ea 100644 --- a/utils/de/floats.texy +++ b/utils/de/floats.texy @@ -42,6 +42,9 @@ echo Floats::areEqual($a, $b) ? 'gleich' : 'nicht gleich'; // gleich Beim Versuch, `NAN` zu vergleichen, kommt es zu einer `\LogicException` Ausnahme. +.[tip] +Die Klasse `Floats` toleriert Unterschiede, die kleiner sind als `1e-10`. Wenn Sie mit größerer Genauigkeit arbeiten müssen, verwenden Sie stattdessen die BCMath-Bibliothek. + Float-Vergleich .[#toc-float-comparison] ======================================== diff --git a/utils/el/floats.texy b/utils/el/floats.texy index 3125001c82..10682f5a1d 100644 --- a/utils/el/floats.texy +++ b/utils/el/floats.texy @@ -42,6 +42,9 @@ echo Floats::areEqual($a, $b) ? 'same': 'not same'; // ίδιο Όταν προσπαθεί να συγκρίνει το `NAN`, πετάει μια εξαίρεση `\LogicException`. +.[tip] +Η κλάση `Floats` ανέχεται διαφορές μικρότερες από `1e-10`. Αν θέλετε να εργαστείτε με μεγαλύτερη ακρίβεια, χρησιμοποιήστε τη βιβλιοθήκη BCMath. + Σύγκριση float .[#toc-float-comparison] ======================================= diff --git a/utils/en/floats.texy b/utils/en/floats.texy index 96bbe394e9..a186e97d5b 100644 --- a/utils/en/floats.texy +++ b/utils/en/floats.texy @@ -42,6 +42,9 @@ echo Floats::areEqual($a, $b) ? 'same' : 'not same'; // same When trying to compare `NAN`, it throws an `\LogicException` exception. +.[tip] +The `Floats` class tolerates differences less than `1e-10`. If you need to work with more precision, use the BCMath library instead. + Float Comparison ================ diff --git a/utils/es/floats.texy b/utils/es/floats.texy index 71989a6346..bfdf458cfa 100644 --- a/utils/es/floats.texy +++ b/utils/es/floats.texy @@ -42,6 +42,9 @@ echo Floats::areEqual($a, $b) ? 'same' : 'not same'; // same Al intentar comparar `NAN`, lanza una excepción `\LogicException`. +.[tip] +La clase `Floats` tolera diferencias inferiores a `1e-10`. Si necesita trabajar con más precisión, utilice en su lugar la biblioteca BCMath. + Comparación de flotadores .[#toc-float-comparison] ================================================== diff --git a/utils/fr/floats.texy b/utils/fr/floats.texy index 0ae4e0fd11..60824eb5d3 100644 --- a/utils/fr/floats.texy +++ b/utils/fr/floats.texy @@ -42,6 +42,9 @@ echo Floats::areEqual($a, $b) ? 'same' : 'not same'; // same Lorsque l'on essaie de comparer `NAN`, une exception `\LogicException` est levée. +.[tip] +La classe `Floats` tolère des différences inférieures à `1e-10`. Si vous devez travailler avec plus de précision, utilisez plutôt la bibliothèque BCMath. + Comparaison de flottants .[#toc-float-comparison] ================================================= diff --git a/utils/hu/floats.texy b/utils/hu/floats.texy index 64f72c88b3..6eb4523785 100644 --- a/utils/hu/floats.texy +++ b/utils/hu/floats.texy @@ -42,6 +42,9 @@ echo Floats::areEqual($a, $b) ? 'same' : 'not same'; // same Amikor megpróbálja összehasonlítani a `NAN`, akkor a `\LogicException` kivételt dob. +.[tip] +A `Floats` osztály tolerálja a `1e-10`-nél kisebb különbségeket. Ha nagyobb pontossággal kell dolgoznia, használja helyette a BCMath könyvtárat. + Lebegő összehasonlítás .[#toc-float-comparison] =============================================== diff --git a/utils/it/floats.texy b/utils/it/floats.texy index 87d310788f..efd473b289 100644 --- a/utils/it/floats.texy +++ b/utils/it/floats.texy @@ -42,6 +42,9 @@ echo Floats::areEqual($a, $b) ? 'same' : 'not same'; // same Quando si tenta di confrontare `NAN`, viene lanciata un'eccezione `\LogicException`. +.[tip] +La classe `Floats` tollera differenze inferiori a `1e-10`. Se è necessario lavorare con maggiore precisione, utilizzare la libreria BCMath. + Confronto tra i galleggianti .[#toc-float-comparison] ===================================================== diff --git a/utils/pl/floats.texy b/utils/pl/floats.texy index d10b3e72ae..feed8fea69 100644 --- a/utils/pl/floats.texy +++ b/utils/pl/floats.texy @@ -42,6 +42,9 @@ echo Floats::areEqual($a, $b) ? 'same' : 'not same'; // same Podczas próby porównania `NAN` rzuca wyjątek `\LogicException`. +.[tip] +Klasa `Floats` toleruje różnice mniejsze niż `1e-10`. Jeśli potrzebujesz pracować z większą precyzją, użyj zamiast tego biblioteki BCMath. + Porównywanie pływaków .[#toc-float-comparison] ============================================== diff --git a/utils/pt/floats.texy b/utils/pt/floats.texy index 7ef9b4f49b..f624d64724 100644 --- a/utils/pt/floats.texy +++ b/utils/pt/floats.texy @@ -42,6 +42,9 @@ echo Floats::areEqual($a, $b) ? 'same' : 'not same'; // same Ao tentar comparar `NAN`, ele lança uma exceção `\LogicException`. +.[tip] +A classe `Floats` tolera diferenças menores que `1e-10`. Se você precisar trabalhar com mais precisão, use a biblioteca BCMath. + Comparação de flutuadores .[#toc-float-comparison] ================================================== diff --git a/utils/ro/floats.texy b/utils/ro/floats.texy index 373fe66b1c..21422ca9ab 100644 --- a/utils/ro/floats.texy +++ b/utils/ro/floats.texy @@ -42,6 +42,9 @@ echo Floats::areEqual($a, $b) ? 'same': 'not same'; // același Când se încearcă să se compare `NAN`, se aruncă o excepție `\LogicException`. +.[tip] +Clasa `Floats` tolerează diferențe mai mici de `1e-10`. Dacă aveți nevoie să lucrați cu o precizie mai mare, utilizați în schimb biblioteca BCMath. + Compararea flotorilor .[#toc-float-comparison] ============================================== diff --git a/utils/ru/floats.texy b/utils/ru/floats.texy index ff06b4f298..769306a0e7 100644 --- a/utils/ru/floats.texy +++ b/utils/ru/floats.texy @@ -42,6 +42,9 @@ echo Floats::areEqual($a, $b) ? 'same' : 'not same'; // same При попытке сравнить `NAN` возникает исключение `\LogicException`. +.[tip] +Класс `Floats` допускает различия меньше, чем `1e-10`. Если вам нужно работать с большей точностью, используйте библиотеку BCMath. + Сравнение плавающих значений .[#toc-float-comparison] ===================================================== diff --git a/utils/sl/floats.texy b/utils/sl/floats.texy index 6832099a97..bf5337b071 100644 --- a/utils/sl/floats.texy +++ b/utils/sl/floats.texy @@ -42,6 +42,9 @@ echo Floats::areEqual($a, $b) ? 'same': 'not same'; // enako Ko poskuša primerjati `NAN`, pa vrže izjemo `\LogicException`. +.[tip] +Razred `Floats` dopušča razlike, manjše od `1e-10`. Če morate delati z večjo natančnostjo, uporabite knjižnico BCMath. + Primerjava floatov .[#toc-float-comparison] =========================================== diff --git a/utils/tr/floats.texy b/utils/tr/floats.texy index 44e716a09c..1ff07cc2d9 100644 --- a/utils/tr/floats.texy +++ b/utils/tr/floats.texy @@ -42,6 +42,9 @@ echo Floats::areEqual($a, $b) ? 'same' : 'not same'; // same `NAN` adresini karşılaştırmaya çalışırken `\LogicException` istisnası atar. +.[tip] +`Floats` sınıfı `1e-10`'dan daha az farkları tolere eder. Daha fazla hassasiyetle çalışmanız gerekiyorsa, bunun yerine BCMath kütüphanesini kullanın. + Şamandıra Karşılaştırması .[#toc-float-comparison] ================================================== diff --git a/utils/uk/floats.texy b/utils/uk/floats.texy index 8ef3c63555..916e0348a1 100644 --- a/utils/uk/floats.texy +++ b/utils/uk/floats.texy @@ -42,6 +42,9 @@ echo Floats::areEqual($a, $b) ? 'same' : 'not same'; // same При спробі порівняти `NAN` виникає виняток `\LogicException`. +.[tip] +Клас `Floats` менш толерантний до відмінностей, ніж `1e-10`. Якщо вам потрібно працювати з більшою точністю, використовуйте замість нього бібліотеку BCMath. + Порівняння плаваючих значень .[#toc-float-comparison] ===================================================== From 2cf34aa121f75339c92103bf5d090693a79d12b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milo=C5=A1=20Brecher?= <34324008+mildabre@users.noreply.github.com> Date: Mon, 18 Mar 2024 22:10:52 +0100 Subject: [PATCH 061/137] typo (#1046) --- best-practices/bg/form-reuse.texy | 2 +- best-practices/cs/form-reuse.texy | 2 +- best-practices/de/form-reuse.texy | 2 +- best-practices/el/form-reuse.texy | 2 +- best-practices/en/form-reuse.texy | 2 +- best-practices/es/form-reuse.texy | 2 +- best-practices/fr/form-reuse.texy | 2 +- best-practices/hu/form-reuse.texy | 2 +- best-practices/it/form-reuse.texy | 2 +- best-practices/pl/form-reuse.texy | 2 +- best-practices/pt/form-reuse.texy | 2 +- best-practices/ro/form-reuse.texy | 2 +- best-practices/ru/form-reuse.texy | 2 +- best-practices/sl/form-reuse.texy | 2 +- best-practices/tr/form-reuse.texy | 2 +- best-practices/uk/form-reuse.texy | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/best-practices/bg/form-reuse.texy b/best-practices/bg/form-reuse.texy index 43a4554915..6e65e1bc8a 100644 --- a/best-practices/bg/form-reuse.texy +++ b/best-practices/bg/form-reuse.texy @@ -335,7 +335,7 @@ class MyPresenter extends Nette\Application\UI\Presenter ) { } - protected function createComponentEditForm(): Form + protected function createComponentEditForm(): EditControl { $control = $this->controlFactory->create(); diff --git a/best-practices/cs/form-reuse.texy b/best-practices/cs/form-reuse.texy index 35a4b1dc04..2a6db194db 100644 --- a/best-practices/cs/form-reuse.texy +++ b/best-practices/cs/form-reuse.texy @@ -335,7 +335,7 @@ class MyPresenter extends Nette\Application\UI\Presenter ) { } - protected function createComponentEditForm(): Form + protected function createComponentEditForm(): EditControl { $control = $this->controlFactory->create(); diff --git a/best-practices/de/form-reuse.texy b/best-practices/de/form-reuse.texy index c37f954138..a68bf02309 100644 --- a/best-practices/de/form-reuse.texy +++ b/best-practices/de/form-reuse.texy @@ -335,7 +335,7 @@ class MyPresenter extends Nette\Application\UI\Presenter ) { } - protected function createComponentEditForm(): Form + protected function createComponentEditForm(): EditControl { $control = $this->controlFactory->create(); diff --git a/best-practices/el/form-reuse.texy b/best-practices/el/form-reuse.texy index afc0397dff..3dc860e4cc 100644 --- a/best-practices/el/form-reuse.texy +++ b/best-practices/el/form-reuse.texy @@ -335,7 +335,7 @@ class MyPresenter extends Nette\Application\UI\Presenter ) { } - protected function createComponentEditForm(): Form + protected function createComponentEditForm(): EditControl { $control = $this->controlFactory->create(); diff --git a/best-practices/en/form-reuse.texy b/best-practices/en/form-reuse.texy index e78e11f1ee..be53a9d13b 100644 --- a/best-practices/en/form-reuse.texy +++ b/best-practices/en/form-reuse.texy @@ -335,7 +335,7 @@ class MyPresenter extends Nette\Application\UI\Presenter ) { } - protected function createComponentEditForm(): Form + protected function createComponentEditForm(): EditControl { $control = $this->controlFactory->create(); diff --git a/best-practices/es/form-reuse.texy b/best-practices/es/form-reuse.texy index ae9c25920a..7f48acaea8 100644 --- a/best-practices/es/form-reuse.texy +++ b/best-practices/es/form-reuse.texy @@ -335,7 +335,7 @@ class MyPresenter extends Nette\Application\UI\Presenter ) { } - protected function createComponentEditForm(): Form + protected function createComponentEditForm(): EditControl { $control = $this->controlFactory->create(); diff --git a/best-practices/fr/form-reuse.texy b/best-practices/fr/form-reuse.texy index 4589e497c0..97260a1ef4 100644 --- a/best-practices/fr/form-reuse.texy +++ b/best-practices/fr/form-reuse.texy @@ -335,7 +335,7 @@ class MyPresenter extends Nette\Application\UI\Presenter ) { } - protected function createComponentEditForm(): Form + protected function createComponentEditForm(): EditControl { $control = $this->controlFactory->create(); diff --git a/best-practices/hu/form-reuse.texy b/best-practices/hu/form-reuse.texy index 1c4b0fbeb8..d3ceabe3e2 100644 --- a/best-practices/hu/form-reuse.texy +++ b/best-practices/hu/form-reuse.texy @@ -335,7 +335,7 @@ class MyPresenter extends Nette\Application\UI\Presenter ) { } - protected function createComponentEditForm(): Form + protected function createComponentEditForm(): EditControl { $control = $this->controlFactory->create(); diff --git a/best-practices/it/form-reuse.texy b/best-practices/it/form-reuse.texy index 10cdc42fce..696ad6d9c6 100644 --- a/best-practices/it/form-reuse.texy +++ b/best-practices/it/form-reuse.texy @@ -335,7 +335,7 @@ class MyPresenter extends Nette\Application\UI\Presenter ) { } - protected function createComponentEditForm(): Form + protected function createComponentEditForm(): EditControl { $control = $this->controlFactory->create(); diff --git a/best-practices/pl/form-reuse.texy b/best-practices/pl/form-reuse.texy index 28412b73b6..735904cffb 100644 --- a/best-practices/pl/form-reuse.texy +++ b/best-practices/pl/form-reuse.texy @@ -335,7 +335,7 @@ class MyPresenter extends Nette\Application\UI\Presenter ) { } - protected function createComponentEditForm(): Form + protected function createComponentEditForm(): EditControl { $control = $this->controlFactory->create(); diff --git a/best-practices/pt/form-reuse.texy b/best-practices/pt/form-reuse.texy index 1f15cd5dd6..7555fad062 100644 --- a/best-practices/pt/form-reuse.texy +++ b/best-practices/pt/form-reuse.texy @@ -335,7 +335,7 @@ class MyPresenter extends Nette\Application\UI\Presenter ) { } - protected function createComponentEditForm(): Form + protected function createComponentEditForm(): EditControl { $control = $this->controlFactory->create(); diff --git a/best-practices/ro/form-reuse.texy b/best-practices/ro/form-reuse.texy index e9ec5c7abc..4c9d7dede0 100644 --- a/best-practices/ro/form-reuse.texy +++ b/best-practices/ro/form-reuse.texy @@ -335,7 +335,7 @@ class MyPresenter extends Nette\Application\UI\Presenter ) { } - protected function createComponentEditForm(): Form + protected function createComponentEditForm(): EditControl { $control = $this->controlFactory->create(); diff --git a/best-practices/ru/form-reuse.texy b/best-practices/ru/form-reuse.texy index 06214c2241..f79fc541af 100644 --- a/best-practices/ru/form-reuse.texy +++ b/best-practices/ru/form-reuse.texy @@ -335,7 +335,7 @@ class MyPresenter extends Nette\Application\UI\Presenter ) { } - protected function createComponentEditForm(): Form + protected function createComponentEditForm(): EditControl { $control = $this->controlFactory->create(); diff --git a/best-practices/sl/form-reuse.texy b/best-practices/sl/form-reuse.texy index 8c185009bc..7eaa8a578e 100644 --- a/best-practices/sl/form-reuse.texy +++ b/best-practices/sl/form-reuse.texy @@ -335,7 +335,7 @@ class MyPresenter extends Nette\Application\UI\Presenter ) { } - protected function createComponentEditForm(): Form + protected function createComponentEditForm(): EditControl { $control = $this->controlFactory->create(); diff --git a/best-practices/tr/form-reuse.texy b/best-practices/tr/form-reuse.texy index fd80cf39ef..f6a3cd40a4 100644 --- a/best-practices/tr/form-reuse.texy +++ b/best-practices/tr/form-reuse.texy @@ -335,7 +335,7 @@ class MyPresenter extends Nette\Application\UI\Presenter ) { } - protected function createComponentEditForm(): Form + protected function createComponentEditForm(): EditControl { $control = $this->controlFactory->create(); diff --git a/best-practices/uk/form-reuse.texy b/best-practices/uk/form-reuse.texy index b1e0418b47..38d700e84f 100644 --- a/best-practices/uk/form-reuse.texy +++ b/best-practices/uk/form-reuse.texy @@ -335,7 +335,7 @@ class MyPresenter extends Nette\Application\UI\Presenter ) { } - protected function createComponentEditForm(): Form + protected function createComponentEditForm(): EditControl { $control = $this->controlFactory->create(); From 5c685c2db0e3c87ca8c0f0b1aec4c733698c7663 Mon Sep 17 00:00:00 2001 From: hermajan Date: Mon, 18 Mar 2024 22:15:46 +0100 Subject: [PATCH 062/137] Fixed PhpStorm typo (#1045) --- nette/bg/installation.texy | 2 +- nette/cs/installation.texy | 2 +- nette/de/installation.texy | 2 +- nette/el/installation.texy | 2 +- nette/en/installation.texy | 2 +- nette/es/installation.texy | 2 +- nette/fr/installation.texy | 2 +- nette/hu/installation.texy | 2 +- nette/it/installation.texy | 2 +- nette/pl/installation.texy | 2 +- nette/pt/installation.texy | 2 +- nette/ro/installation.texy | 2 +- nette/ru/installation.texy | 2 +- nette/sl/installation.texy | 2 +- nette/tr/installation.texy | 2 +- nette/uk/installation.texy | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/nette/bg/installation.texy b/nette/bg/installation.texy index a669e5b3ab..8ca67baa2e 100644 --- a/nette/bg/installation.texy +++ b/nette/bg/installation.texy @@ -20,7 +20,7 @@ Nette предлага колекция от полезни и усъвърше composer require nette/utils ``` -Предпочитате ли графичен интерфейс? Разгледайте [ръководството за |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] инсталиране на пакети в средата PhpStrom. +Предпочитате ли графичен интерфейс? Разгледайте [ръководството за |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] инсталиране на пакети в средата PhpStorm. Как да започнете нов проект с Nette .[#toc-how-to-start-a-new-project-with-nette] diff --git a/nette/cs/installation.texy b/nette/cs/installation.texy index b2d4b99c94..6f5455879f 100644 --- a/nette/cs/installation.texy +++ b/nette/cs/installation.texy @@ -20,7 +20,7 @@ Nette nabízí kolekci užitečných a vyspělých balíčků (knihoven) pro PHP composer require nette/utils ``` -Preferujete grafické rozhraní? Prohlédněte si [návod|https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] na instalaci balíčků v prostředí PhpStrom. +Preferujete grafické rozhraní? Prohlédněte si [návod|https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] na instalaci balíčků v prostředí PhpStorm. Jak založit nový projekt s Nette diff --git a/nette/de/installation.texy b/nette/de/installation.texy index 6e419e22e7..f4c428ca07 100644 --- a/nette/de/installation.texy +++ b/nette/de/installation.texy @@ -20,7 +20,7 @@ Nette bietet eine Sammlung von nützlichen und anspruchsvollen Paketen (Biblioth composer require nette/utils ``` -Bevorzugen Sie eine grafische Oberfläche? Sehen Sie sich die [Anleitung |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] zur Installation von Paketen in der PhpStrom-Umgebung an. +Bevorzugen Sie eine grafische Oberfläche? Sehen Sie sich die [Anleitung |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] zur Installation von Paketen in der PhpStorm-Umgebung an. Wie man ein neues Projekt mit Nette startet .[#toc-how-to-start-a-new-project-with-nette] diff --git a/nette/el/installation.texy b/nette/el/installation.texy index d99ca71ff0..bf7a84e962 100644 --- a/nette/el/installation.texy +++ b/nette/el/installation.texy @@ -20,7 +20,7 @@ composer require nette/utils ``` -Προτιμάτε ένα γραφικό περιβάλλον εργασίας; Ανατρέξτε στον [οδηγό |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] για την εγκατάσταση πακέτων στο περιβάλλον PhpStrom. +Προτιμάτε ένα γραφικό περιβάλλον εργασίας; Ανατρέξτε στον [οδηγό |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] για την εγκατάσταση πακέτων στο περιβάλλον PhpStorm. Πώς να ξεκινήσετε ένα νέο έργο με τη Nette .[#toc-how-to-start-a-new-project-with-nette] diff --git a/nette/en/installation.texy b/nette/en/installation.texy index 016f177da7..0dfea8fadb 100644 --- a/nette/en/installation.texy +++ b/nette/en/installation.texy @@ -20,7 +20,7 @@ Nette offers a collection of useful and sophisticated packages (libraries) for P composer require nette/utils ``` -Do you prefer a graphical interface? Check out the [guide|https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] on installing packages in the PhpStrom environment. +Do you prefer a graphical interface? Check out the [guide|https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] on installing packages in the PhpStorm environment. How to Start a New Project with Nette diff --git a/nette/es/installation.texy b/nette/es/installation.texy index 4690a5a0f3..4394de8f6a 100644 --- a/nette/es/installation.texy +++ b/nette/es/installation.texy @@ -20,7 +20,7 @@ Nette ofrece una colección de paquetes (librerías) útiles y sofisticados para composer require nette/utils ``` -¿Prefieres una interfaz gráfica? Consulta la [guía |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] de instalación de paquetes en el entorno PhpStrom. +¿Prefieres una interfaz gráfica? Consulta la [guía |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] de instalación de paquetes en el entorno PhpStorm. Cómo iniciar un nuevo proyecto con Nette .[#toc-how-to-start-a-new-project-with-nette] diff --git a/nette/fr/installation.texy b/nette/fr/installation.texy index 76b5e3fdd8..64be253e09 100644 --- a/nette/fr/installation.texy +++ b/nette/fr/installation.texy @@ -20,7 +20,7 @@ Nette propose une collection de packages (bibliothèques) utiles et sophistiqué composer require nette/utils ``` -Vous préférez une interface graphique ? Consultez le [guide d' |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] installation des paquets dans l'environnement PhpStrom. +Vous préférez une interface graphique ? Consultez le [guide d' |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] installation des paquets dans l'environnement PhpStorm. Comment démarrer un nouveau projet avec Nette .[#toc-how-to-start-a-new-project-with-nette] diff --git a/nette/hu/installation.texy b/nette/hu/installation.texy index a390238849..cafa64d29c 100644 --- a/nette/hu/installation.texy +++ b/nette/hu/installation.texy @@ -20,7 +20,7 @@ A Nette hasznos és kifinomult csomagok (könyvtárak) gyűjteményét kínálja composer require nette/utils ``` -Grafikus felületet szeretne? Tekintse meg a csomagok telepítéséről szóló [útmutatót |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] a PhpStrom környezetben. +Grafikus felületet szeretne? Tekintse meg a csomagok telepítéséről szóló [útmutatót |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] a PhpStorm környezetben. Új projekt indítása a Nette segítségével .[#toc-how-to-start-a-new-project-with-nette] diff --git a/nette/it/installation.texy b/nette/it/installation.texy index 48fbf452d1..cfdcbe8aef 100644 --- a/nette/it/installation.texy +++ b/nette/it/installation.texy @@ -20,7 +20,7 @@ Nette offre una raccolta di pacchetti (librerie) utili e sofisticati per PHP. Pe composer require nette/utils ``` -Preferite un'interfaccia grafica? Consultate la [guida |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] all'installazione dei pacchetti nell'ambiente PhpStrom. +Preferite un'interfaccia grafica? Consultate la [guida |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] all'installazione dei pacchetti nell'ambiente PhpStorm. Come avviare un nuovo progetto con Nette .[#toc-how-to-start-a-new-project-with-nette] diff --git a/nette/pl/installation.texy b/nette/pl/installation.texy index 6655f61a7f..8e2c2e70f7 100644 --- a/nette/pl/installation.texy +++ b/nette/pl/installation.texy @@ -20,7 +20,7 @@ Nette oferuje kolekcję przydatnych i zaawansowanych pakietów (bibliotek) dla P composer require nette/utils ``` -Wolisz interfejs graficzny? Zapoznaj się z [przewodnikiem |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] dotyczącym instalacji pakietów w środowisku PhpStrom. +Wolisz interfejs graficzny? Zapoznaj się z [przewodnikiem |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] dotyczącym instalacji pakietów w środowisku PhpStorm. Jak rozpocząć nowy projekt z Nette .[#toc-how-to-start-a-new-project-with-nette] diff --git a/nette/pt/installation.texy b/nette/pt/installation.texy index 66d80dec1f..958f96c331 100644 --- a/nette/pt/installation.texy +++ b/nette/pt/installation.texy @@ -20,7 +20,7 @@ O Nette oferece uma coleção de pacotes (bibliotecas) úteis e sofisticados par composer require nette/utils ``` -Você prefere uma interface gráfica? Confira o [guia |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] sobre a instalação de pacotes no ambiente PhpStrom. +Você prefere uma interface gráfica? Confira o [guia |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] sobre a instalação de pacotes no ambiente PhpStorm. Como iniciar um novo projeto com o Nette .[#toc-how-to-start-a-new-project-with-nette] diff --git a/nette/ro/installation.texy b/nette/ro/installation.texy index a21291725e..370bcd62ca 100644 --- a/nette/ro/installation.texy +++ b/nette/ro/installation.texy @@ -20,7 +20,7 @@ Nette oferă o colecție de pachete (biblioteci) utile și sofisticate pentru PH composer require nette/utils ``` -Preferați o interfață grafică? Consultați [ghidul |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] de instalare a pachetelor în mediul PhpStrom. +Preferați o interfață grafică? Consultați [ghidul |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] de instalare a pachetelor în mediul PhpStorm. Cum să începeți un proiect nou cu Nette .[#toc-how-to-start-a-new-project-with-nette] diff --git a/nette/ru/installation.texy b/nette/ru/installation.texy index 230676af6a..97bbf8671f 100644 --- a/nette/ru/installation.texy +++ b/nette/ru/installation.texy @@ -20,7 +20,7 @@ Nette представляет собой набор полезных и сло composer require nette/utils ``` -Вы предпочитаете графический интерфейс? Ознакомьтесь с [руководством |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] по установке пакетов в среде PhpStrom. +Вы предпочитаете графический интерфейс? Ознакомьтесь с [руководством |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] по установке пакетов в среде PhpStorm. Как начать новый проект с помощью Nette .[#toc-how-to-start-a-new-project-with-nette] diff --git a/nette/sl/installation.texy b/nette/sl/installation.texy index b7d5e84ccc..66c1d70baa 100644 --- a/nette/sl/installation.texy +++ b/nette/sl/installation.texy @@ -20,7 +20,7 @@ Nette ponuja zbirko uporabnih in izpopolnjenih paketov (knjižnic) za PHP. Če j composer require nette/utils ``` -Ali imate raje grafični vmesnik? Oglejte si [vodnik za |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] nameščanje paketov v okolje PhpStrom. +Ali imate raje grafični vmesnik? Oglejte si [vodnik za |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] nameščanje paketov v okolje PhpStorm. Kako začeti nov projekt z Nette .[#toc-how-to-start-a-new-project-with-nette] diff --git a/nette/tr/installation.texy b/nette/tr/installation.texy index 9acc4f5ba5..7f82f49a85 100644 --- a/nette/tr/installation.texy +++ b/nette/tr/installation.texy @@ -20,7 +20,7 @@ Nette, PHP için kullanışlı ve sofistike paketlerden (kütüphaneler) oluşan composer require nette/utils ``` -Grafik arayüzü mü tercih ediyorsunuz? PhpStrom ortamında paket yükleme [kılavuzuna |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] göz atın. +Grafik arayüzü mü tercih ediyorsunuz? PhpStorm ortamında paket yükleme [kılavuzuna |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] göz atın. Nette ile Yeni Bir Projeye Nasıl Başlanır .[#toc-how-to-start-a-new-project-with-nette] diff --git a/nette/uk/installation.texy b/nette/uk/installation.texy index d0bb92c629..af5ff9936a 100644 --- a/nette/uk/installation.texy +++ b/nette/uk/installation.texy @@ -20,7 +20,7 @@ Nette пропонує колекцію корисних і складних п composer require nette/utils ``` -Віддаєте перевагу графічному інтерфейсу? Ознайомтеся з [посібником |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] зі встановлення пакунків у середовищі PhpStrom. +Віддаєте перевагу графічному інтерфейсу? Ознайомтеся з [посібником |https://www.jetbrains.com/help/phpstorm/using-the-composer-dependency-manager.html] зі встановлення пакунків у середовищі PhpStorm. Як розпочати новий проект за допомогою Nette .[#toc-how-to-start-a-new-project-with-nette] From ee998def8dcb89e8e7d8ff2bb116e0e057c57cee Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 19 Mar 2024 22:59:38 +0100 Subject: [PATCH 063/137] application: better wording [Closes nette/application#323] --- application/bg/creating-links.texy | 2 +- application/cs/creating-links.texy | 2 +- application/de/creating-links.texy | 2 +- application/el/creating-links.texy | 2 +- application/en/creating-links.texy | 2 +- application/es/creating-links.texy | 2 +- application/fr/creating-links.texy | 2 +- application/hu/creating-links.texy | 2 +- application/it/creating-links.texy | 2 +- application/pl/creating-links.texy | 2 +- application/pt/creating-links.texy | 2 +- application/ro/creating-links.texy | 2 +- application/ru/creating-links.texy | 2 +- application/sl/creating-links.texy | 2 +- application/tr/creating-links.texy | 2 +- application/uk/creating-links.texy | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/application/bg/creating-links.texy b/application/bg/creating-links.texy index f56a6f00fc..14bdd3e2d9 100644 --- a/application/bg/creating-links.texy +++ b/application/bg/creating-links.texy @@ -140,7 +140,7 @@ $url = $this->link('Product:show', [$product->id, 'lang' => 'cs']); обновить ``` -Това ще предаде всички параметри, посочени в сигнатурата на метода. `render()` или `action()`. Така че, ако сме на `Product:show` и `id:123`, връзката към `this` също ще предаде този параметър. +В същото време всички параметри, посочени в сигнатурата на `action()` или `render()` ако методът `action()` не са дефинирани, се прехвърлят. Така че, ако се намираме на страниците `Product:show` и `id:123`, връзката към `this` също ще предаде този параметър. Разбира се, можете да зададете параметрите и директно: diff --git a/application/cs/creating-links.texy b/application/cs/creating-links.texy index 6c30a94e62..bd921ae70c 100644 --- a/application/cs/creating-links.texy +++ b/application/cs/creating-links.texy @@ -140,7 +140,7 @@ Cíl `this` vytvoří odkaz na aktuální stránku: refresh ``` -Zároveň se přenáší i všechny parametry uvedené v signatuře `render()` nebo `action()` metody. Takže pokud jsme na stránce `Product:show` a `id: 123`, odkaz na `this` předá i tento parameter. +Zároveň se přenáší i všechny parametry uvedené v signatuře metody `action()` nebo `render()`, pokud není `action()` definovaná. Takže pokud jsme na stránce `Product:show` a `id: 123`, odkaz na `this` předá i tento parameter. Samozřejmě je možné parametry specifikovat přímo: diff --git a/application/de/creating-links.texy b/application/de/creating-links.texy index b462d2177f..b2dd309752 100644 --- a/application/de/creating-links.texy +++ b/application/de/creating-links.texy @@ -140,7 +140,7 @@ Das Ziel `this` wird einen Link zur aktuellen Seite erstellen: refresh ``` -Gleichzeitig werden alle Parameter, die in der Signatur des Befehls `render()` oder `action()` Methode angegeben sind, übertragen. Wenn wir uns also auf den Seiten `Product:show` und `id:123` befinden, wird der Link zu `this` auch diesen Parameter übergeben. +Gleichzeitig werden alle Parameter, die in der Signatur des Befehls `action()` oder `render()` Methode angegebenen Parameter, wenn die `action()` nicht definiert ist, übertragen. Wenn wir uns also auf den Seiten `Product:show` und `id:123` befinden, wird der Link zu `this` auch diesen Parameter übergeben. Natürlich ist es auch möglich, die Parameter direkt anzugeben: diff --git a/application/el/creating-links.texy b/application/el/creating-links.texy index 8d8c27fc2c..8a9f563cf8 100644 --- a/application/el/creating-links.texy +++ b/application/el/creating-links.texy @@ -140,7 +140,7 @@ $url = $this->link('Product:show', [$product->id, 'lang' => 'cs']); refresh ``` -Ταυτόχρονα, όλες οι παράμετροι που καθορίζονται στην υπογραφή της εντολής `render()` ή `action()` μεταφέρονται. Έτσι, αν βρισκόμαστε στις σελίδες `Product:show` και `id:123`, ο σύνδεσμος προς την `this` θα μεταφέρει και αυτή την παράμετρο. +Ταυτόχρονα, όλες οι παράμετροι που καθορίζονται στην υπογραφή της `action()` ή `render()` μεθόδου, εάν η `action()` δεν έχει οριστεί, μεταφέρονται. Έτσι, αν βρισκόμαστε στις σελίδες `Product:show` και `id:123`, ο σύνδεσμος προς την `this` θα μεταφέρει και αυτή την παράμετρο. Φυσικά, είναι δυνατόν να καθορίσετε τις παραμέτρους απευθείας: diff --git a/application/en/creating-links.texy b/application/en/creating-links.texy index 6cac071b7d..eb10c4c852 100644 --- a/application/en/creating-links.texy +++ b/application/en/creating-links.texy @@ -140,7 +140,7 @@ The target `this` will create a link to the current page: refresh ``` -At the same time, all parameters specified in the signature of the `render()` or `action()` method are transferred. So if we are on the `Product:show` and `id:123` pages, the link to `this` will also pass this parameter. +At the same time, all parameters specified in the signature of the `action()` or `render()` method, if the `action()` is not defined, are transferred. So if we are on the `Product:show` and `id:123` pages, the link to `this` will also pass this parameter. Of course, it is possible to specify the parameters directly: diff --git a/application/es/creating-links.texy b/application/es/creating-links.texy index d6e63a4bcb..ed5ab76589 100644 --- a/application/es/creating-links.texy +++ b/application/es/creating-links.texy @@ -140,7 +140,7 @@ El destino `this` creará un enlace a la página actual: refresh ``` -Al mismo tiempo, todos los parámetros especificados en la firma de la directiva `render()` o `action()` se transfieren. Así, si estamos en las páginas `Product:show` y `id:123`, el enlace a `this` también pasará este parámetro. +Al mismo tiempo, todos los parámetros especificados en la firma de la directiva `action()` o `render()` si el método `action()` no está definido, se transfieren. Así, si estamos en las páginas `Product:show` y `id:123`, el enlace a `this` también pasará este parámetro. Por supuesto, es posible especificar los parámetros directamente: diff --git a/application/fr/creating-links.texy b/application/fr/creating-links.texy index 0c6c184066..32ad736c4b 100644 --- a/application/fr/creating-links.texy +++ b/application/fr/creating-links.texy @@ -140,7 +140,7 @@ La cible `this` créera un lien vers la page actuelle : refresh ``` -En même temps, tous les paramètres spécifiés dans la signature de l'instruction `render()` ou `action()` sont transférés. Ainsi, si nous sommes sur les pages `Product:show` et `id:123`, le lien vers `this` transmettra également ce paramètre. +En même temps, tous les paramètres spécifiés dans la signature de l'élément `action()` ou `render()` si la méthode `action()` n'est pas défini, sont transférés. Ainsi, si nous nous trouvons sur les pages `Product:show` et `id:123`, le lien vers `this` transmettra également ce paramètre. Bien sûr, il est possible de spécifier les paramètres directement : diff --git a/application/hu/creating-links.texy b/application/hu/creating-links.texy index cf2d0df2e8..052dc6f4ef 100644 --- a/application/hu/creating-links.texy +++ b/application/hu/creating-links.texy @@ -140,7 +140,7 @@ A cél `this` létrehoz egy linket az aktuális oldalra: refresh ``` -Ugyanakkor az összes, az aláírásában megadott paramétert a `render()` vagy `action()` metódusban megadott paraméterek átadásra kerülnek. Tehát ha a `Product:show` és a `id:123` oldalakon vagyunk, akkor a `this` link is átadja ezt a paramétert. +Ugyanakkor az összes paraméter, amelyet a `action()` vagy a `render()` metódusban megadott paraméterek, ha a `action()` nincs definiálva, átadásra kerül. Tehát ha a `Product:show` és a `id:123` oldalakon vagyunk, akkor a `this` linkje is átadja ezt a paramétert. Természetesen lehetőség van a paraméterek közvetlen megadására is: diff --git a/application/it/creating-links.texy b/application/it/creating-links.texy index de4a530016..a1dbcc4bb6 100644 --- a/application/it/creating-links.texy +++ b/application/it/creating-links.texy @@ -140,7 +140,7 @@ Il target `this` creerà un collegamento alla pagina corrente: refresh ``` -Allo stesso tempo, tutti i parametri specificati nella firma del metodo `render()` o `action()` vengono trasferiti. Quindi, se ci troviamo nelle pagine `Product:show` e `id:123`, anche il collegamento a `this` passerà questo parametro. +Allo stesso tempo, tutti i parametri specificati nella firma dell'elemento `action()` o `render()` se il metodo `action()` non è definito, vengono trasferiti. Quindi, se ci troviamo nelle pagine `Product:show` e `id:123`, il collegamento a `this` passerà anche questo parametro. Naturalmente, è possibile specificare direttamente i parametri: diff --git a/application/pl/creating-links.texy b/application/pl/creating-links.texy index 24a2152b62..781a17e60d 100644 --- a/application/pl/creating-links.texy +++ b/application/pl/creating-links.texy @@ -140,7 +140,7 @@ Cel `this` tworzy link do bieżącej strony: refresh ``` -Wszystkie parametry określone w podpisie są również przekazywane `render()` lub `action()` metody. Jeśli więc jesteśmy na `Product:show` i `id: 123`, to link do `this` również przekaże ten parametr. +W tym samym czasie, wszystkie parametry określone w sygnaturze parametru `action()` lub `render()` jeśli metoda `action()` nie są zdefiniowane, są przekazywane. Jeśli więc jesteśmy na stronach `Product:show` i `id:123`, link do `this` również przekaże ten parametr. Oczywiście istnieje możliwość bezpośredniego podania parametrów: diff --git a/application/pt/creating-links.texy b/application/pt/creating-links.texy index 4ecadd7bda..24570ecfb2 100644 --- a/application/pt/creating-links.texy +++ b/application/pt/creating-links.texy @@ -140,7 +140,7 @@ A meta `this` irá criar um link para a página atual: refresh ``` -Ao mesmo tempo, todos os parâmetros especificados na assinatura do `render()` ou `action()` método são transferidos. Portanto, se estivermos nas páginas `Product:show` e `id:123`, o link para `this` também passará este parâmetro. +Ao mesmo tempo, todos os parâmetros especificados na assinatura do parâmetro `action()` ou `render()` se o método `action()` não estiver definido, serão transferidos. Portanto, se estivermos nas páginas `Product:show` e `id:123`, o link para `this` também passará esse parâmetro. Naturalmente, é possível especificar os parâmetros diretamente: diff --git a/application/ro/creating-links.texy b/application/ro/creating-links.texy index a26a28b861..67bf8715d5 100644 --- a/application/ro/creating-links.texy +++ b/application/ro/creating-links.texy @@ -140,7 +140,7 @@ Obiectivul `this` va crea un link către pagina curentă: refresh ``` -În același timp, toți parametrii specificați în semnătura de la `render()` sau `action()` sunt transferați. Astfel, dacă ne aflăm pe paginile `Product:show` și `id:123`, legătura către `this` va transfera și acest parametru. +În același timp, toți parametrii specificați în semnătura `action()` sau `render()` în cazul în care metoda `action()` nu este definită, sunt transferați. Astfel, dacă ne aflăm pe paginile `Product:show` și `id:123`, legătura către `this` va transfera și acest parametru. Desigur, este posibil să se specifice parametrii direct: diff --git a/application/ru/creating-links.texy b/application/ru/creating-links.texy index debaf56da0..8961c3227b 100644 --- a/application/ru/creating-links.texy +++ b/application/ru/creating-links.texy @@ -140,7 +140,7 @@ $url = $this->link('Product:show', [$product->id, 'lang' => 'cs']); обновить ``` -При этом передаются все параметры, указанные в сигнатуре метода `render()` или `action()`. Таким образом, если мы находимся на страницах `Product:show` и `id:123`, ссылка на `this` также будет передавать этот параметр. +В то же время все параметры, указанные в сигнатуре `action()` или `render()` метода, если `action()` не определены, передаются. Таким образом, если мы находимся на страницах `Product:show` и `id:123`, то ссылка на `this` также будет передавать этот параметр. Конечно, можно указать параметры напрямую: diff --git a/application/sl/creating-links.texy b/application/sl/creating-links.texy index 5944fc4ea5..c4732bce8b 100644 --- a/application/sl/creating-links.texy +++ b/application/sl/creating-links.texy @@ -140,7 +140,7 @@ Ciljna stran `this` bo ustvarila povezavo do trenutne strani: refresh ``` -Hkrati se vsi parametri, navedeni v podpisu `render()` ali `action()` se prenesejo. Če smo torej na straneh `Product:show` in `id:123`, bo tudi povezava do strani `this` prenesla ta parameter. +Hkrati se vsi parametri, navedeni v podpisu `action()` ali . `render()` metode, če je `action()` niso opredeljeni, se prenesejo. Če smo torej na straneh `Product:show` in `id:123`, bo povezava do strani `this` prenesla tudi ta parameter. Seveda je mogoče parametre navesti tudi neposredno: diff --git a/application/tr/creating-links.texy b/application/tr/creating-links.texy index d52dc2e452..330930300d 100644 --- a/application/tr/creating-links.texy +++ b/application/tr/creating-links.texy @@ -140,7 +140,7 @@ Hedef `this` geçerli sayfaya bir bağlantı oluşturacaktır: refresh ``` -Aynı zamanda, imzasında belirtilen tüm parametreler `render()` veya `action()` yöntemi aktarılır. Yani `Product:show` ve `id:123` sayfalarındaysak, `this` bağlantısı da bu parametreyi geçirecektir. +Aynı zamanda, imzasında belirtilen tüm parametreler `action()` veya `render()` yönteminde, eğer `action()` tanımlanmamışsa, aktarılır. Yani `Product:show` ve `id:123` sayfalarındaysak, `this` bağlantısı da bu parametreyi geçirecektir. Elbette parametreleri doğrudan belirtmek de mümkündür: diff --git a/application/uk/creating-links.texy b/application/uk/creating-links.texy index fc428edab6..19f653904e 100644 --- a/application/uk/creating-links.texy +++ b/application/uk/creating-links.texy @@ -140,7 +140,7 @@ $url = $this->link('Product:show', [$product->id, 'lang' => 'cs']); обновить ``` -При цьому передаються всі параметри, зазначені в сигнатурі методу `render()` або `action()`. Таким чином, якщо ми перебуваємо на сторінках `Product:show` і `id:123`, посилання на `this` також передаватиме цей параметр. +При цьому всі параметри, зазначені в підписі до файлу `action()` або `render()` якщо метод `action()` не визначено, передаються. Отже, якщо ми знаходимося на сторінках `Product:show` і `id:123`, то посилання на `this` також передасть цей параметр. Звичайно, можна вказати параметри безпосередньо: From 1eeb8c848b8dfb385f8662f605decc928b1ed19f Mon Sep 17 00:00:00 2001 From: Joel Szwarga <3922354+rastographics@users.noreply.github.com> Date: Tue, 19 Mar 2024 17:22:59 -0500 Subject: [PATCH 064/137] Grammar corrected in documentation (#1044) Some English grammar corrections that make the documentation a little easier to understand and sound more professional. --- latte/en/template-inheritance.texy | 36 +++++++++++++++--------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/latte/en/template-inheritance.texy b/latte/en/template-inheritance.texy index 682e8ed475..5294812f14 100644 --- a/latte/en/template-inheritance.texy +++ b/latte/en/template-inheritance.texy @@ -2,7 +2,7 @@ Template Inheritance and Reusability ************************************ .[perex] -Template reusability and inheritance mechanisms are here to boosts your productivity because each template contains only its unique contents and the repeated elements and structures are reused. We introduce three concepts: [#layout inheritance], [#horizontal reuse] and [#unit inheritance]. +Template reusability and inheritance mechanisms are here to boost your productivity because each template contains only its unique contents and the repeated elements and structures are reused. We introduce three concepts: [#layout inheritance], [#horizontal reuse] and [#unit inheritance]. The concept of Latte template inheritance is similar to PHP class inheritance. You define a **parent template** that other **child templates** can extend from and can override parts of the parent template. It works great when elements share a common structure. Sounds complicated? Don't worry, it's not. @@ -30,7 +30,7 @@ Let’s look at layout template inheritance by starting with an example. This is ``` -The `{block}` tags defines three blocks that child templates can fill in. All the block tag does is to tell the template engine that a child template may override those portions of the template by defining their own block of the same name. +The `{block}` tags define three blocks that child templates can fill in. All the block tag does is tell the template engine that a child template may override those portions of the template by defining their own block of the same name. A child template might look like this: @@ -46,7 +46,7 @@ A child template might look like this: The `{layout}` tag is the key here. It tells the template engine that this template “extends” another template. When Latte renderes this template, first it locates the parent – in this case, `layout.latte`. -At that point, the template engine will notice the three block tags in `layout.latte` and replace those blocks with the contents of the child template. Note that since the child template didn’t define the *footer* block, the contents from the parent template is used instead. Content within a `{block}` tag in a parent template is always used as a fallback. +At that point, the template engine will notice the three block tags in `layout.latte` and replace those blocks with the contents of the child template. Note that since the child template didn’t define the *footer* block, the content from the parent template is used instead. Content within a `{block}` tag in a parent template is always used as a fallback. The output might look like: @@ -76,7 +76,7 @@ In a child template, blocks can only be located either at the top level or insid {/block} ``` -Also a block will always be created in regardless of whether the surrounding `{if}` condition is evaluated to be true or false. Contrary to what you might think, this template does define a block. +Also a block will always be created regardless of whether the surrounding `{if}` condition is evaluated to be true or false. Contrary to what you might think, this template does define a block. ```latte {if false} @@ -96,7 +96,7 @@ If you want the output inside block to be displayed conditionally, use the follo {/block} ``` -Data outside of a blocks in a child template are executed before the layout template is rendered, thus you can use it to define variables like `{var $foo = bar}` and propagate data to the whole inheritance chain: +Data outside of blocks in a child template are executed before the layout template is rendered, thus you can use it to define variables like `{var $foo = bar}` and propagate data to the whole inheritance chain: ```latte {layout 'layout.latte'} @@ -213,7 +213,7 @@ The tag can also be written as [n:attribute|syntax#n:attributes]: Local Blocks ------------ -Every block overrides content of parent block of the same name. Except for local blocks. They are something like private methods in class. You can create a template without worrying that – due to coincidence of block names – they would be overwritten by second template. +Every block overrides content of parent block of the same name. Except for local blocks. They are something like private methods in class. You can create a template without worrying that – due to coincidence of block names – they would be overwritten by a second template. ```latte {block local helper} @@ -236,13 +236,13 @@ To print a block in a specific place, use the `{include blockname}` tag:

        {include title}

        ``` -You can also display block from another template: +You can also display a block from another template: ```latte {include footer from 'main.latte'} ``` -Printed block have not access to the variables of the active context, except if the block is defined in the same file where it is included. However they have access to the global variables. +Printed blocks do not have access to the variables of the active context, except if the block is defined in the same file where it is included. However they do have access to the global variables. You can pass variables to the block in the following way: @@ -257,7 +257,7 @@ You can use a variable or any expression in PHP as the block name. In this case, {include block $name} ``` -Block can also be printed inside itself, which is useful, for example, when rendering a tree structure: +A block can also be printed inside itself, which is useful, for example, when rendering a tree structure: ```latte {define menu, $items} @@ -275,7 +275,7 @@ Block can also be printed inside itself, which is useful, for example, when rend {/define} ``` -Instead of `{include menu, ...}` we can also write `{include this, ...}` where `this` means current block. +Instead of `{include menu, ...}` we can also write `{include this, ...}` where `this` means the current block. Printed content can be modified by [filters|syntax#filters]. The following example removes all HTML and title-cases it: @@ -332,7 +332,7 @@ Imagine you have a helper template with a collection of definitions on how to dr {/define} ``` -Arguments of a definitions are always optional with default value `null`, unless default value is specified (here `'text'` is the default value for `$type`). Parameter types can also be declared: `{define input, string $name, ...}`. +Arguments of a definition are always optional with default value `null`, unless default value is specified (here `'text'` is the default value for `$type`). Parameter types can also be declared: `{define input, string $name, ...}`. The template with the definitions is loaded using [`{import}` |#horizontal-reuse]. The definitions themselves are rendered [in the same way as the blocks |#Printing Blocks]: @@ -409,7 +409,7 @@ Tips ---- Here are some tips for working with blocks: -- The last top-level block does not need to have closing tag (block ends with the end of the document). This simplifies the writing of child templates, which one primary block. +- The last top-level block does not need to have closing tag (block ends with the end of the document). This simplifies the writing of child templates with one primary block. - For extra readability, you can optionally give a name to your `{/block}` tag, for example `{/block footer}`. However, the name must match the block name. In larger templates, this technique helps you see which block tags are being closed. @@ -480,7 +480,7 @@ The unit inheritance takes the idea of layout inheritance to the level of conten In unit inheritance the `{embed}` tag is the key. It combines the behavior of `{include}` and `{layout}`. It allows you to include another template’s or block's contents and optionally pass variables, just like `{include}` does. It also allows you to override any block defined inside the included template, like `{layout}` does. -For example we are going to use the collapsible accordion element. Let’s take a look at the element skeleton in template `collapsible.latte`: +For example, we are going to use the collapsible accordion element. Let’s take a look at the element skeleton in the template `collapsible.latte`: ```latte
        @@ -494,9 +494,9 @@ For example we are going to use the collapsible accordion element. Let’s take
        ``` -The `{block}` tags defines two blocks that child templates can fill in. Yes, like in the case of parent template in the layout inheritance template. You also see `$modifierClass` variable. +The `{block}` tags defines two blocks that child templates can fill in. Yes, like in the case of parent template in the layout inheritance template. You also see a `$modifierClass` variable. -Let's use our element in template. This is where `{embed}` comes in. It’s a super powerful piece of kit that lets us do all the things: include element's template contents, add variables to it, and add blocks with custom HTML to it: +Let's use our element in a template. This is where `{embed}` comes in. It’s a super powerful piece of kit that lets us do all the things: include an element's template contents, add variables to it, and add blocks with custom HTML to it: ```latte {embed 'collapsible.latte', modifierClass: my-style} @@ -526,7 +526,7 @@ The output might look like: ``` -Blocks inside embed tags form a separate layer independent of other blocks. Therefore, they can have the same name as the block outside the embed and are not affected in any way. Using the tag [include|#Printing Blocks] inside `{embed}` tags you can insert blocks here created, blocks from embedded template (which *are not* [local|#Local Blocks]), and also blocks from main template which *are* local. You can also [import blocks|#Horizontal Reuse] from other files: +Blocks inside embed tags form a separate layer independent of other blocks. Therefore, they can have the same name as the block outside the embed and are not affected in any way. Using the tag [include|#Printing Blocks] inside `{embed}` tags you can insert blocks created here, blocks from an embedded template (which *are not* [local|#Local Blocks]), and also blocks from the main template which *are* local. You can also [import blocks|#Horizontal Reuse] from other files: ```latte {block outer}…{/block} @@ -547,7 +547,7 @@ Blocks inside embed tags form a separate layer independent of other blocks. Ther {/embed} ``` -Embeded templates have not access to the variables of the active context, but they have access to the global variables. +Embedded templates do not have access to the variables of the active context, but they do have access to the global variables. With `{embed}` you can insert not only templates but also other blocks, so the previous example could be written like this: @@ -580,7 +580,7 @@ If we pass an expression to `{embed}` and it is not clear whether it is a block Use Cases ========= -There are various types of inheritance and code reuse in Latte. Let's summarize the main concepts for more clearance: +There are various types of inheritance and code reuse in Latte. Let's summarize the main concepts for more clarity: `{include template}` From 385ef56c45e70d04fef0eb55bc93749b333f60a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radek=20Dost=C3=A1l?= Date: Tue, 19 Mar 2024 23:26:20 +0100 Subject: [PATCH 065/137] Typo. (#1042) --- forms/cs/validation.texy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forms/cs/validation.texy b/forms/cs/validation.texy index 141771580c..228989e6af 100644 --- a/forms/cs/validation.texy +++ b/forms/cs/validation.texy @@ -364,7 +364,7 @@ $details->addInteger('age') $details->addInteger('age2') ->setRequired('age2'); -$form->addSubmit('send1'); // Validuje celý formuláře +$form->addSubmit('send1'); // Validuje celý formulář $form->addSubmit('send2') ->setValidationScope([]); // Nevaliduje vůbec $form->addSubmit('send3') From 746be14f563872f559e52227521a4dc7d1ac26ef Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 3 Apr 2024 17:13:29 +0200 Subject: [PATCH 066/137] latte: vscode plugin --- latte/bg/recipes.texy | 2 +- latte/cs/recipes.texy | 2 +- latte/de/recipes.texy | 2 +- latte/el/recipes.texy | 2 +- latte/en/recipes.texy | 2 +- latte/es/recipes.texy | 2 +- latte/fr/recipes.texy | 2 +- latte/hu/recipes.texy | 2 +- latte/it/recipes.texy | 2 +- latte/ja/recipes.texy | 2 +- latte/pl/recipes.texy | 2 +- latte/pt/recipes.texy | 2 +- latte/ro/recipes.texy | 2 +- latte/ru/recipes.texy | 2 +- latte/sl/recipes.texy | 2 +- latte/tr/recipes.texy | 2 +- latte/uk/recipes.texy | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) diff --git a/latte/bg/recipes.texy b/latte/bg/recipes.texy index e0f1445d8c..d3659fc171 100644 --- a/latte/bg/recipes.texy +++ b/latte/bg/recipes.texy @@ -9,7 +9,7 @@ - NetBeans IDE има вградена поддръжка за - PhpStorm: инсталирайте [приставката Latte |https://plugins.jetbrains.com/plugin/7457-latte] в `Settings > Plugins > Marketplace` -- VS Code: намерете плъгина "Nette Latte + Neon" в маркерплей +- VS код: търсене на маркерплейс за плъгин за [шаблони |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] [Nette Latte + Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] или [Nette Latte |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] - Sublime Text 3: в Управление на пакетите намерете и инсталирайте пакета `Nette` и изберете Latte в `View > Syntax` - в по-стари редактори използвайте Smarty за подчертаване на .latte файлове diff --git a/latte/cs/recipes.texy b/latte/cs/recipes.texy index b071f62371..90d74badb3 100644 --- a/latte/cs/recipes.texy +++ b/latte/cs/recipes.texy @@ -9,7 +9,7 @@ Pište šablony v editoru nebo IDE, který má podporu pro Latte. Bude to mnohem - NetBeans IDE má podporu vestavěnou - PhpStorm: nainstalujte v `Settings > Plugins > Marketplace` [plugin Latte|https://plugins.jetbrains.com/plugin/7457-latte] -- VS Code: hledejte v markerplace "Nette Latte + Neon" plugin +- VS Code: hledejte v marketplace [Nette Latte + Neon|https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] nebo [Nette Latte templates|https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] plugin - Sublime Text 3: v Package Control najděte a nainstalujte balíček `Nette` a zvolte Latte ve `View > Syntax` - ve starých editorech použijte pro soubory .latte zvýrazňování Smarty diff --git a/latte/de/recipes.texy b/latte/de/recipes.texy index 174f5a0254..625f7dc132 100644 --- a/latte/de/recipes.texy +++ b/latte/de/recipes.texy @@ -9,7 +9,7 @@ Schreiben Sie Vorlagen in einem Editor oder einer IDE, die Latte unterstützt. E - NetBeans IDE hat integrierte Unterstützung - PhpStorm: Installieren Sie das [Latte-Plugin |https://plugins.jetbrains.com/plugin/7457-latte] in `Settings > Plugins > Marketplace` -- VS Code: Suchen Sie auf markerplace nach dem "Nette Latte + Neon" Plugin +- VS Code: suche markerplace für [Nette Latte + Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] oder [Nette Latte templates |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] plugin - Sublime Text 3: in der Paketverwaltung das Paket `Nette` suchen und installieren und Latte in auswählen `View > Syntax` - in alten Editoren Smarty-Hervorhebung für .latte-Dateien verwenden diff --git a/latte/el/recipes.texy b/latte/el/recipes.texy index 358bbc29bf..2dee1c0c48 100644 --- a/latte/el/recipes.texy +++ b/latte/el/recipes.texy @@ -9,7 +9,7 @@ - Το NetBeans IDE έχει ενσωματωμένη υποστήριξη - PhpStorm: εγκαταστήστε το [πρόσθετο Latte |https://plugins.jetbrains.com/plugin/7457-latte] στο `Settings > Plugins > Marketplace` -- VS Code: αναζητήστε το markerplace για το plugin "Nette Latte + Neon". +- VS Code: αναζήτηση markerplace για [Nette Latte + Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] ή [Nette Latte templates |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] plugin - Sublime Text 3: στο Package Control βρείτε και εγκαταστήστε το πακέτο `Nette` και επιλέξτε Latte στο `View > Syntax` - σε παλιούς επεξεργαστές χρησιμοποιήστε την επισήμανση Smarty για τα αρχεία .latte diff --git a/latte/en/recipes.texy b/latte/en/recipes.texy index c205005472..925e03ac70 100644 --- a/latte/en/recipes.texy +++ b/latte/en/recipes.texy @@ -9,7 +9,7 @@ Write templates in an editor or IDE that has support for Latte. It will be much - NetBeans IDE has built-in support - PhpStorm: install the [Latte plugin|https://plugins.jetbrains.com/plugin/7457-latte] in `Settings > Plugins > Marketplace` -- VS Code: search markerplace for "Nette Latte + Neon" plugin +- VS Code: search markerplace for [Nette Latte + Neon|https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] or [Nette Latte templates|https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] plugin - Sublime Text 3: in Package Control find and install `Nette` package and select Latte in `View > Syntax` - in old editors use Smarty highlighting for .latte files diff --git a/latte/es/recipes.texy b/latte/es/recipes.texy index 1774ae053f..270aa6f68a 100644 --- a/latte/es/recipes.texy +++ b/latte/es/recipes.texy @@ -9,7 +9,7 @@ Escriba plantillas en un editor o IDE que tenga soporte para Latte. Será mucho - NetBeans IDE tiene soporte incorporado - PhpStorm: instale el [plugin |https://plugins.jetbrains.com/plugin/7457-latte] Latte en `Settings > Plugins > Marketplace` -- VS Code: busque en markerplace el plugin "Nette Latte + Neon +- VS Code: busque en markerplace el plugin de [plantillas |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] [Nette Latte + Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] o [Nette Latte |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] - Sublime Text 3: en Package Control busque e instale el paquete `Nette` y seleccione Latte en `View > Syntax` - en editores antiguos utilice Smarty para resaltar los archivos .latte diff --git a/latte/fr/recipes.texy b/latte/fr/recipes.texy index 0fafcd16d6..4f2be42390 100644 --- a/latte/fr/recipes.texy +++ b/latte/fr/recipes.texy @@ -9,7 +9,7 @@ Conseils et astuces - L'EDI NetBeans a un support intégré - PhpStorm : installez le [plugin Latte |https://plugins.jetbrains.com/plugin/7457-latte] en `Settings > Plugins > Marketplace` -- VS Code : cherchez dans markerplace le plugin "Nette Latte + Neon". +- VS Code : rechercher sur markerplace le plugin [Nette Latte + Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] ou [Nette Latte templates |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] - Sublime Text 3 : dans Package Control, trouvez et installez le paquet `Nette` et sélectionnez Latte dans le menu déroulant. `View > Syntax` - Dans les anciens éditeurs, utilisez la mise en évidence Smarty pour les fichiers .latte. diff --git a/latte/hu/recipes.texy b/latte/hu/recipes.texy index 099db80aa9..15ba057b29 100644 --- a/latte/hu/recipes.texy +++ b/latte/hu/recipes.texy @@ -9,7 +9,7 @@ Szerkesztők és IDE .[#toc-editors-and-ide] - A NetBeans IDE beépített támogatással rendelkezik - PhpStorm: telepítse a [Latte bővítményt |https://plugins.jetbrains.com/plugin/7457-latte] a `Settings > Plugins > Marketplace` -- VS Code: keresse meg a markerplace-t a "Nette Latte + Neon" pluginnal. +- VS kód: keresés markerplace a [Nette Latte + Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] vagy [Nette Latte sablonok |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] pluginhoz - Sublime Text 3: a Package Controlban keresse meg és telepítse a `Nette` csomagot és válassza ki a Latte-t a `View > Syntax` - a régi szerkesztőkben használja a Smarty kiemelést a .latte fájlokra diff --git a/latte/it/recipes.texy b/latte/it/recipes.texy index 5985254606..70b673c3c4 100644 --- a/latte/it/recipes.texy +++ b/latte/it/recipes.texy @@ -9,7 +9,7 @@ Scrivete i modelli in un editor o IDE che supporti Latte. Sarà molto più piace - NetBeans IDE ha un supporto integrato - PhpStorm: installare il [plugin Latte |https://plugins.jetbrains.com/plugin/7457-latte] in `Settings > Plugins > Marketplace` -- VS Code: cercare il plugin "Nette Latte + Neon" in Markerplace +- Codice VS: cercare markerplace per il plugin [dei modelli |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] [Nette Latte + Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] o [Nette Latte |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] - Sublime Text 3: in Package Control trovare e installare il pacchetto `Nette` e selezionare Latte in `View > Syntax` - nei vecchi editor usare l'evidenziazione Smarty per i file .latte diff --git a/latte/ja/recipes.texy b/latte/ja/recipes.texy index 56ba9e0068..6d64bc9d3e 100644 --- a/latte/ja/recipes.texy +++ b/latte/ja/recipes.texy @@ -9,7 +9,7 @@ Latteに対応したエディタやIDEでテンプレートを書きましょう - NetBeans IDEはサポートが組み込まれています - PhpStorm:[Latteプラグ |https://plugins.jetbrains.com/plugin/7457-latte]インをインストールする`Settings > Plugins > Marketplace` -- VS Code:マーカープレイスで「Nette Latte + Neon」プラグインを探す +- VSコード:[Nette Latte + Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte]または[Nette Latteテンプレートプラグインの |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang]markerplace検索 - Sublime Text 3: パッケージコントロールで`Nette` パッケージを検索してインストールし、Latteを選択します。`View > Syntax` - 古いエディタでは、.latte ファイルに Smarty ハイライトを使用します。 diff --git a/latte/pl/recipes.texy b/latte/pl/recipes.texy index c95813ae11..a0cbc407c6 100644 --- a/latte/pl/recipes.texy +++ b/latte/pl/recipes.texy @@ -9,7 +9,7 @@ Napisz szablony w edytorze lub IDE, który ma wsparcie dla Latte. Będzie to o w - NetBeans IDE ma wbudowaną obsługę - PhpStorm: zainstaluj [wtyczkę Latte |https://plugins.jetbrains.com/plugin/7457-latte] w `Settings > Plugins > Marketplace` -- Kod VS: wyszukiwanie w markerplace dla wtyczki "Nette Latte + Neon" +- VS Code: wyszukaj markerplace dla [Nette Latte + Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] lub [Nette Latte templates |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] plugin - Sublime Text 3: w Package Control znajdź i zainstaluj pakiet `Nette` i wybierz Latte w `View > Syntax` - W starych edytorach użyj podświetlenia Smarty dla plików .latte diff --git a/latte/pt/recipes.texy b/latte/pt/recipes.texy index fa24fa5399..1e66873211 100644 --- a/latte/pt/recipes.texy +++ b/latte/pt/recipes.texy @@ -9,7 +9,7 @@ Escreva os modelos em um editor ou IDE que tenha suporte para Latte. Será muito - NetBeans IDE tem suporte integrado - PhpStorm: instale o [plugin Latte |https://plugins.jetbrains.com/plugin/7457-latte] `Settings > Plugins > Marketplace` -- Código VS: busca no marcador de busca do plugin "Nette Latte + Neon +- Código VS: procure no markerplace pelo plug-in [Nette Latte + Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] ou [Nette Latte templates |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] - Texto Sublime 3: em Package Control find and install `Nette` e selecione Latte in `View > Syntax` - em editores antigos usam Smarty highlighting para arquivos .latte diff --git a/latte/ro/recipes.texy b/latte/ro/recipes.texy index 88795d0716..7f9c6c67bf 100644 --- a/latte/ro/recipes.texy +++ b/latte/ro/recipes.texy @@ -9,7 +9,7 @@ Scrieți șabloane într-un editor sau IDE care are suport pentru Latte. Va fi m - NetBeans IDE are suport încorporat - PhpStorm: instalați [pluginul Latte |https://plugins.jetbrains.com/plugin/7457-latte] în `Settings > Plugins > Marketplace` -- VS Code: căutați în markerplace pentru pluginul "Nette Latte + Neon" +- VS Code: căutați markerplace pentru Nette [Latte |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] [+ Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] sau Nette [Latte șabloane |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] plugin - Sublime Text 3: în Package Control găsiți și instalați pachetul `Nette` și selectați Latte în `View > Syntax` - în vechile editoare utilizați evidențierea Smarty pentru fișierele .latte diff --git a/latte/ru/recipes.texy b/latte/ru/recipes.texy index b978c389a8..35e0d01526 100644 --- a/latte/ru/recipes.texy +++ b/latte/ru/recipes.texy @@ -9,7 +9,7 @@ - NetBeans IDE имеет встроенную поддержку - PhpStorm: установите [плагин Latte |https://plugins.jetbrains.com/plugin/7457-latte] в `Settings > Plugins > Marketplace` -- VS Code: найдите в маркерплейсе плагин "Nette Latte + Neon" +- VS Code: поиск маркерплейса для плагина [Nette Latte + Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] или [шаблонов Nette Latte |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] - Sublime Text 3: в Package Control найдите и установите пакет `Nette` и выберите Latte in `View > Syntax` - в старых редакторах используйте подсветку Smarty для файлов .latte diff --git a/latte/sl/recipes.texy b/latte/sl/recipes.texy index f9b3d43c7d..94203c290d 100644 --- a/latte/sl/recipes.texy +++ b/latte/sl/recipes.texy @@ -9,7 +9,7 @@ Predloge pišite v urejevalniku ali IDE, ki podpira Latte. Bilo bo veliko bolj p - V okolju NetBeans IDE je vgrajena podpora - PhpStorm: namestite [vtičnik Latte |https://plugins.jetbrains.com/plugin/7457-latte] v `Settings > Plugins > Marketplace` -- Koda VS: iskanje v markerplaceu za vtičnik "Nette Latte + Neon" +- VS koda: iskanje markerplace za [Nette Latte + Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] ali [Nette Latte predloge |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] plugin - Sublime Text 3: v Upravljanju paketov poiščite in namestite paket `Nette` ter izberite Latte v `View > Syntax` - V starih urejevalnikih uporabite Smartyjevo označevanje za datoteke .latte diff --git a/latte/tr/recipes.texy b/latte/tr/recipes.texy index 45c99eaa74..964b762217 100644 --- a/latte/tr/recipes.texy +++ b/latte/tr/recipes.texy @@ -9,7 +9,7 @@ Editörler ve IDE .[#toc-editors-and-ide] - NetBeans IDE yerleşik desteğe sahiptir - PhpStorm: [Latte eklentisini |https://plugins.jetbrains.com/plugin/7457-latte] şuraya yükleyin `Settings > Plugins > Marketplace` -- VS Code: "Nette Latte + Neon" eklentisi için markerplace'te arama yapın +- VS Code: [Nette Latte + Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] veya [Nette Latte şablonları |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] eklentisi için markerplace'te arama yapın - Sublime Text 3: Paket Kontrolünde `Nette` paketini bulun ve yükleyin ve Latte'yi seçin `View > Syntax` - eski düzenleyicilerde .latte dosyaları için Smarty vurgulamasını kullanın diff --git a/latte/uk/recipes.texy b/latte/uk/recipes.texy index 29537ce07e..33db8bf8af 100644 --- a/latte/uk/recipes.texy +++ b/latte/uk/recipes.texy @@ -9,7 +9,7 @@ - NetBeans IDE має вбудовану підтримку - PhpStorm: встановіть [плагін Latte |https://plugins.jetbrains.com/plugin/7457-latte] в `Settings > Plugins > Marketplace` -- VS Code: знайдіть у маркерплейсі плагін "Nette Latte + Neon" +- VS Code: пошук маркерів для плагіна [шаблонів |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] [Nette Latte + Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] або [Nette Latte |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] - Sublime Text 3: у Package Control знайдіть і встановіть пакет `Nette` і виберіть Latte in `View > Syntax` - у старих редакторах використовуйте підсвічування Smarty для файлів .latte From 49541dc1a2bffe11d2f12030a7941c82869c88e4 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 4 Apr 2024 17:26:26 +0200 Subject: [PATCH 067/137] typo --- database/cs/upgrading.texy | 1 - 1 file changed, 1 deletion(-) diff --git a/database/cs/upgrading.texy b/database/cs/upgrading.texy index 22963a8271..0a89ef3585 100644 --- a/database/cs/upgrading.texy +++ b/database/cs/upgrading.texy @@ -12,4 +12,3 @@ Kód byl pečlivě vyladěn pro PHP 8.1. Byly doplněny všechny nové typehinty - MySQL: nulové datum `0000-00-00` vrací jako `null` - MySQL: decimal bez desetinných míst vrací jako int místo float - typ `time` vrací jako DateTime s datumem `1. 1. 0001` místo aktuálního data - From 43a39908cf6f99e173c6f049d416f3b898c69b52 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 18 Apr 2024 16:58:11 +0200 Subject: [PATCH 068/137] typo --- best-practices/bg/pagination.texy | 1 - best-practices/cs/pagination.texy | 1 - best-practices/de/pagination.texy | 1 - best-practices/el/pagination.texy | 1 - best-practices/en/pagination.texy | 1 - best-practices/es/pagination.texy | 1 - best-practices/fr/pagination.texy | 1 - best-practices/hu/pagination.texy | 1 - best-practices/it/pagination.texy | 1 - best-practices/pl/pagination.texy | 1 - best-practices/pt/pagination.texy | 1 - best-practices/ro/pagination.texy | 1 - best-practices/ru/pagination.texy | 1 - best-practices/sl/pagination.texy | 1 - best-practices/tr/pagination.texy | 1 - best-practices/uk/pagination.texy | 1 - utils/bg/filesystem.texy | 1 - utils/cs/filesystem.texy | 1 - utils/de/filesystem.texy | 1 - utils/el/filesystem.texy | 1 - utils/en/filesystem.texy | 1 - utils/es/filesystem.texy | 1 - utils/fr/filesystem.texy | 1 - utils/hu/filesystem.texy | 1 - utils/it/filesystem.texy | 1 - utils/pl/filesystem.texy | 1 - utils/pt/filesystem.texy | 1 - utils/ro/filesystem.texy | 1 - utils/ru/filesystem.texy | 1 - utils/sl/filesystem.texy | 1 - utils/tr/filesystem.texy | 1 - utils/uk/filesystem.texy | 1 - 32 files changed, 32 deletions(-) diff --git a/best-practices/bg/pagination.texy b/best-practices/bg/pagination.texy index be7883dffc..28256dd731 100644 --- a/best-practices/bg/pagination.texy +++ b/best-practices/bg/pagination.texy @@ -198,7 +198,6 @@ class ArticleRepository ) { } - public function findPublishedArticles(): Nette\Database\Table\Selection { return $this->database->table('articles') diff --git a/best-practices/cs/pagination.texy b/best-practices/cs/pagination.texy index 46a00cd256..bf7d18a418 100644 --- a/best-practices/cs/pagination.texy +++ b/best-practices/cs/pagination.texy @@ -198,7 +198,6 @@ class ArticleRepository ) { } - public function findPublishedArticles(): Nette\Database\Table\Selection { return $this->database->table('articles') diff --git a/best-practices/de/pagination.texy b/best-practices/de/pagination.texy index 5775e52df1..ef5a0920ad 100644 --- a/best-practices/de/pagination.texy +++ b/best-practices/de/pagination.texy @@ -198,7 +198,6 @@ class ArticleRepository ) { } - public function findPublishedArticles(): Nette\Database\Table\Selection { return $this->database->table('articles') diff --git a/best-practices/el/pagination.texy b/best-practices/el/pagination.texy index 3003b38a84..06fca7da8a 100644 --- a/best-practices/el/pagination.texy +++ b/best-practices/el/pagination.texy @@ -198,7 +198,6 @@ class ArticleRepository ) { } - public function findPublishedArticles(): Nette\Database\Table\Selection { return $this->database->table('articles') diff --git a/best-practices/en/pagination.texy b/best-practices/en/pagination.texy index c0c0007e9b..113ce80193 100644 --- a/best-practices/en/pagination.texy +++ b/best-practices/en/pagination.texy @@ -198,7 +198,6 @@ class ArticleRepository ) { } - public function findPublishedArticles(): Nette\Database\Table\Selection { return $this->database->table('articles') diff --git a/best-practices/es/pagination.texy b/best-practices/es/pagination.texy index 4638f53da7..44d6fddd5f 100644 --- a/best-practices/es/pagination.texy +++ b/best-practices/es/pagination.texy @@ -198,7 +198,6 @@ class ArticleRepository ) { } - public function findPublishedArticles(): Nette\Database\Table\Selection { return $this->database->table('articles') diff --git a/best-practices/fr/pagination.texy b/best-practices/fr/pagination.texy index 9cb7e34af0..cbd07b5ec6 100644 --- a/best-practices/fr/pagination.texy +++ b/best-practices/fr/pagination.texy @@ -198,7 +198,6 @@ class ArticleRepository ) { } - public function findPublishedArticles(): Nette\Database\Table\Selection { return $this->database->table('articles') diff --git a/best-practices/hu/pagination.texy b/best-practices/hu/pagination.texy index eee3c4024b..e1805afd07 100644 --- a/best-practices/hu/pagination.texy +++ b/best-practices/hu/pagination.texy @@ -198,7 +198,6 @@ class ArticleRepository ) { } - public function findPublishedArticles(): Nette\Database\Table\Selection { return $this->database->table('articles') diff --git a/best-practices/it/pagination.texy b/best-practices/it/pagination.texy index f88acbacb5..0d6ca96483 100644 --- a/best-practices/it/pagination.texy +++ b/best-practices/it/pagination.texy @@ -198,7 +198,6 @@ class ArticleRepository ) { } - public function findPublishedArticles(): Nette\Database\Table\Selection { return $this->database->table('articles') diff --git a/best-practices/pl/pagination.texy b/best-practices/pl/pagination.texy index 83ff2c4cd9..d6da41b76b 100644 --- a/best-practices/pl/pagination.texy +++ b/best-practices/pl/pagination.texy @@ -198,7 +198,6 @@ class ArticleRepository ) { } - public function findPublishedArticles(): Nette\Database\Table\Selection { return $this->database->table('articles') diff --git a/best-practices/pt/pagination.texy b/best-practices/pt/pagination.texy index dfce31dfc6..7fae6d5b5e 100644 --- a/best-practices/pt/pagination.texy +++ b/best-practices/pt/pagination.texy @@ -198,7 +198,6 @@ class ArticleRepository ) { } - public function findPublishedArticles(): Nette\Database\Table\Selection { return $this->database->table('articles') diff --git a/best-practices/ro/pagination.texy b/best-practices/ro/pagination.texy index 4175e89bd9..40d9de47aa 100644 --- a/best-practices/ro/pagination.texy +++ b/best-practices/ro/pagination.texy @@ -198,7 +198,6 @@ class ArticleRepository ) { } - public function findPublishedArticles(): Nette\Database\Table\Selection { return $this->database->table('articles') diff --git a/best-practices/ru/pagination.texy b/best-practices/ru/pagination.texy index 11f52f40f2..6d384a2ebf 100644 --- a/best-practices/ru/pagination.texy +++ b/best-practices/ru/pagination.texy @@ -198,7 +198,6 @@ class ArticleRepository ) { } - public function findPublishedArticles(): Nette\Database\Table\Selection { return $this->database->table('articles') diff --git a/best-practices/sl/pagination.texy b/best-practices/sl/pagination.texy index b5322e1cd1..fff9e4bf1f 100644 --- a/best-practices/sl/pagination.texy +++ b/best-practices/sl/pagination.texy @@ -198,7 +198,6 @@ class ArticleRepository ) { } - public function findPublishedArticles(): Nette\Database\Table\Selection { return $this->database->table('articles') diff --git a/best-practices/tr/pagination.texy b/best-practices/tr/pagination.texy index 5ae4641731..0f0d378bfd 100644 --- a/best-practices/tr/pagination.texy +++ b/best-practices/tr/pagination.texy @@ -198,7 +198,6 @@ class ArticleRepository ) { } - public function findPublishedArticles(): Nette\Database\Table\Selection { return $this->database->table('articles') diff --git a/best-practices/uk/pagination.texy b/best-practices/uk/pagination.texy index b0883298b5..56ddd52028 100644 --- a/best-practices/uk/pagination.texy +++ b/best-practices/uk/pagination.texy @@ -198,7 +198,6 @@ class ArticleRepository ) { } - public function findPublishedArticles(): Nette\Database\Table\Selection { return $this->database->table('articles') diff --git a/utils/bg/filesystem.texy b/utils/bg/filesystem.texy index e4950c69f1..ea12aa182e 100644 --- a/utils/bg/filesystem.texy +++ b/utils/bg/filesystem.texy @@ -191,7 +191,6 @@ class AnyClassUsingFileSystem ) { } - public function readConfig(): string { return $this->fileSystem->read(/* ... */); diff --git a/utils/cs/filesystem.texy b/utils/cs/filesystem.texy index 3ceacacb4e..d1a844fffd 100644 --- a/utils/cs/filesystem.texy +++ b/utils/cs/filesystem.texy @@ -191,7 +191,6 @@ class AnyClassUsingFileSystem ) { } - public function readConfig(): string { return $this->fileSystem->read(/* ... */); diff --git a/utils/de/filesystem.texy b/utils/de/filesystem.texy index 94f3eaef39..dde00658a2 100644 --- a/utils/de/filesystem.texy +++ b/utils/de/filesystem.texy @@ -191,7 +191,6 @@ class AnyClassUsingFileSystem ) { } - public function readConfig(): string { return $this->fileSystem->read(/* ... */); diff --git a/utils/el/filesystem.texy b/utils/el/filesystem.texy index 1a0317bbb3..7219be059f 100644 --- a/utils/el/filesystem.texy +++ b/utils/el/filesystem.texy @@ -191,7 +191,6 @@ class AnyClassUsingFileSystem ) { } - public function readConfig(): string { return $this->fileSystem->read(/* ... */); diff --git a/utils/en/filesystem.texy b/utils/en/filesystem.texy index 522039c28e..fab3feea01 100644 --- a/utils/en/filesystem.texy +++ b/utils/en/filesystem.texy @@ -191,7 +191,6 @@ class AnyClassUsingFileSystem ) { } - public function readConfig(): string { return $this->fileSystem->read(/* ... */); diff --git a/utils/es/filesystem.texy b/utils/es/filesystem.texy index dc546ee9a5..e3cd23b683 100644 --- a/utils/es/filesystem.texy +++ b/utils/es/filesystem.texy @@ -191,7 +191,6 @@ class AnyClassUsingFileSystem ) { } - public function readConfig(): string { return $this->fileSystem->read(/* ... */); diff --git a/utils/fr/filesystem.texy b/utils/fr/filesystem.texy index 9eebde9692..19a148c11f 100644 --- a/utils/fr/filesystem.texy +++ b/utils/fr/filesystem.texy @@ -191,7 +191,6 @@ class AnyClassUsingFileSystem ) { } - public function readConfig(): string { return $this->fileSystem->read(/* ... */); diff --git a/utils/hu/filesystem.texy b/utils/hu/filesystem.texy index 37eaf4d0e7..36f0687c1b 100644 --- a/utils/hu/filesystem.texy +++ b/utils/hu/filesystem.texy @@ -191,7 +191,6 @@ class AnyClassUsingFileSystem ) { } - public function readConfig(): string { return $this->fileSystem->read(/* ... */); diff --git a/utils/it/filesystem.texy b/utils/it/filesystem.texy index 9b8a981282..3fa2a45128 100644 --- a/utils/it/filesystem.texy +++ b/utils/it/filesystem.texy @@ -191,7 +191,6 @@ class AnyClassUsingFileSystem ) { } - public function readConfig(): string { return $this->fileSystem->read(/* ... */); diff --git a/utils/pl/filesystem.texy b/utils/pl/filesystem.texy index 0ccc81bcff..01382d8eb5 100644 --- a/utils/pl/filesystem.texy +++ b/utils/pl/filesystem.texy @@ -191,7 +191,6 @@ class AnyClassUsingFileSystem ) { } - public function readConfig(): string { return $this->fileSystem->read(/* ... */); diff --git a/utils/pt/filesystem.texy b/utils/pt/filesystem.texy index 2b3c6ef368..5ef16b465e 100644 --- a/utils/pt/filesystem.texy +++ b/utils/pt/filesystem.texy @@ -191,7 +191,6 @@ class AnyClassUsingFileSystem ) { } - public function readConfig(): string { return $this->fileSystem->read(/* ... */); diff --git a/utils/ro/filesystem.texy b/utils/ro/filesystem.texy index 029969d120..f57c3eaa54 100644 --- a/utils/ro/filesystem.texy +++ b/utils/ro/filesystem.texy @@ -191,7 +191,6 @@ class AnyClassUsingFileSystem ) { } - public function readConfig(): string { return $this->fileSystem->read(/* ... */); diff --git a/utils/ru/filesystem.texy b/utils/ru/filesystem.texy index 39c217a040..8704cd54e9 100644 --- a/utils/ru/filesystem.texy +++ b/utils/ru/filesystem.texy @@ -191,7 +191,6 @@ class AnyClassUsingFileSystem ) { } - public function readConfig(): string { return $this->fileSystem->read(/* ... */); diff --git a/utils/sl/filesystem.texy b/utils/sl/filesystem.texy index 4f2aea2f35..6c144c173b 100644 --- a/utils/sl/filesystem.texy +++ b/utils/sl/filesystem.texy @@ -191,7 +191,6 @@ class AnyClassUsingFileSystem ) { } - public function readConfig(): string { return $this->fileSystem->read(/* ... */); diff --git a/utils/tr/filesystem.texy b/utils/tr/filesystem.texy index 88aa5f6a37..a5c5931d3e 100644 --- a/utils/tr/filesystem.texy +++ b/utils/tr/filesystem.texy @@ -191,7 +191,6 @@ class AnyClassUsingFileSystem ) { } - public function readConfig(): string { return $this->fileSystem->read(/* ... */); diff --git a/utils/uk/filesystem.texy b/utils/uk/filesystem.texy index 36f7ea9579..cd1d667c15 100644 --- a/utils/uk/filesystem.texy +++ b/utils/uk/filesystem.texy @@ -191,7 +191,6 @@ class AnyClassUsingFileSystem ) { } - public function readConfig(): string { return $this->fileSystem->read(/* ... */); From 905c5a4a7633ff99faaf534264e06c7348c6d729 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 4 Apr 2024 17:21:55 +0200 Subject: [PATCH 069/137] uses GitHub Actions --- .github/workflows/coding-style.yml | 17 +++++++++++++++++ .travis.yml | 13 ------------- 2 files changed, 17 insertions(+), 13 deletions(-) create mode 100644 .github/workflows/coding-style.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/coding-style.yml b/.github/workflows/coding-style.yml new file mode 100644 index 0000000000..27ec1b2828 --- /dev/null +++ b/.github/workflows/coding-style.yml @@ -0,0 +1,17 @@ +name: Coding Style + +on: [push, pull_request] + +jobs: + nette_cc: + name: Nette Code Checker + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: shivammathur/setup-php@v2 + with: + php-version: 8.3 + coverage: none + + - run: composer create-project nette/code-checker temp/code-checker ^3 --no-progress + - run: php temp/code-checker/code-checker --no-progress diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 550b89053d..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -language: php - -script: - - php code-checker/src/code-checker.php - -before_script: - - travis_retry composer create-project nette/code-checker code-checker ~2.5 --no-interaction - -sudo: false - -cache: - directories: - - $HOME/.composer/cache From b4acaf8bd38d1ab1629e047e8f8cd8dedea8df4a Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sat, 6 Apr 2024 14:51:10 +0200 Subject: [PATCH 070/137] latte: simplified "{..}" --- application/bg/creating-links.texy | 2 +- application/cs/creating-links.texy | 2 +- application/de/creating-links.texy | 2 +- application/el/creating-links.texy | 2 +- application/en/creating-links.texy | 2 +- application/es/creating-links.texy | 2 +- application/fr/creating-links.texy | 2 +- application/hu/creating-links.texy | 2 +- application/it/creating-links.texy | 2 +- application/pl/creating-links.texy | 2 +- application/pt/creating-links.texy | 2 +- application/ro/creating-links.texy | 2 +- application/ru/creating-links.texy | 2 +- application/sl/creating-links.texy | 2 +- application/tr/creating-links.texy | 2 +- application/uk/creating-links.texy | 2 +- latte/bg/filters.texy | 10 +++++----- latte/bg/safety-first.texy | 2 +- latte/bg/syntax.texy | 2 +- latte/bg/tags.texy | 2 +- latte/cs/filters.texy | 10 +++++----- latte/cs/safety-first.texy | 2 +- latte/cs/syntax.texy | 2 +- latte/cs/tags.texy | 2 +- latte/de/filters.texy | 10 +++++----- latte/de/safety-first.texy | 2 +- latte/de/syntax.texy | 2 +- latte/de/tags.texy | 2 +- latte/el/filters.texy | 10 +++++----- latte/el/safety-first.texy | 2 +- latte/el/syntax.texy | 2 +- latte/el/tags.texy | 2 +- latte/en/filters.texy | 10 +++++----- latte/en/safety-first.texy | 2 +- latte/en/syntax.texy | 2 +- latte/en/tags.texy | 2 +- latte/es/filters.texy | 10 +++++----- latte/es/safety-first.texy | 2 +- latte/es/syntax.texy | 2 +- latte/es/tags.texy | 2 +- latte/fr/filters.texy | 10 +++++----- latte/fr/safety-first.texy | 2 +- latte/fr/syntax.texy | 2 +- latte/fr/tags.texy | 2 +- latte/hu/filters.texy | 10 +++++----- latte/hu/safety-first.texy | 2 +- latte/hu/syntax.texy | 2 +- latte/hu/tags.texy | 2 +- latte/it/filters.texy | 10 +++++----- latte/it/safety-first.texy | 2 +- latte/it/syntax.texy | 2 +- latte/it/tags.texy | 2 +- latte/ja/filters.texy | 10 +++++----- latte/ja/safety-first.texy | 2 +- latte/ja/syntax.texy | 2 +- latte/ja/tags.texy | 2 +- latte/pl/filters.texy | 10 +++++----- latte/pl/safety-first.texy | 2 +- latte/pl/syntax.texy | 2 +- latte/pl/tags.texy | 2 +- latte/pt/filters.texy | 10 +++++----- latte/pt/safety-first.texy | 2 +- latte/pt/syntax.texy | 2 +- latte/pt/tags.texy | 2 +- latte/ro/filters.texy | 10 +++++----- latte/ro/safety-first.texy | 2 +- latte/ro/syntax.texy | 2 +- latte/ro/tags.texy | 2 +- latte/ru/filters.texy | 10 +++++----- latte/ru/safety-first.texy | 2 +- latte/ru/syntax.texy | 2 +- latte/ru/tags.texy | 2 +- latte/sl/filters.texy | 10 +++++----- latte/sl/safety-first.texy | 2 +- latte/sl/syntax.texy | 2 +- latte/sl/tags.texy | 2 +- latte/tr/filters.texy | 10 +++++----- latte/tr/safety-first.texy | 2 +- latte/tr/syntax.texy | 2 +- latte/tr/tags.texy | 2 +- latte/uk/filters.texy | 10 +++++----- latte/uk/safety-first.texy | 2 +- latte/uk/syntax.texy | 2 +- latte/uk/tags.texy | 2 +- 84 files changed, 152 insertions(+), 152 deletions(-) diff --git a/application/bg/creating-links.texy b/application/bg/creating-links.texy index 14bdd3e2d9..e75c39e78b 100644 --- a/application/bg/creating-links.texy +++ b/application/bg/creating-links.texy @@ -213,7 +213,7 @@ $url = $this->link('Product:show', [$product->id, 'lang' => 'cs']); Ако искаме да направим препратка към презентаторите в шаблона на компонента, използваме тага `{plink}`: ```latte -главная страница +главная страница ``` или в кода diff --git a/application/cs/creating-links.texy b/application/cs/creating-links.texy index bd921ae70c..2d497b68f2 100644 --- a/application/cs/creating-links.texy +++ b/application/cs/creating-links.texy @@ -213,7 +213,7 @@ Protože [komponenty|components] jsou samostatné znovupoužitelné celky, kter Pokud bychom chtěli v šabloně komponenty odkazovat na presentery, použijeme k tomu značku `{plink}`: ```latte -úvod +úvod ``` nebo v kódu diff --git a/application/de/creating-links.texy b/application/de/creating-links.texy index b2dd309752..2543101182 100644 --- a/application/de/creating-links.texy +++ b/application/de/creating-links.texy @@ -213,7 +213,7 @@ Da [Komponenten |components] separate, wiederverwendbare Einheiten sind, die kei Wenn wir auf Präsentatoren in der Komponentenvorlage verlinken wollen, verwenden wir das Tag `{plink}`: ```latte -home +home ``` oder im Code diff --git a/application/el/creating-links.texy b/application/el/creating-links.texy index 8a9f563cf8..c77bb68c72 100644 --- a/application/el/creating-links.texy +++ b/application/el/creating-links.texy @@ -213,7 +213,7 @@ $url = $this->link('Product:show', [$product->id, 'lang' => 'cs']); Αν θέλουμε να συνδέσουμε με παρουσιαστές στο πρότυπο συστατικού, χρησιμοποιούμε την ετικέτα `{plink}`: ```latte -home +home ``` ή στον κώδικα diff --git a/application/en/creating-links.texy b/application/en/creating-links.texy index eb10c4c852..d80f9ce29b 100644 --- a/application/en/creating-links.texy +++ b/application/en/creating-links.texy @@ -213,7 +213,7 @@ Because [components] are separate reusable units that should have no relations t If we want to link to presenters in the component template, we use the tag `{plink}`: ```latte -home +home ``` or in the code diff --git a/application/es/creating-links.texy b/application/es/creating-links.texy index ed5ab76589..497734da6f 100644 --- a/application/es/creating-links.texy +++ b/application/es/creating-links.texy @@ -213,7 +213,7 @@ Dado que los [componentes |components] son unidades reutilizables independientes Si queremos enlazar con presentadores en la plantilla de componentes, utilizaremos la etiqueta `{plink}`: ```latte -home +home ``` o en el código diff --git a/application/fr/creating-links.texy b/application/fr/creating-links.texy index 32ad736c4b..35b5171f65 100644 --- a/application/fr/creating-links.texy +++ b/application/fr/creating-links.texy @@ -213,7 +213,7 @@ Comme les [composants |components] sont des unités distinctes réutilisables qu Si nous voulons créer un lien vers les présentateurs dans le modèle de composant, nous utilisons la balise `{plink}`: ```latte -home +home ``` ou dans le code diff --git a/application/hu/creating-links.texy b/application/hu/creating-links.texy index 052dc6f4ef..6adfa6d498 100644 --- a/application/hu/creating-links.texy +++ b/application/hu/creating-links.texy @@ -213,7 +213,7 @@ Mivel a [komponensek |components] különálló, újrafelhasználható egységek Ha a komponenssablonban előadókra akarunk hivatkozni, akkor a `{plink}` címkét használjuk: ```latte -home +home ``` vagy a kódban diff --git a/application/it/creating-links.texy b/application/it/creating-links.texy index a1dbcc4bb6..40648f85d6 100644 --- a/application/it/creating-links.texy +++ b/application/it/creating-links.texy @@ -213,7 +213,7 @@ Poiché i [componenti |components] sono unità riutilizzabili separate che non d Se vogliamo collegarci ai presentatori nel modello del componente, usiamo il tag `{plink}`: ```latte -home +home ``` o nel codice diff --git a/application/pl/creating-links.texy b/application/pl/creating-links.texy index 781a17e60d..bea0dda8d5 100644 --- a/application/pl/creating-links.texy +++ b/application/pl/creating-links.texy @@ -213,7 +213,7 @@ Ponieważ [komponenty |components] są samodzielnymi, wielokrotnego użytku jedn Gdybyśmy chcieli odwołać się do prezenterów w szablonie komponentu, użylibyśmy do tego celu tagu `{plink}`: ```latte -úvod +home ``` lub w kodzie diff --git a/application/pt/creating-links.texy b/application/pt/creating-links.texy index 24570ecfb2..349e4358cd 100644 --- a/application/pt/creating-links.texy +++ b/application/pt/creating-links.texy @@ -213,7 +213,7 @@ Como [os componentes |components] são unidades reutilizáveis separadas que nã Se quisermos fazer um link para apresentadores no modelo de componente, usamos a tag `{plink}`: ```latte -home +home ``` ou no código diff --git a/application/ro/creating-links.texy b/application/ro/creating-links.texy index 67bf8715d5..c296f1546a 100644 --- a/application/ro/creating-links.texy +++ b/application/ro/creating-links.texy @@ -213,7 +213,7 @@ Deoarece [componentele |components] sunt unități separate reutilizabile care n Dacă dorim să facem legătura cu prezentatorii din șablonul componentei, folosim eticheta `{plink}`: ```latte -home +home ``` sau în cod diff --git a/application/ru/creating-links.texy b/application/ru/creating-links.texy index 8961c3227b..ad3f4f361f 100644 --- a/application/ru/creating-links.texy +++ b/application/ru/creating-links.texy @@ -213,7 +213,7 @@ $url = $this->link('Product:show', [$product->id, 'lang' => 'cs']); Если мы хотим сделать ссылку на презентеры в шаблоне компонента, мы используем тег `{plink}`: ```latte -главная страница +главная страница ``` or in the code diff --git a/application/sl/creating-links.texy b/application/sl/creating-links.texy index c4732bce8b..1fb0ff24c2 100644 --- a/application/sl/creating-links.texy +++ b/application/sl/creating-links.texy @@ -213,7 +213,7 @@ Ker so [komponente |components] ločene enote za večkratno uporabo, ki naj ne b Če se želimo v predlogi komponente povezati s predstavniki, uporabimo oznako `{plink}`: ```latte -home +home ``` ali v kodi diff --git a/application/tr/creating-links.texy b/application/tr/creating-links.texy index 330930300d..34cde301ee 100644 --- a/application/tr/creating-links.texy +++ b/application/tr/creating-links.texy @@ -213,7 +213,7 @@ Bileşendeki Bağlantılar .[#toc-links-in-component] Bileşen şablonunda sunum yapanlara bağlantı vermek istiyorsak `{plink}` etiketini kullanırız: ```latte -home +home ``` veya kodda diff --git a/application/uk/creating-links.texy b/application/uk/creating-links.texy index 19f653904e..3f605ac54a 100644 --- a/application/uk/creating-links.texy +++ b/application/uk/creating-links.texy @@ -213,7 +213,7 @@ $url = $this->link('Product:show', [$product->id, 'lang' => 'cs']); Якщо ми хочемо зробити посилання на презентери в шаблоні компонента, ми використовуємо тег `{plink}`: ```latte -главная страница +главная страница ``` or in the code diff --git a/latte/bg/filters.texy b/latte/bg/filters.texy index 6283bf3c42..285a4b4d89 100644 --- a/latte/bg/filters.texy +++ b/latte/bg/filters.texy @@ -203,8 +203,8 @@ checkUrl .[filter] ```latte {var $link = 'javascript:window.close()'} -checked -unchecked +checked +unchecked ``` Отпечатва: @@ -235,7 +235,7 @@ dataStream(string mimetype = detect) .[filter] Нека имаме изображение в променлива `$img = Image::fromFile('obrazek.gif')`, тогава ```latte - + ``` Отпечатва например: @@ -416,8 +416,8 @@ nocheck .[filter] ```latte {var $link = 'javascript:window.close()'} -checked -unchecked +checked +unchecked ``` Отпечатъци: diff --git a/latte/bg/safety-first.texy b/latte/bg/safety-first.texy index 2693ba01f9..b8dca3c913 100644 --- a/latte/bg/safety-first.texy +++ b/latte/bg/safety-first.texy @@ -351,7 +351,7 @@ Latte автоматично проверява дали променливат ```latte {var $link = 'javascript:attack()'} -click here +click here ``` Пише: diff --git a/latte/bg/syntax.texy b/latte/bg/syntax.texy index 5a5eb32559..b7406ed381 100644 --- a/latte/bg/syntax.texy +++ b/latte/bg/syntax.texy @@ -98,7 +98,7 @@ n:атрибути .[#toc-n-attributes] Или с префикс `tag-` функционалността се прилага само за HTML тагове: ```latte -

        Title

        +

        Title

        ``` В зависимост от стойността на променливата `$url` ще бъде изведено следното: diff --git a/latte/bg/tags.texy b/latte/bg/tags.texy index 24e6ad3834..758ce4721e 100644 --- a/latte/bg/tags.texy +++ b/latte/bg/tags.texy @@ -292,7 +292,7 @@ Age: {date('Y') - $birth}
        Използвайте условието `{ifset $var}`, за да определите дали дадена променлива (или няколко променливи) съществува и има ненулева стойност. Всъщност това е същото като `if (isset($var))` в PHP. Както всеки сдвоен таг, и този може да бъде записан като [n:attribute |syntax#n-attributes], затова нека го покажем с пример: ```latte - + ``` diff --git a/latte/cs/filters.texy b/latte/cs/filters.texy index b7a86927f4..55382c19ef 100644 --- a/latte/cs/filters.texy +++ b/latte/cs/filters.texy @@ -203,8 +203,8 @@ Vynutí ošetření URL adresy. Kontroluje, zda proměnná obsahuje webovou URL ```latte {var $link = 'javascript:window.close()'} -kontrolované -nekontrolované +kontrolované +nekontrolované ``` Vypíše: @@ -235,7 +235,7 @@ Konvertuje obsah do data URI scheme. Pomocí něj lze do HTML nebo CSS vkládat Mějme v proměnné obrázek `$img = Image::fromFile('obrazek.gif')`, poté ```latte - + ``` Vypíše například: @@ -416,8 +416,8 @@ Pokud odkaz používá jiné schéma, např. `javascript:` nebo `data:`, a jste ```latte {var $link = 'javascript:window.close()'} -kontrolované -nekontrolované +kontrolované +nekontrolované ``` Vypíše: diff --git a/latte/cs/safety-first.texy b/latte/cs/safety-first.texy index 44bd9f4edf..ed212e83b6 100644 --- a/latte/cs/safety-first.texy +++ b/latte/cs/safety-first.texy @@ -351,7 +351,7 @@ Latte automaticky kontroluje, zda proměnná použitá v atributech `src` nebo ` ```latte {var $link = 'javascript:attack()'} -klikni +klikni ``` Vypíše: diff --git a/latte/cs/syntax.texy b/latte/cs/syntax.texy index d90970c534..e1532cabd0 100644 --- a/latte/cs/syntax.texy +++ b/latte/cs/syntax.texy @@ -98,7 +98,7 @@ Vypíše se: Nebo pomocí prefixu `tag-` aplikujeme funkcionalitu jen na samotné HTML značky: ```latte -

        Title

        +

        Title

        ``` Což vypíše v závislosti na proměnné `$url`: diff --git a/latte/cs/tags.texy b/latte/cs/tags.texy index 6725270e1d..8f90f0553a 100644 --- a/latte/cs/tags.texy +++ b/latte/cs/tags.texy @@ -292,7 +292,7 @@ Viz také [`{ifset block}` |template-inheritance#Kontrola existence bloků] Pomocí podmínky `{ifset $var}` zjistíme, zda proměnná (nebo více proměnných) existuje a má ne*null*ovou hodnotu. Vlastně jde o totéž, jako `if (isset($var))` v PHP. Jako každou párovou značku ji lze zapisovat i v podobě [n:attributu|syntax#n:atributy], tak si to ukažme jako příklad: ```latte - + ``` diff --git a/latte/de/filters.texy b/latte/de/filters.texy index 3784d34eb4..8d134d91de 100644 --- a/latte/de/filters.texy +++ b/latte/de/filters.texy @@ -203,8 +203,8 @@ Erzwingt URL-Sanitization. Sie prüft, ob die Variable eine Web-URL enthält (d. ```latte {var $link = 'javascript:window.close()'} -checked -unchecked +checked +unchecked ``` Druckt: @@ -235,7 +235,7 @@ Konvertiert den Inhalt in ein Daten-URI-Schema. Es kann verwendet werden, um Bil Nehmen wir an, ein Bild befindet sich in einer Variablen `$img = Image::fromFile('obrazek.gif')`, dann ```latte - + ``` Druckt zum Beispiel: @@ -416,8 +416,8 @@ Wenn der Link ein anderes Schema verwendet, z. B. `javascript:` oder `data:`, un ```latte {var $link = 'javascript:window.close()'} -checked -unchecked +checked +unchecked ``` Drucke: diff --git a/latte/de/safety-first.texy b/latte/de/safety-first.texy index ef699fd12a..6529d9848c 100644 --- a/latte/de/safety-first.texy +++ b/latte/de/safety-first.texy @@ -351,7 +351,7 @@ Latte prüft automatisch, ob die in den Attributen `src` oder `href` verwendete ```latte {var $link = 'javascript:attack()'} -click here +click here ``` Schreibt: diff --git a/latte/de/syntax.texy b/latte/de/syntax.texy index 33a208a405..b6f6482c5b 100644 --- a/latte/de/syntax.texy +++ b/latte/de/syntax.texy @@ -98,7 +98,7 @@ Druckt: Oder durch die Verwendung des Präfixes `tag-` wird die Funktionalität nur auf die HTML-Tags angewendet: ```latte -

        Title

        +

        Title

        ``` Je nach dem Wert der Variable `$url` wird dies gedruckt: diff --git a/latte/de/tags.texy b/latte/de/tags.texy index 839cdd7f75..a76145a8d8 100644 --- a/latte/de/tags.texy +++ b/latte/de/tags.texy @@ -292,7 +292,7 @@ Siehe auch [`{ifset block}` |template-inheritance#checking-block-existence] Verwenden Sie die `{ifset $var}` Bedingung, um festzustellen, ob eine Variable (oder mehrere Variablen) existiert und einen Nicht-Null-Wert hat. Es ist eigentlich das Gleiche wie `if (isset($var))` in PHP. Wie jedes Paar-Tag kann es in der Form von [n:attribute |syntax#n:attributes] geschrieben werden, also zeigen wir es in einem Beispiel: ```latte - + ``` diff --git a/latte/el/filters.texy b/latte/el/filters.texy index ac76626627..8a45af2856 100644 --- a/latte/el/filters.texy +++ b/latte/el/filters.texy @@ -203,8 +203,8 @@ checkUrl .[filter] ```latte {var $link = 'javascript:window.close()'} -checked -unchecked +checked +unchecked ``` Εκτυπώνει: @@ -235,7 +235,7 @@ dataStream(string mimetype = detect) .[filter] Ας έχουμε μια εικόνα σε μια μεταβλητή `$img = Image::fromFile('obrazek.gif')`, τότε ```latte - + ``` Εκτυπώνει για παράδειγμα: @@ -416,8 +416,8 @@ nocheck .[filter] ```latte {var $link = 'javascript:window.close()'} -checked -unchecked +checked +unchecked ``` Εκτυπώσεις: diff --git a/latte/el/safety-first.texy b/latte/el/safety-first.texy index 10e6d61f4c..6322b713f0 100644 --- a/latte/el/safety-first.texy +++ b/latte/el/safety-first.texy @@ -351,7 +351,7 @@ Latte βλέπει το πρότυπο με τον ίδιο τρόπο που τ ```latte {var $link = 'javascript:attack()'} -click here +click here ``` Γράφει: diff --git a/latte/el/syntax.texy b/latte/el/syntax.texy index 8f36653703..3ea9bf87ab 100644 --- a/latte/el/syntax.texy +++ b/latte/el/syntax.texy @@ -98,7 +98,7 @@ n:attributes .[#toc-n-attributes] Η με τη χρήση του προθέματος `tag-` η λειτουργικότητα εφαρμόζεται μόνο στις ετικέτες HTML: ```latte -

        Title

        +

        Title

        ``` Ανάλογα με την τιμή της μεταβλητής `$url` αυτό θα εκτυπωθεί: diff --git a/latte/el/tags.texy b/latte/el/tags.texy index 068d3cd0cf..80f552c565 100644 --- a/latte/el/tags.texy +++ b/latte/el/tags.texy @@ -292,7 +292,7 @@ Age: {date('Y') - $birth}
        Χρησιμοποιήστε τη συνθήκη `{ifset $var}` για να προσδιορίσετε αν μια μεταβλητή (ή πολλαπλές μεταβλητές) υπάρχει και έχει μη μηδενική τιμή. Στην πραγματικότητα είναι το ίδιο με το `if (isset($var))` στην PHP. Όπως κάθε ετικέτα pair, μπορεί να γραφτεί με τη μορφή [n:attribute |syntax#n:attributes], οπότε ας το δείξουμε σε παράδειγμα: ```latte - + ``` diff --git a/latte/en/filters.texy b/latte/en/filters.texy index 3eacff86a4..f8f113b7f7 100644 --- a/latte/en/filters.texy +++ b/latte/en/filters.texy @@ -203,8 +203,8 @@ Enforces URL sanitization. It checks if the variable contains a web URL (ie. HTT ```latte {var $link = 'javascript:window.close()'} -checked -unchecked +checked +unchecked ``` Prints: @@ -235,7 +235,7 @@ Converts the content to data URI scheme. It can be used to insert images into HT Lets have an image in a variable `$img = Image::fromFile('obrazek.gif')`, then ```latte - + ``` Prints for example: @@ -416,8 +416,8 @@ If the link uses a different scheme, such as `javascript:` or `data:`, and you a ```latte {var $link = 'javascript:window.close()'} -checked -unchecked +checked +unchecked ``` Prints: diff --git a/latte/en/safety-first.texy b/latte/en/safety-first.texy index 83454d8ade..172c583ca6 100644 --- a/latte/en/safety-first.texy +++ b/latte/en/safety-first.texy @@ -351,7 +351,7 @@ Latte automatically checks whether the variable used in the `src` or `href` attr ```latte {var $link = 'javascript:attack()'} -click here +click here ``` Writes: diff --git a/latte/en/syntax.texy b/latte/en/syntax.texy index 532a8555a0..d5cb6a97e0 100644 --- a/latte/en/syntax.texy +++ b/latte/en/syntax.texy @@ -98,7 +98,7 @@ Prints: Or by using `tag-` prefix the functionality is applied on the HTML tags only: ```latte -

        Title

        +

        Title

        ``` Depending on the value of `$url` variable this will print: diff --git a/latte/en/tags.texy b/latte/en/tags.texy index a25ecff68e..356332803d 100644 --- a/latte/en/tags.texy +++ b/latte/en/tags.texy @@ -292,7 +292,7 @@ See also [`{ifset block}` |template-inheritance#checking-block-existence] Use the `{ifset $var}` condition to determine if a variable (or multiple variables) exists and has a non-null value. It's actually the same as `if (isset($var))` in PHP. Like any pair tag, this can be written in the form of [n:attribute|syntax#n:attributes], so let's show it in example: ```latte - + ``` diff --git a/latte/es/filters.texy b/latte/es/filters.texy index 81479c86c3..6579e256d2 100644 --- a/latte/es/filters.texy +++ b/latte/es/filters.texy @@ -203,8 +203,8 @@ Aplica la limpieza de URL. Comprueba si la variable contiene una URL web (es dec ```latte {var $link = 'javascript:window.close()'} -checked -unchecked +checked +unchecked ``` Imprime: @@ -235,7 +235,7 @@ Convierte el contenido en un esquema URI de datos. Puede utilizarse para inserta Tengamos una imagen en una variable `$img = Image::fromFile('obrazek.gif')`, entonces ```latte - + ``` Imprime por ejemplo @@ -416,8 +416,8 @@ Si el enlace utiliza un esquema diferente, como `javascript:` o `data:`, y está ```latte {var $link = 'javascript:window.close()'} -checked -unchecked +checked +unchecked ``` Imprime: diff --git a/latte/es/safety-first.texy b/latte/es/safety-first.texy index 5f70f5225d..4669fe47f3 100644 --- a/latte/es/safety-first.texy +++ b/latte/es/safety-first.texy @@ -351,7 +351,7 @@ Latte comprueba automáticamente si la variable utilizada en los atributos `src` ```latte {var $link = 'javascript:attack()'} -click here +click here ``` Escribe: diff --git a/latte/es/syntax.texy b/latte/es/syntax.texy index 8adcf5e086..2e4e2bacce 100644 --- a/latte/es/syntax.texy +++ b/latte/es/syntax.texy @@ -98,7 +98,7 @@ Imprime: O utilizando `tag-` prefijo la funcionalidad se aplica en las etiquetas HTML solamente: ```latte -

        Title

        +

        Title

        ``` Dependiendo del valor de la variable `$url` se imprimirá: diff --git a/latte/es/tags.texy b/latte/es/tags.texy index d529d1c009..a15396875c 100644 --- a/latte/es/tags.texy +++ b/latte/es/tags.texy @@ -292,7 +292,7 @@ Véase también [`{ifset block}` |template-inheritance#checking-block-existence] Utilice la condición `{ifset $var}` para determinar si una variable (o múltiples variables) existe y tiene un valor no nulo. En realidad es lo mismo que `if (isset($var))` en PHP. Como cualquier etiqueta de par, esto puede ser escrito en la forma de [n:attribute |syntax#n:attributes], así que vamos a mostrarlo en el ejemplo: ```latte - + ``` diff --git a/latte/fr/filters.texy b/latte/fr/filters.texy index 01cd3a3475..0e063d0655 100644 --- a/latte/fr/filters.texy +++ b/latte/fr/filters.texy @@ -203,8 +203,8 @@ Assure la désinfection des URL. Il vérifie si la variable contient une URL web ```latte {var $link = 'javascript:window.close()'} -checked -unchecked +checked +unchecked ``` Imprime : @@ -235,7 +235,7 @@ Convertit le contenu en schéma URI de données. Il peut être utilisé pour ins Si nous avons une image dans une variable `$img = Image::fromFile('obrazek.gif')`, alors ```latte - + ``` Imprime par exemple : @@ -416,8 +416,8 @@ Si le lien utilise un schéma différent, tel que `javascript:` ou `data:`, et q ```latte {var $link = 'javascript:window.close()'} -checked -unchecked +checked +unchecked ``` Imprimés : diff --git a/latte/fr/safety-first.texy b/latte/fr/safety-first.texy index b8fdd5708b..92e1a40c74 100644 --- a/latte/fr/safety-first.texy +++ b/latte/fr/safety-first.texy @@ -351,7 +351,7 @@ Latte vérifie automatiquement si la variable utilisée dans les attributs `src` ```latte {var $link = 'javascript:attack()'} -click here +click here ``` Écrit : diff --git a/latte/fr/syntax.texy b/latte/fr/syntax.texy index eda154bdf5..221453d873 100644 --- a/latte/fr/syntax.texy +++ b/latte/fr/syntax.texy @@ -98,7 +98,7 @@ Imprimés : Ou en utilisant le préfixe `tag-` la fonctionnalité est appliquée sur les balises HTML uniquement : ```latte -

        Title

        +

        Title

        ``` Selon la valeur de la variable `$url`, ceci s'imprimera : diff --git a/latte/fr/tags.texy b/latte/fr/tags.texy index 2899f54d90..98961782c6 100644 --- a/latte/fr/tags.texy +++ b/latte/fr/tags.texy @@ -292,7 +292,7 @@ Voir aussi [`{ifset block}` |template-inheritance#checking-block-existence] Utilisez la condition `{ifset $var}` pour déterminer si une variable (ou plusieurs variables) existe et a une valeur non nulle. C'est en fait la même chose que `if (isset($var))` en PHP. Comme toute balise de paire, elle peut être écrite sous la forme [n:attribut |syntax#n:attributes], alors montrons-la en exemple : ```latte - + ``` diff --git a/latte/hu/filters.texy b/latte/hu/filters.texy index 6e67a8ec5f..089b313db5 100644 --- a/latte/hu/filters.texy +++ b/latte/hu/filters.texy @@ -203,8 +203,8 @@ Kényszeríti az URL szanálását. Ellenőrzi, hogy a változó tartalmaz-e web ```latte {var $link = 'javascript:window.close()'} -checked -unchecked +checked +unchecked ``` Nyomtat: @@ -235,7 +235,7 @@ A tartalmat adat URI-sémává alakítja át. Használható képek HTML- vagy CS Legyen egy kép egy változóban `$img = Image::fromFile('obrazek.gif')`, akkor ```latte - + ``` Kinyomtatja például: @@ -416,8 +416,8 @@ Ha a hivatkozás más sémát használ, például `javascript:` vagy `data:`, é ```latte {var $link = 'javascript:window.close()'} -checked -unchecked +checked +unchecked ``` Nyomtatások: diff --git a/latte/hu/safety-first.texy b/latte/hu/safety-first.texy index f13a4f2ee0..1df495fcb7 100644 --- a/latte/hu/safety-first.texy +++ b/latte/hu/safety-first.texy @@ -351,7 +351,7 @@ A Latte automatikusan ellenőrzi, hogy a `src` vagy a `href` attribútumban hasz ```latte {var $link = 'javascript:attack()'} -click here +click here ``` Írja: diff --git a/latte/hu/syntax.texy b/latte/hu/syntax.texy index f0fdbbae0e..61340ef0e8 100644 --- a/latte/hu/syntax.texy +++ b/latte/hu/syntax.texy @@ -98,7 +98,7 @@ Nyomtatás: A `tag-` előtag használatával a funkciót csak a HTML-címkékre alkalmazzuk: ```latte -

        Title

        +

        Title

        ``` A `$url` változó értékétől függően ez kiírásra kerül: diff --git a/latte/hu/tags.texy b/latte/hu/tags.texy index 068aae2a75..36306dd87b 100644 --- a/latte/hu/tags.texy +++ b/latte/hu/tags.texy @@ -292,7 +292,7 @@ Lásd még [`{ifset block}` |template-inheritance#checking-block-existence] A `{ifset $var}` feltétel segítségével meghatározhatja, hogy egy változó (vagy több változó) létezik-e, és van-e nem null értékű értéke. Ez tulajdonképpen ugyanaz, mint a `if (isset($var))` a PHP-ben. Mint minden páros tag, ez is leírható [n:attribútum |syntax#n:attributes] formában, ezért mutassuk meg példában: ```latte - + ``` diff --git a/latte/it/filters.texy b/latte/it/filters.texy index 024d7cd79d..28aacbe3e8 100644 --- a/latte/it/filters.texy +++ b/latte/it/filters.texy @@ -203,8 +203,8 @@ Impone la sanitizzazione degli URL. Controlla se la variabile contiene un URL we ```latte {var $link = 'javascript:window.close()'} -checked -unchecked +checked +unchecked ``` Stampa: @@ -235,7 +235,7 @@ Converte il contenuto in uno schema URI di dati. Può essere usato per inserire Poniamo di avere un'immagine in una variabile `$img = Image::fromFile('obrazek.gif')`, allora ```latte - + ``` Stampa ad esempio: @@ -416,8 +416,8 @@ Se il link utilizza uno schema diverso, come `javascript:` o `data:`, e si è si ```latte {var $link = 'javascript:window.close()'} -checked -unchecked +checked +unchecked ``` Stampe: diff --git a/latte/it/safety-first.texy b/latte/it/safety-first.texy index 6ed5a293af..e70e37a2af 100644 --- a/latte/it/safety-first.texy +++ b/latte/it/safety-first.texy @@ -351,7 +351,7 @@ Latte controlla automaticamente se la variabile utilizzata negli attributi `src` ```latte {var $link = 'javascript:attack()'} -click here +click here ``` Scrive: diff --git a/latte/it/syntax.texy b/latte/it/syntax.texy index eef05b2ef3..4678d5ee18 100644 --- a/latte/it/syntax.texy +++ b/latte/it/syntax.texy @@ -98,7 +98,7 @@ Stampe: Oppure utilizzando il prefisso `tag-` la funzionalità viene applicata solo ai tag HTML: ```latte -

        Title

        +

        Title

        ``` A seconda del valore della variabile `$url` verrà stampato: diff --git a/latte/it/tags.texy b/latte/it/tags.texy index 5086c7081e..f3cc4079ba 100644 --- a/latte/it/tags.texy +++ b/latte/it/tags.texy @@ -292,7 +292,7 @@ Vedi anche [`{ifset block}` |template-inheritance#checking-block-existence] Utilizzare la condizione `{ifset $var}` per determinare se una variabile (o più variabili) esiste e ha un valore non nullo. In realtà è la stessa cosa di `if (isset($var))` in PHP. Come ogni tag di coppia, può essere scritto nella forma [n:attribute |syntax#n:attributes], quindi lo mostriamo in un esempio: ```latte - + ``` diff --git a/latte/ja/filters.texy b/latte/ja/filters.texy index d2c6eb78c2..9ffd2c17cc 100644 --- a/latte/ja/filters.texy +++ b/latte/ja/filters.texy @@ -203,8 +203,8 @@ URLのサニタイズ処理を行います。変数が Web URL (つまり HTTP/H ```latte {var $link = 'javascript:window.close()'} -checked -unchecked +checked +unchecked ``` 印刷します。 @@ -235,7 +235,7 @@ dataStream(string mimetype = detect) .[filter] 変数`$img = Image::fromFile('obrazek.gif')` に画像を入れておくとします。 ```latte - + ``` 例えば印刷します。 @@ -416,8 +416,8 @@ nocheck .[filter] ```latte {var $link = 'javascript:window.close()'} -checked -unchecked +checked +unchecked ``` 印刷物 diff --git a/latte/ja/safety-first.texy b/latte/ja/safety-first.texy index 8af99cf01d..f5d16e3692 100644 --- a/latte/ja/safety-first.texy +++ b/latte/ja/safety-first.texy @@ -351,7 +351,7 @@ Latte は`src` または`href` 属性で使用されている変数に Web URL ( ```latte {var $link = 'javascript:attack()'} -click here +click here ``` 書き込みを行います。 diff --git a/latte/ja/syntax.texy b/latte/ja/syntax.texy index 6aa80cb7a5..f1bf39d6ce 100644 --- a/latte/ja/syntax.texy +++ b/latte/ja/syntax.texy @@ -98,7 +98,7 @@ n:属性 .[#toc-n-attributes] また、`tag-` という接頭辞をつけると、HTML タグにのみ機能が適用されます。 ```latte -

        Title

        +

        Title

        ``` 変数`$url` の値によって、このように表示されます。 diff --git a/latte/ja/tags.texy b/latte/ja/tags.texy index 0737ec276c..65fc624eb9 100644 --- a/latte/ja/tags.texy +++ b/latte/ja/tags.texy @@ -292,7 +292,7 @@ n:attributesに接頭辞`tag-` を付けることができることをご存知 変数(あるいは複数の変数)が存在し、かつ非 null 値であるかどうかを調べるには、`{ifset $var}` 条件を使用します。これは、実際にはPHPの`if (isset($var))` と同じです。他のペアタグと同様に、[n:attributeの |syntax#n:attributes]形式で書くことができますので、例で紹介しましょう。 ```latte - + ``` diff --git a/latte/pl/filters.texy b/latte/pl/filters.texy index 26522886f7..686040ed31 100644 --- a/latte/pl/filters.texy +++ b/latte/pl/filters.texy @@ -203,8 +203,8 @@ Wymusza sanityzację adresów URL. Sprawdza czy zmienna zawiera adres URL strony ```latte {var $link = 'javascript:window.close()'} -checked -unchecked +checked +unchecked ``` Wydruki: @@ -235,7 +235,7 @@ Konwertuje zawartość na schemat URI danych. Może być używany do wstawiania Załóżmy, że mamy obrazek w zmiennej `$img = Image::fromFile('obrazek.gif')`, to ```latte - + ``` Drukuje na przykład: @@ -416,8 +416,8 @@ Jeśli link używa innego schematu, takiego jak `javascript:` lub `data:`, i jes ```latte {var $link = 'javascript:window.close()'} -checked -unchecked +checked +unchecked ``` Wydruki: diff --git a/latte/pl/safety-first.texy b/latte/pl/safety-first.texy index e862574247..a3cae08534 100644 --- a/latte/pl/safety-first.texy +++ b/latte/pl/safety-first.texy @@ -351,7 +351,7 @@ Latte automatycznie sprawdza, czy zmienna użyta w atrybutach `src` lub `href` z ```latte {var $link = 'javascript:attack()'} -klikni +click here ``` Wydruki: diff --git a/latte/pl/syntax.texy b/latte/pl/syntax.texy index 106fc68597..4d4bd4e523 100644 --- a/latte/pl/syntax.texy +++ b/latte/pl/syntax.texy @@ -98,7 +98,7 @@ Zostanie wydrukowany: Możesz też użyć przedrostka `tag-`, aby zastosować tę funkcjonalność do samych znaczników HTML: ```latte -

        Title

        +

        Title

        ``` Która wychodzi w zależności od zmiennej `$url`: diff --git a/latte/pl/tags.texy b/latte/pl/tags.texy index d0489ba7dd..03beb0ba26 100644 --- a/latte/pl/tags.texy +++ b/latte/pl/tags.texy @@ -292,7 +292,7 @@ Zobacz także. [`{ifset block}` |template-inheritance#Checking-Block-Existence] Użyj warunku `{ifset $var}`, aby określić, czy zmienna (lub wiele zmiennych) istnieje i ma wartość non-*null*. Właściwie to jest to samo, co `if (isset($var))` w PHP. Jak każdy znacznik par, może być również napisany jako [n:atrybut |syntax#n-attributes], więc weźmy to jako przykład: ```latte - + ``` diff --git a/latte/pt/filters.texy b/latte/pt/filters.texy index 29bc3d8f7d..f0e37193ad 100644 --- a/latte/pt/filters.texy +++ b/latte/pt/filters.texy @@ -203,8 +203,8 @@ Impõe a higienização do URL. Verifica se a variável contém uma URL da web ( ```latte {var $link = 'javascript:window.close()'} -checked -unchecked +checked +unchecked ``` Impressões: @@ -235,7 +235,7 @@ Converte o conteúdo para o esquema URI de dados. Pode ser usado para inserir im Vamos ter uma imagem em uma variável `$img = Image::fromFile('obrazek.gif')`, então ```latte - + ``` Impressões, por exemplo: @@ -416,8 +416,8 @@ Se o link usa um esquema diferente, como `javascript:` ou `data:`, e você tem c ```latte {var $link = 'javascript:window.close()'} -checked -unchecked +checked +unchecked ``` Impressões: diff --git a/latte/pt/safety-first.texy b/latte/pt/safety-first.texy index e9b0a37e5c..572c4a3732 100644 --- a/latte/pt/safety-first.texy +++ b/latte/pt/safety-first.texy @@ -351,7 +351,7 @@ Latte verifica automaticamente se a variável utilizada nos atributos `src` ou ` ```latte {var $link = 'javascript:attack()'} -click here +click here ``` Escreve: diff --git a/latte/pt/syntax.texy b/latte/pt/syntax.texy index 47772ddec6..e9c51124b7 100644 --- a/latte/pt/syntax.texy +++ b/latte/pt/syntax.texy @@ -98,7 +98,7 @@ Impressões: Ou usando o prefixo `tag-`, a funcionalidade é aplicada apenas nas tags HTML: ```latte -

        Title

        +

        Title

        ``` Dependendo do valor da variável `$url`, isto será impresso: diff --git a/latte/pt/tags.texy b/latte/pt/tags.texy index 96620fc6f4..83bf532ed1 100644 --- a/latte/pt/tags.texy +++ b/latte/pt/tags.texy @@ -292,7 +292,7 @@ Veja também [`{ifset block}` |template-inheritance#checking-block-existence] Use a condição `{ifset $var}` para determinar se uma variável (ou múltiplas variáveis) existe e tem um valor não-nulo. Na verdade é o mesmo que `if (isset($var))` em PHP. Como qualquer tag de par, isto pode ser escrito na forma de [n:atributo |syntax#n:attributes], então vamos mostrá-lo no exemplo: ```latte - + ``` diff --git a/latte/ro/filters.texy b/latte/ro/filters.texy index 3570525f3c..6a247bf6ab 100644 --- a/latte/ro/filters.texy +++ b/latte/ro/filters.texy @@ -203,8 +203,8 @@ Aplică igienizarea URL-urilor. Verifică dacă variabila conține un URL web (a ```latte {var $link = 'javascript:window.close()'} -checked -unchecked +checked +unchecked ``` Imprimă: @@ -235,7 +235,7 @@ Convertește conținutul în schema URI de date. Poate fi utilizat pentru a inse Să avem o imagine într-o variabilă `$img = Image::fromFile('obrazek.gif')`, atunci ```latte - + ``` Se imprimă de exemplu: @@ -416,8 +416,8 @@ Dacă link-ul utilizează o schemă diferită, cum ar fi `javascript:` sau `data ```latte {var $link = 'javascript:window.close()'} -checked -unchecked +checked +unchecked ``` Tipărituri: diff --git a/latte/ro/safety-first.texy b/latte/ro/safety-first.texy index fa2cb883f5..8025c926d4 100644 --- a/latte/ro/safety-first.texy +++ b/latte/ro/safety-first.texy @@ -351,7 +351,7 @@ Latte verifică automat dacă variabila utilizată în atributele `src` sau `hre ```latte {var $link = 'javascript:attack()'} -click here +click here ``` Scrie: diff --git a/latte/ro/syntax.texy b/latte/ro/syntax.texy index baefef14b5..003b2d7016 100644 --- a/latte/ro/syntax.texy +++ b/latte/ro/syntax.texy @@ -98,7 +98,7 @@ Imprimă: Sau prin utilizarea prefixului `tag-`, funcționalitatea se aplică numai la etichetele HTML: ```latte -

        Title

        +

        Title

        ``` În funcție de valoarea variabilei `$url`, se va imprima: diff --git a/latte/ro/tags.texy b/latte/ro/tags.texy index 0e59e6a9ad..141b10f975 100644 --- a/latte/ro/tags.texy +++ b/latte/ro/tags.texy @@ -292,7 +292,7 @@ A se vedea și [`{ifset block}` |template-inheritance#checking-block-existence] Utilizați condiția `{ifset $var}` pentru a determina dacă o variabilă (sau mai multe variabile) există și dacă are o valoare diferită de cea nulă. De fapt, este același lucru cu `if (isset($var))` în PHP. La fel ca orice tag pair, aceasta poate fi scrisă sub forma [n:attribute |syntax#n:attributes], așa că haideți să o arătăm în exemplu: ```latte - + ``` diff --git a/latte/ru/filters.texy b/latte/ru/filters.texy index 404481160b..13db5a8302 100644 --- a/latte/ru/filters.texy +++ b/latte/ru/filters.texy @@ -203,8 +203,8 @@ checkUrl .[filter] ```latte {var $link = 'javascript:window.close()'} -checked -unchecked +checked +unchecked ``` Печатает: @@ -235,7 +235,7 @@ dataStream(string mimetype = detect) .[filter] Пусть у вас есть изображение в переменной `$img = Image::fromFile('obrazek.gif')`, тогда ```latte - + ``` Печатает, например: @@ -416,8 +416,8 @@ nocheck .[filter] ```latte {var $link = 'javascript:window.close()'} -checked -unchecked +checked +unchecked ``` Печатные издания: diff --git a/latte/ru/safety-first.texy b/latte/ru/safety-first.texy index b2da171ab4..35b52cdb20 100644 --- a/latte/ru/safety-first.texy +++ b/latte/ru/safety-first.texy @@ -351,7 +351,7 @@ Latte автоматически проверяет, содержит ли пе ```latte {var $link = 'javascript:attack()'} -click here +click here ``` Пишет: diff --git a/latte/ru/syntax.texy b/latte/ru/syntax.texy index 8f30d3b53a..a0408ab285 100644 --- a/latte/ru/syntax.texy +++ b/latte/ru/syntax.texy @@ -98,7 +98,7 @@ Prints: Или с помощью префикса `tag-` функциональность применяется только к HTML-тегам: ```latte -

        Title

        +

        Title

        ``` В зависимости от значения переменной `$url` будет выведено следующее: diff --git a/latte/ru/tags.texy b/latte/ru/tags.texy index 620280e2d7..9ba8f55fc7 100644 --- a/latte/ru/tags.texy +++ b/latte/ru/tags.texy @@ -292,7 +292,7 @@ Age: {date('Y') - $birth}
        Используйте условие `{ifset $var}`, чтобы определить, существует ли переменная (или несколько переменных) и имеет ли она ненулевое значение. На самом деле это то же самое, что и `if (isset($var))` в PHP. Как и любой парный тег, этот может быть записан в виде [n:attribute |syntax#n-attributes], поэтому покажем его на примере: ```latte - + ``` diff --git a/latte/sl/filters.texy b/latte/sl/filters.texy index f031d784fb..a9734fca0f 100644 --- a/latte/sl/filters.texy +++ b/latte/sl/filters.texy @@ -203,8 +203,8 @@ Uveljavlja čiščenje URL-jev. Preveri, ali spremenljivka vsebuje spletni naslo ```latte {var $link = 'javascript:window.close()'} -checked -unchecked +checked +unchecked ``` Izpisuje: @@ -235,7 +235,7 @@ Pretvori vsebino v podatkovno shemo URI. Uporablja se lahko za vstavljanje slik Imejmo sliko v spremenljivki `$img = Image::fromFile('obrazek.gif')`, potem ```latte - + ``` natisne na primer: @@ -416,8 +416,8 @@ Preprečuje samodejno prečiščevanje URL. Latte [samodejno preveri, |safety-fi ```latte {var $link = 'javascript:window.close()'} -checked -unchecked +checked +unchecked ``` Izpisi: diff --git a/latte/sl/safety-first.texy b/latte/sl/safety-first.texy index 47770a5dac..e6fd55b0db 100644 --- a/latte/sl/safety-first.texy +++ b/latte/sl/safety-first.texy @@ -351,7 +351,7 @@ Latte samodejno preveri, ali spremenljivka, uporabljena v atributih `src` ali `h ```latte {var $link = 'javascript:attack()'} -click here +click here ``` Napiše: diff --git a/latte/sl/syntax.texy b/latte/sl/syntax.texy index 0896381aa7..c53cb2e597 100644 --- a/latte/sl/syntax.texy +++ b/latte/sl/syntax.texy @@ -98,7 +98,7 @@ Izpisi: S predpono `tag-` se funkcionalnost uporablja samo za oznake HTML: ```latte -

        Title

        +

        Title

        ``` Glede na vrednost spremenljivke `$url` se izpiše: diff --git a/latte/sl/tags.texy b/latte/sl/tags.texy index 7203fb69fd..5b497fe2de 100644 --- a/latte/sl/tags.texy +++ b/latte/sl/tags.texy @@ -292,7 +292,7 @@ Glej tudi [`{ifset block}` |template-inheritance#checking-block-existence] Pogoj `{ifset $var}` uporabite za ugotavljanje, ali spremenljivka (ali več spremenljivk) obstaja in ima vrednost, ki ni ničelna. To je pravzaprav enako kot `if (isset($var))` v PHP. Kot vsako parno oznako lahko tudi to zapišemo v obliki [n:atribut |syntax#n:attributes], zato jo prikažimo na primeru: ```latte - + ``` diff --git a/latte/tr/filters.texy b/latte/tr/filters.texy index c5715649be..0d4600fbba 100644 --- a/latte/tr/filters.texy +++ b/latte/tr/filters.texy @@ -203,8 +203,8 @@ URL sanitizasyonunu zorlar. Değişkenin bir web URL'si (yani HTTP/HTTPS protoko ```latte {var $link = 'javascript:window.close()'} -checked -unchecked +checked +unchecked ``` Baskılar: @@ -235,7 +235,7 @@ dataStream(string mimetype = detect) .[filter] `$img = Image::fromFile('obrazek.gif')` değişkeninde bir görüntüye sahip olalım, sonra ```latte - + ``` Örneğin baskılar: @@ -416,8 +416,8 @@ Bağlantı `javascript:` veya `data:` gibi farklı bir şema kullanıyorsa ve i ```latte {var $link = 'javascript:window.close()'} -checked -unchecked +checked +unchecked ``` Baskılar: diff --git a/latte/tr/safety-first.texy b/latte/tr/safety-first.texy index bc798290c4..767b38c305 100644 --- a/latte/tr/safety-first.texy +++ b/latte/tr/safety-first.texy @@ -351,7 +351,7 @@ Latte, `src` veya `href` niteliklerinde kullanılan değişkenin bir web URL'si ```latte {var $link = 'javascript:attack()'} -click here +click here ``` Yazıyor: diff --git a/latte/tr/syntax.texy b/latte/tr/syntax.texy index 6e2b0e4925..805f3bc168 100644 --- a/latte/tr/syntax.texy +++ b/latte/tr/syntax.texy @@ -98,7 +98,7 @@ Baskılar: Veya `tag-` önekini kullanarak işlevsellik yalnızca HTML etiketlerine uygulanır: ```latte -

        Title

        +

        Title

        ``` `$url` değişkeninin değerine bağlı olarak bu yazdırılacaktır: diff --git a/latte/tr/tags.texy b/latte/tr/tags.texy index f0f09fb3e3..e4c5096392 100644 --- a/latte/tr/tags.texy +++ b/latte/tr/tags.texy @@ -292,7 +292,7 @@ Ayrıca bakınız [`{ifset block}` |template-inheritance#checking-block-existenc Bir değişkenin (veya birden fazla değişkenin) var olup olmadığını ve boş olmayan bir değere sahip olup olmadığını belirlemek için `{ifset $var}` koşulunu kullanın. Aslında PHP'deki `if (isset($var))` ile aynıdır. Herhangi bir çift etiketi gibi, bu da [n:attribute |syntax#n:attributes] şeklinde yazılabilir, bu yüzden örnek olarak gösterelim: ```latte - + ``` diff --git a/latte/uk/filters.texy b/latte/uk/filters.texy index b3fe48bcc2..21b3d55fb6 100644 --- a/latte/uk/filters.texy +++ b/latte/uk/filters.texy @@ -203,8 +203,8 @@ checkUrl .[filter] ```latte {var $link = 'javascript:window.close()'} -checked -unchecked +checked +unchecked ``` Виводить на друк: @@ -235,7 +235,7 @@ dataStream(string mimetype = detect) .[filter] Нехай у змінній є зображення `$img = Image::fromFile('obrazek.gif')`, тоді ```latte - + ``` Виводить, наприклад: @@ -416,8 +416,8 @@ nocheck .[filter] ```latte {var $link = 'javascript:window.close()'} -checked -unchecked +checked +unchecked ``` Відбитки: diff --git a/latte/uk/safety-first.texy b/latte/uk/safety-first.texy index 46ffe3c360..567c5010b6 100644 --- a/latte/uk/safety-first.texy +++ b/latte/uk/safety-first.texy @@ -351,7 +351,7 @@ Latte автоматично перевіряє, чи містить змінн ```latte {var $link = 'javascript:attack()'} -click here +click here ``` Пише: diff --git a/latte/uk/syntax.texy b/latte/uk/syntax.texy index b1636f38ba..6cfd21070d 100644 --- a/latte/uk/syntax.texy +++ b/latte/uk/syntax.texy @@ -98,7 +98,7 @@ Prints: Або за допомогою префікса `tag-` функціональність застосовується тільки до HTML-тегів: ```latte -

        Title

        +

        Title

        ``` Залежно від значення змінної `$url` буде виведено таке: diff --git a/latte/uk/tags.texy b/latte/uk/tags.texy index 802bbbd888..5400052a93 100644 --- a/latte/uk/tags.texy +++ b/latte/uk/tags.texy @@ -292,7 +292,7 @@ Age: {date('Y') - $birth}
        Використовуйте умову `{ifset $var}`, щоб визначити, чи існує змінна (або кілька змінних) і чи має вона ненульове значення. Насправді це те саме, що й `if (isset($var))` у PHP. Як і будь-який парний тег, цей може бути записаний у вигляді [n:attribute |syntax#n-attributes], тому покажемо його на прикладі: ```latte - + ``` From c6737e3e57189c15787104756426fe86ec3e6a3f Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 15 Apr 2024 19:30:39 +0200 Subject: [PATCH 071/137] typo --- application/bg/components.texy | 2 +- application/cs/components.texy | 2 +- application/de/components.texy | 2 +- application/el/components.texy | 2 +- application/en/components.texy | 2 +- application/es/components.texy | 2 +- application/fr/components.texy | 2 +- application/hu/components.texy | 2 +- application/it/components.texy | 2 +- application/pl/components.texy | 2 +- application/pt/components.texy | 2 +- application/ro/components.texy | 2 +- application/ru/components.texy | 2 +- application/sl/components.texy | 2 +- application/tr/components.texy | 2 +- application/uk/components.texy | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/application/bg/components.texy b/application/bg/components.texy index 0a8293d052..e5ccab94e7 100644 --- a/application/bg/components.texy +++ b/application/bg/components.texy @@ -347,7 +347,7 @@ services: Накрая ще използваме тази фабрика в нашия презентатор: ```php -class PollPresenter extends Nette\UI\Application\Presenter +class PollPresenter extends Nette\Application\UI\Presenter { public function __construct( private PollControlFactory $pollControlFactory, diff --git a/application/cs/components.texy b/application/cs/components.texy index 649c1a6b0d..d60ee2b7fd 100644 --- a/application/cs/components.texy +++ b/application/cs/components.texy @@ -347,7 +347,7 @@ services: a nakonec ji použijeme v našem presenteru: ```php -class PollPresenter extends Nette\UI\Application\Presenter +class PollPresenter extends Nette\Application\UI\Presenter { public function __construct( private PollControlFactory $pollControlFactory, diff --git a/application/de/components.texy b/application/de/components.texy index e5371761ea..a335f73618 100644 --- a/application/de/components.texy +++ b/application/de/components.texy @@ -347,7 +347,7 @@ services: Schließlich werden wir diese Fabrik in unserem Präsentator verwenden: ```php -class PollPresenter extends Nette\UI\Application\Presenter +class PollPresenter extends Nette\Application\UI\Presenter { public function __construct( private PollControlFactory $pollControlFactory, diff --git a/application/el/components.texy b/application/el/components.texy index 8df1c185b6..ed46dc4e74 100644 --- a/application/el/components.texy +++ b/application/el/components.texy @@ -347,7 +347,7 @@ services: Τέλος, θα χρησιμοποιήσουμε αυτό το εργοστάσιο στον παρουσιαστή μας: ```php -class PollPresenter extends Nette\UI\Application\Presenter +class PollPresenter extends Nette\Application\UI\Presenter { public function __construct( private PollControlFactory $pollControlFactory, diff --git a/application/en/components.texy b/application/en/components.texy index eb131f7990..42b40aaacb 100644 --- a/application/en/components.texy +++ b/application/en/components.texy @@ -347,7 +347,7 @@ services: Finally, we will use this factory in our presenter: ```php -class PollPresenter extends Nette\UI\Application\Presenter +class PollPresenter extends Nette\Application\UI\Presenter { public function __construct( private PollControlFactory $pollControlFactory, diff --git a/application/es/components.texy b/application/es/components.texy index 837084cc94..0482a246a3 100644 --- a/application/es/components.texy +++ b/application/es/components.texy @@ -347,7 +347,7 @@ services: Por último, vamos a utilizar esta fábrica en nuestro presentador: ```php -class PollPresenter extends Nette\UI\Application\Presenter +class PollPresenter extends Nette\Application\UI\Presenter { public function __construct( private PollControlFactory $pollControlFactory, diff --git a/application/fr/components.texy b/application/fr/components.texy index b35c16a737..0b261bac97 100644 --- a/application/fr/components.texy +++ b/application/fr/components.texy @@ -347,7 +347,7 @@ services: Enfin, nous allons utiliser cette fabrique dans notre présentateur : ```php -class PollPresenter extends Nette\UI\Application\Presenter +class PollPresenter extends Nette\Application\UI\Presenter { public function __construct( private PollControlFactory $pollControlFactory, diff --git a/application/hu/components.texy b/application/hu/components.texy index d418cd212a..96d0ee1e96 100644 --- a/application/hu/components.texy +++ b/application/hu/components.texy @@ -347,7 +347,7 @@ services: Végül ezt a gyárat fogjuk használni a prezenterünkben: ```php -class PollPresenter extends Nette\UI\Application\Presenter +class PollPresenter extends Nette\Application\UI\Presenter { public function __construct( private PollControlFactory $pollControlFactory, diff --git a/application/it/components.texy b/application/it/components.texy index 5bd93e7940..c623b0b7cd 100644 --- a/application/it/components.texy +++ b/application/it/components.texy @@ -347,7 +347,7 @@ services: Infine, utilizzeremo questo factory nel nostro presenter: ```php -class PollPresenter extends Nette\UI\Application\Presenter +class PollPresenter extends Nette\Application\UI\Presenter { public function __construct( private PollControlFactory $pollControlFactory, diff --git a/application/pl/components.texy b/application/pl/components.texy index 1ae99ccb3e..740e5f919e 100644 --- a/application/pl/components.texy +++ b/application/pl/components.texy @@ -347,7 +347,7 @@ services: i w końcu użyć go w naszym prezenterze: ```php -class PollPresenter extends Nette\UI\Application\Presenter +class PollPresenter extends Nette\Application\UI\Presenter { public function __construct( private PollControlFactory $pollControlFactory, diff --git a/application/pt/components.texy b/application/pt/components.texy index 33a0a01398..9cfe7557f5 100644 --- a/application/pt/components.texy +++ b/application/pt/components.texy @@ -347,7 +347,7 @@ services: Finalmente, utilizaremos esta fábrica em nosso apresentador: ```php -class PollPresenter extends Nette\UI\Application\Presenter +class PollPresenter extends Nette\Application\UI\Presenter { public function __construct( private PollControlFactory $pollControlFactory, diff --git a/application/ro/components.texy b/application/ro/components.texy index 90d2c70502..d988ba261f 100644 --- a/application/ro/components.texy +++ b/application/ro/components.texy @@ -347,7 +347,7 @@ services: În cele din urmă, vom utiliza această fabrică în prezentatorul nostru: ```php -class PollPresenter extends Nette\UI\Application\Presenter +class PollPresenter extends Nette\Application\UI\Presenter { public function __construct( private PollControlFactory $pollControlFactory, diff --git a/application/ru/components.texy b/application/ru/components.texy index 7d3e1e2133..9c9fa01111 100644 --- a/application/ru/components.texy +++ b/application/ru/components.texy @@ -347,7 +347,7 @@ services: Наконец, мы будем использовать эту фабрику в нашем презентере: ```php -class PollPresenter extends Nette\UI\Application\Presenter +class PollPresenter extends Nette\Application\UI\Presenter { public function __construct( private PollControlFactory $pollControlFactory, diff --git a/application/sl/components.texy b/application/sl/components.texy index 6b1ee7044b..dd8ce1e37d 100644 --- a/application/sl/components.texy +++ b/application/sl/components.texy @@ -347,7 +347,7 @@ services: Na koncu bomo to tovarno uporabili v našem predstavitvenem programu: ```php -class PollPresenter extends Nette\UI\Application\Presenter +class PollPresenter extends Nette\Application\UI\Presenter { public function __construct( private PollControlFactory $pollControlFactory, diff --git a/application/tr/components.texy b/application/tr/components.texy index e2c61f23ec..5e1c447262 100644 --- a/application/tr/components.texy +++ b/application/tr/components.texy @@ -347,7 +347,7 @@ services: Son olarak, bu fabrikayı sunucumuzda kullanacağız: ```php -class PollPresenter extends Nette\UI\Application\Presenter +class PollPresenter extends Nette\Application\UI\Presenter { public function __construct( private PollControlFactory $pollControlFactory, diff --git a/application/uk/components.texy b/application/uk/components.texy index 9b1e067d5d..37b1d65983 100644 --- a/application/uk/components.texy +++ b/application/uk/components.texy @@ -347,7 +347,7 @@ services: Нарешті, ми будемо використовувати цю фабрику в нашому презентері: ```php -class PollPresenter extends Nette\UI\Application\Presenter +class PollPresenter extends Nette\Application\UI\Presenter { public function __construct( private PollControlFactory $pollControlFactory, From 67d0eab911e936c5f71c83cfdd5e27053f5016a1 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 18 Apr 2024 22:28:06 +0200 Subject: [PATCH 072/137] nette/application 3.2.3 --- application/bg/configuration.texy | 5 +++ application/bg/creating-links.texy | 24 ++++++++++++ application/bg/presenters.texy | 54 +++++++++++++++++++++++++- application/cs/configuration.texy | 5 +++ application/cs/creating-links.texy | 24 ++++++++++++ application/cs/presenters.texy | 54 +++++++++++++++++++++++++- application/de/configuration.texy | 5 +++ application/de/creating-links.texy | 24 ++++++++++++ application/de/presenters.texy | 54 +++++++++++++++++++++++++- application/el/configuration.texy | 5 +++ application/el/creating-links.texy | 24 ++++++++++++ application/el/presenters.texy | 54 +++++++++++++++++++++++++- application/en/configuration.texy | 5 +++ application/en/creating-links.texy | 24 ++++++++++++ application/en/presenters.texy | 54 +++++++++++++++++++++++++- application/es/configuration.texy | 5 +++ application/es/creating-links.texy | 24 ++++++++++++ application/es/presenters.texy | 54 +++++++++++++++++++++++++- application/fr/configuration.texy | 5 +++ application/fr/creating-links.texy | 24 ++++++++++++ application/fr/presenters.texy | 54 +++++++++++++++++++++++++- application/hu/configuration.texy | 5 +++ application/hu/creating-links.texy | 24 ++++++++++++ application/hu/presenters.texy | 54 +++++++++++++++++++++++++- application/it/configuration.texy | 5 +++ application/it/creating-links.texy | 24 ++++++++++++ application/it/presenters.texy | 54 +++++++++++++++++++++++++- application/pl/configuration.texy | 5 +++ application/pl/creating-links.texy | 24 ++++++++++++ application/pl/presenters.texy | 54 +++++++++++++++++++++++++- application/pt/configuration.texy | 5 +++ application/pt/creating-links.texy | 24 ++++++++++++ application/pt/presenters.texy | 54 +++++++++++++++++++++++++- application/ro/configuration.texy | 5 +++ application/ro/creating-links.texy | 24 ++++++++++++ application/ro/presenters.texy | 54 +++++++++++++++++++++++++- application/ru/configuration.texy | 5 +++ application/ru/creating-links.texy | 24 ++++++++++++ application/ru/presenters.texy | 54 +++++++++++++++++++++++++- application/sl/configuration.texy | 5 +++ application/sl/creating-links.texy | 24 ++++++++++++ application/sl/presenters.texy | 54 +++++++++++++++++++++++++- application/tr/configuration.texy | 5 +++ application/tr/creating-links.texy | 24 ++++++++++++ application/tr/presenters.texy | 54 +++++++++++++++++++++++++- application/uk/configuration.texy | 5 +++ application/uk/creating-links.texy | 24 ++++++++++++ application/uk/presenters.texy | 54 +++++++++++++++++++++++++- nette/cs/vulnerability-protection.texy | 6 +-- nette/en/vulnerability-protection.texy | 6 +-- 50 files changed, 1302 insertions(+), 38 deletions(-) diff --git a/application/bg/configuration.texy b/application/bg/configuration.texy index 584883c9e9..30bc0d30c0 100644 --- a/application/bg/configuration.texy +++ b/application/bg/configuration.texy @@ -20,6 +20,9 @@ application: # име на водещ на грешка errorPresenter: Error # (string|array) по подразбиране е 'Nette:Error' + # дефинира псевдоними за водещи и събития + aliases: ... + # дефинира правила за съпоставяне на името на водещия с клас mapping: ... @@ -39,6 +42,8 @@ application: Опцията `silentLinks` определя как Nette да се държи в режим на разработчик, когато генерирането на връзки е неуспешно (например поради липса на презентатор и т.н.). Стойността по подразбиране `false` означава, че Nette работи `E_USER_WARNING`. Задаването на `true` потиска това съобщение за грешка. В производствена среда винаги се извиква `E_USER_WARNING`. Можем също така да повлияем на това поведение, като зададем променливата на водещия [$invalidLinkMode |creating-links#Invalid-Links]. +[Псевдонимите опростяват препратките към |creating-links#aliases] често използвани презентатори. + Съпоставянето [определя правилата, по които |modules#Mapping] името на класа се извежда от основното име. diff --git a/application/bg/creating-links.texy b/application/bg/creating-links.texy index e75c39e78b..ebdffa92c5 100644 --- a/application/bg/creating-links.texy +++ b/application/bg/creating-links.texy @@ -223,6 +223,30 @@ $this->getPresenter()->link('Home:default') ``` +Псевдоними .[#toc-aliases]{data-version:v3.2.2} +=============================================== + +Понякога е полезно да зададете лесно запомнящ се псевдоним на двойка презентатор:действие. Например, можете да наречете началната страница `Front:Home:default` просто `home` или `Admin:Dashboard:default` - `admin`. + +Псевдонимите се дефинират в [конфигурацията |configuration] под ключа `application › aliases`: + +```neon +application: + aliases: + home: Front:Home:default + admin: Admin:Dashboard:default + sign: Front:Sign:in +``` + +Във връзките те се записват с помощта на символа at, например: + +```latte +administration +``` + +Те се поддържат във всички методи, които работят с връзки, като например `redirect()` и други подобни. + + Невалидни връзки .[#toc-invalid-links] ====================================== diff --git a/application/bg/presenters.texy b/application/bg/presenters.texy index 76b510873b..efcce1d904 100644 --- a/application/bg/presenters.texy +++ b/application/bg/presenters.texy @@ -447,12 +447,62 @@ $this->sendResponse(new Responses\CallbackResponse($callback)); ``` +Ограничаване на достъпа с помощта на `#[Requires]` .[#toc-access-restriction-using-requires]{data-version:3.2.2} +---------------------------------------------------------------------------------------------------------------- + +В `#[Requires]` предоставя разширени опции за ограничаване на достъпа до презентаторите и техните методи. Той може да се използва за определяне на HTTP методи, изискване на AJAX заявки, ограничаване на достъпа до същия произход и ограничаване на достъпа само до препращане. Атрибутът може да се прилага към класове на презентатори, както и към отделни методи, като например `action()`, `render()`, `handle()`, и `createComponent()`. + +Ето един пример за използването му за ограничаване на достъпа само до метода HTTP `POST`: + +```php +use Nette\Application\Attributes\Requires; + +#[Requires(methods: 'POST')] +class MyPresenter extends Nette\Application\UI\Presenter +{ +} +``` + +Можете да зададете тези ограничения: +- на HTTP методите: `#[Requires(methods: ['GET', 'POST'])]` +- изискващи AJAX заявка: `#[Requires(ajax: true)]` +- достъп само от един и същ произход: `#[Requires(sameOrigin: true)]` +- достъп само чрез препращане: `#[Requires(forward: true)]` +- ограничения за конкретни действия: `#[Requires(actions: 'default')]` + +Условията могат да се комбинират чрез изброяване на няколко атрибута или чрез обединяването им в един: + +```php +#[Requires(methods: 'POST', ajax: true)] +public function actionDelete(int $id) +{ +} + +// or + +#[Requires(methods: 'POST')] +#[Requires(ajax: true)] +public function actionDelete(int $id) +{ +} +``` + + Проверка на метода HTTP .[#toc-http-method-check] ------------------------------------------------- -Презентаторите в Nette автоматично проверяват HTTP метода на всяка входяща заявка. Основната причина за тази проверка е сигурността. Проверката на метода се извършва в `checkHttpMethod()`, който определя дали методът, посочен в заявката, е включен в масива `$presenter->allowedMethods`. По подразбиране този масив съдържа елементите `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`, което означава, че тези методи са разрешени. +В Nette презентаторите автоматично проверяват HTTP метода на всяка входяща заявка главно от съображения за сигурност. По подразбиране са разрешени методите `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`. + +Ако искате да разрешите допълнителни методи, като например `OPTIONS`, можете да използвате `#[Requires]` атрибут (от Nette Application v3.2): + +```php +#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])] +class MyPresenter extends Nette\Application\UI\Presenter +{ +} +``` -Ако желаете допълнително да разрешите метода `OPTIONS`, това може да се постигне по следния начин: +Във версия 3.1 проверката се извършва в `checkHttpMethod()`, който проверява дали методът, посочен в заявката, е включен в масива `$presenter->allowedMethods`. Добавете метод по следния начин: ```php class MyPresenter extends Nette\Application\UI\Presenter diff --git a/application/cs/configuration.texy b/application/cs/configuration.texy index 3aaade80d5..acab7d7adf 100644 --- a/application/cs/configuration.texy +++ b/application/cs/configuration.texy @@ -20,6 +20,9 @@ application: # název error-presenteru errorPresenter: Error # (string|array) výchozí je 'Nette:Error' + # definuje aliasy pro presentery a akce + aliases: ... + # definuje pravidla pro překlad názvu presenteru na třídu mapping: ... @@ -39,6 +42,8 @@ application: Volba `silentLinks` určuje, jak se Nette zachová ve vývojářském režimu, když selže generování odkazu (třeba proto, že neexistuje presenter, atd). Výchozí hodnota `false` znamená, že Nette vyhodí `E_USER_WARNING` chybu. Nastavením na `true` dojde k potlačení této chybové hlášky. V produkčním prostředí se `E_USER_WARNING` vyvolá vždy. Toto chování můžeme také ovlivnit nastavením proměnné presenteru [$invalidLinkMode|creating-links#neplatne-odkazy]. +[Aliasy zjednodušují odkazování |creating-links#aliasy] na často používané presentery. + [Mapování definuje pravidla |modules#mapování], podle kterých se z názvu presenteru odvodí název třídy. diff --git a/application/cs/creating-links.texy b/application/cs/creating-links.texy index 2d497b68f2..25a1f8d240 100644 --- a/application/cs/creating-links.texy +++ b/application/cs/creating-links.texy @@ -223,6 +223,30 @@ $this->getPresenter()->link('Home:default') ``` +Aliasy .{data-version:v3.2.2} +============================= + +Občas se může hodit přiřadit dvojici Presenter:akce snadno zapamatovatelný alias. Například úvodní stránku `Front:Home:default` pojmenovat jednoduše jako `home` nebo `Admin:Dashboard:default` jako `admin`. + +Aliasy se definují v [konfiguraci|configuration] pod klíčem `application › aliases`: + +```neon +application: + aliases: + home: Front:Home:default + admin: Admin:Dashboard:default + sign: Front:Sign:in +``` + +V odkazech se pak zapisují pomocí zavináče, například: + +```latte +administrace +``` + +Podporované jsou i ve všech metodách pracujících s odkazy, jako je `redirect()` a podobně. + + Neplatné odkazy =============== diff --git a/application/cs/presenters.texy b/application/cs/presenters.texy index 14dad81a49..4936a85634 100644 --- a/application/cs/presenters.texy +++ b/application/cs/presenters.texy @@ -447,12 +447,62 @@ $this->sendResponse(new Responses\CallbackResponse($callback)); ``` +Omezení přístupu pomocí `#[Requires]` .{data-version:3.2.2} +----------------------------------------------------------- + +Atribut `#[Requires]` poskytuje pokročilé možnosti pro omezení přístupu k presenterům a jejich metodám. Lze jej použít pro specifikaci HTTP metod, vyžadování AJAXového požadavku, omezení na stejný původ (same origin), a přístup pouze přes forwardování. Atribut lze aplikovat jak na třídy presenterů, tak na jednotlivé metody `action()`, `render()`, `handle()` a `createComponent()`. + +Příklad použití pro omezení přístupu pouze HTTP metodou `POST`: + +```php +use Nette\Application\Attributes\Requires; + +#[Requires(methods: 'POST')] +class MyPresenter extends Nette\Application\UI\Presenter +{ +} +``` + +Můžete určit tyto omezení: +- na HTTP metody: `#[Requires(methods: ['GET', 'POST'])]` +- vyžadování AJAXového požadavku: `#[Requires(ajax: true)]` +- přístup pouze ze stejného původu: `#[Requires(sameOrigin: true)]` +- přístup pouze přes forward: `#[Requires(forward: true)]` +- omezení na konkrétní akce: `#[Requires(actions: 'default')]` + +Kombinovat podmínky lze uvedením více atributů nebo spojením do jednoho: + +```php +#[Requires(methods: 'POST', ajax: true)] +public function actionDelete(int $id) +{ +} + +// nebo + +#[Requires(methods: 'POST')] +#[Requires(ajax: true)] +public function actionDelete(int $id) +{ +} +``` + + Kontrola HTTP metody -------------------- -Presentery v Nette automaticky ověřují HTTP metodu každého příchozího požadavku. Důvodem pro tuto kontrolu je především bezpečnost. Ověření metody se provádí v `checkHttpMethod()`, která zjišťuje, zda je metoda specifikovaná v požadavku obsažena v poli `$presenter->allowedMethods`. To standardně obsahuje položky `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`, tedy tyto metody jsou povoleny. +Presentery v Nette automaticky ověřují HTTP metodu každého příchozího požadavku. Důvodem pro tuto kontrolu je především bezpečnost. Standardně jsou povoleny metody `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`. + +Chcete-li povolit navíc například metodu `OPTIONS`, použijte k tomu atribut `#[Requires]` (od Nette Application v3.2): + +```php +#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])] +class MyPresenter extends Nette\Application\UI\Presenter +{ +} +``` -Chcete-li povolit navíc metodu `OPTIONS`, je možné toho dosáhnout následujícím způsobem: +Ve verzi 3.1 se ověření provádí v `checkHttpMethod()`, která zjišťuje, zda je metoda specifikovaná v požadavku obsažena v poli `$presenter->allowedMethods`. Přidání metody udělejte takto: ```php class MyPresenter extends Nette\Application\UI\Presenter diff --git a/application/de/configuration.texy b/application/de/configuration.texy index 17fb1ccc00..d5b665b684 100644 --- a/application/de/configuration.texy +++ b/application/de/configuration.texy @@ -20,6 +20,9 @@ Anwendung: # Name des Fehlermelders errorPresenter: Error # (string|array) Standardwert ist 'Nette:Error' + # definiert Aliase für Moderatoren und Veranstaltungen + aliases: ... + # definiert die Regeln für die Auflösung des Presenter-Namens in eine Klasse mapping: ... @@ -39,6 +42,8 @@ application: Die Option `silentLinks` legt fest, wie sich Nette im Entwicklermodus verhält, wenn die Link-Generierung fehlschlägt (z. B. weil kein Presenter vorhanden ist usw.). Der Standardwert `false` bedeutet, dass Nette `E_USER_WARNING` auslöst. Die Einstellung `true` unterdrückt diese Fehlermeldung. In einer Produktionsumgebung wird immer `E_USER_WARNING` aufgerufen. Wir können dieses Verhalten auch beeinflussen, indem wir die Presenter-Variable [$invalidLinkMode |creating-links#Invalid Links] setzen. +[Aliasnamen vereinfachen das Aufsuchen |creating-links#aliases] häufig verwendeter Moderatoren. + Das [Mapping definiert die Regeln |modules#mapping], nach denen der Klassenname aus dem Presenter-Namen abgeleitet wird. diff --git a/application/de/creating-links.texy b/application/de/creating-links.texy index 2543101182..2b5a91f73d 100644 --- a/application/de/creating-links.texy +++ b/application/de/creating-links.texy @@ -223,6 +223,30 @@ $this->getPresenter()->link('Home:default') ``` +Aliasnamen .[#toc-aliases]{data-version:v3.2.2} +=============================================== + +Manchmal ist es sinnvoll, einem Presenter:Action-Paar einen leicht zu merkenden Alias zuzuweisen. Zum Beispiel könnten Sie die Homepage `Front:Home:default` einfach als `home` oder `Admin:Dashboard:default` als `admin` benennen. + +Aliasnamen werden in der [Konfiguration |configuration] unter dem Schlüssel `application › aliases` definiert: + +```neon +application: + aliases: + home: Front:Home:default + admin: Admin:Dashboard:default + sign: Front:Sign:in +``` + +In Links werden sie mit dem at-Symbol geschrieben, zum Beispiel: + +```latte +administration +``` + +Sie werden in allen Methoden unterstützt, die mit Links arbeiten, wie `redirect()` und ähnliche. + + Ungültige Links .[#toc-invalid-links] ===================================== diff --git a/application/de/presenters.texy b/application/de/presenters.texy index b96fcc7772..2407021005 100644 --- a/application/de/presenters.texy +++ b/application/de/presenters.texy @@ -447,12 +447,62 @@ $this->sendResponse(new Responses\CallbackResponse($callback)); ``` +Zugangsbeschränkung mit `#[Requires]` .[#toc-access-restriction-using-requires]{data-version:3.2.2} +--------------------------------------------------------------------------------------------------- + +Das Attribut `#[Requires]` Attribut bietet erweiterte Optionen zur Einschränkung des Zugriffs auf Präsentatoren und ihre Methoden. Es kann verwendet werden, um HTTP-Methoden zu spezifizieren, AJAX-Anfragen zu verlangen, den Zugriff auf denselben Ursprung zu beschränken und den Zugriff nur auf Weiterleitungen zu beschränken. Das Attribut kann sowohl auf Presenter-Klassen als auch auf einzelne Methoden angewendet werden, z. B. `action()`, `render()`, `handle()`, und `createComponent()`. + +Hier ein Beispiel für die Beschränkung des Zugriffs nur auf die Methode HTTP `POST`: + +```php +use Nette\Application\Attributes\Requires; + +#[Requires(methods: 'POST')] +class MyPresenter extends Nette\Application\UI\Presenter +{ +} +``` + +Sie können diese Einschränkungen angeben: +- auf HTTP-Methoden: `#[Requires(methods: ['GET', 'POST'])]` +- die eine AJAX-Anfrage erfordern: `#[Requires(ajax: true)]` +- Zugriff nur vom selben Ursprung: `#[Requires(sameOrigin: true)]` +- Zugriff nur über Weiterleitung: `#[Requires(forward: true)]` +- Einschränkungen für bestimmte Aktionen: `#[Requires(actions: 'default')]` + +Bedingungen können kombiniert werden, indem mehrere Attribute aufgelistet oder zu einem einzigen zusammengefasst werden: + +```php +#[Requires(methods: 'POST', ajax: true)] +public function actionDelete(int $id) +{ +} + +// or + +#[Requires(methods: 'POST')] +#[Requires(ajax: true)] +public function actionDelete(int $id) +{ +} +``` + + HTTP-Methodenprüfung .[#toc-http-method-check] ---------------------------------------------- -Die Präsentatoren in Nette überprüfen automatisch die HTTP-Methode jeder eingehenden Anfrage. Der Hauptgrund für diese Überprüfung ist die Sicherheit. Die Methodenprüfung wird in `checkHttpMethod()` durchgeführt, das feststellt, ob die in der Anfrage angegebene Methode im Array `$presenter->allowedMethods` enthalten ist. Standardmäßig enthält dieses Array die Einträge `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`, was bedeutet, dass diese Methoden erlaubt sind. +In Nette überprüfen die Moderatoren die HTTP-Methode jeder eingehenden Anfrage automatisch, hauptsächlich aus Sicherheitsgründen. Standardmäßig sind die Methoden `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH` zugelassen. + +Wenn Sie zusätzliche Methoden wie `OPTIONS` aktivieren möchten, können Sie das `#[Requires]` Attribut verwenden (ab Nette Application v3.2): + +```php +#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])] +class MyPresenter extends Nette\Application\UI\Presenter +{ +} +``` -Wenn Sie zusätzlich die Methode `OPTIONS` zulassen möchten, können Sie dies auf folgende Weise erreichen: +In Version 3.1 wird die Überprüfung in `checkHttpMethod()` durchgeführt, das prüft, ob die in der Anfrage angegebene Methode im Array `$presenter->allowedMethods` enthalten ist. Fügen Sie eine Methode wie diese hinzu: ```php class MyPresenter extends Nette\Application\UI\Presenter diff --git a/application/el/configuration.texy b/application/el/configuration.texy index 8b29cf2cc6..99bea2563d 100644 --- a/application/el/configuration.texy +++ b/application/el/configuration.texy @@ -20,6 +20,9 @@ application: # όνομα του error-presenter errorPresenter: Error # (string|array) προεπιλογή 'Nette:Error' + # ορίζει ψευδώνυμα για παρουσιαστές και εκδηλώσεις + aliases: ... + # ορίζει τους κανόνες για την επίλυση του ονόματος του παρουσιαστή σε μια κλάση mapping: ... @@ -39,6 +42,8 @@ application: Η επιλογή `silentLinks` καθορίζει τον τρόπο με τον οποίο η Nette συμπεριφέρεται στη λειτουργία ανάπτυξης όταν η δημιουργία συνδέσμων αποτυγχάνει (για παράδειγμα, επειδή δεν υπάρχει παρουσιαστής κ.λπ.). Η προεπιλεγμένη τιμή `false` σημαίνει ότι η Nette ενεργοποιεί το `E_USER_WARNING`. Η ρύθμιση σε `true` καταστέλλει αυτό το μήνυμα σφάλματος. Σε περιβάλλον παραγωγής, το `E_USER_WARNING` ενεργοποιείται πάντα. Μπορούμε επίσης να επηρεάσουμε αυτή τη συμπεριφορά θέτοντας τη μεταβλητή του παρουσιαστή [$invalidLinkMode |creating-links#Invalid Links]. +Τα [ψευδώνυμα απλοποιούν την αναφορά σε |creating-links#aliases] συχνά χρησιμοποιούμενους παρουσιαστές. + Η [αντιστοίχιση ορίζει τους κανόνες |modules#mapping] με τους οποίους το όνομα της κλάσης προκύπτει από το όνομα του παρουσιαστή. diff --git a/application/el/creating-links.texy b/application/el/creating-links.texy index c77bb68c72..1914401594 100644 --- a/application/el/creating-links.texy +++ b/application/el/creating-links.texy @@ -223,6 +223,30 @@ $this->getPresenter()->link('Home:default') ``` +Ψευδώνυμα .[#toc-aliases]{data-version:v3.2.2} +============================================== + +Μερικές φορές είναι χρήσιμο να αντιστοιχίσετε ένα εύκολα απομνημονεύσιμο ψευδώνυμο σε ένα ζεύγος Παρουσιαστής:ενέργεια. Για παράδειγμα, θα μπορούσατε να ονομάσετε την αρχική σελίδα `Front:Home:default` απλά ως `home` ή `Admin:Dashboard:default` ως `admin`. + +Τα ψευδώνυμα ορίζονται στη [ρύθμιση παρα |configuration] μέτρων κάτω από το κλειδί `application › aliases`: + +```neon +application: + aliases: + home: Front:Home:default + admin: Admin:Dashboard:default + sign: Front:Sign:in +``` + +Στους συνδέσμους, γράφονται χρησιμοποιώντας το σύμβολο at, για παράδειγμα: + +```latte +administration +``` + +Υποστηρίζονται σε όλες τις μεθόδους που λειτουργούν με συνδέσμους, όπως το `redirect()` και παρόμοια. + + Άκυροι σύνδεσμοι .[#toc-invalid-links] ====================================== diff --git a/application/el/presenters.texy b/application/el/presenters.texy index 820803188d..3f55886ec4 100644 --- a/application/el/presenters.texy +++ b/application/el/presenters.texy @@ -447,12 +447,62 @@ $this->sendResponse(new Responses\CallbackResponse($callback)); ``` +Περιορισμός πρόσβασης με χρήση `#[Requires]` .[#toc-access-restriction-using-requires]{data-version:3.2.2} +---------------------------------------------------------------------------------------------------------- + +Το `#[Requires]` παρέχει προηγμένες επιλογές για τον περιορισμό της πρόσβασης στους παρουσιαστές και τις μεθόδους τους. Μπορεί να χρησιμοποιηθεί για τον προσδιορισμό μεθόδων HTTP, την απαίτηση αιτήσεων AJAX, τον περιορισμό της πρόσβασης στην ίδια προέλευση και τον περιορισμό της πρόσβασης μόνο στην προώθηση. Το χαρακτηριστικό μπορεί να εφαρμοστεί σε κλάσεις παρουσιαστών καθώς και σε μεμονωμένες μεθόδους όπως οι `action()`, `render()`, `handle()`, και `createComponent()`. + +Ακολουθεί ένα παράδειγμα χρήσης της για να περιορίσετε την πρόσβαση μόνο στη μέθοδο HTTP `POST`: + +```php +use Nette\Application\Attributes\Requires; + +#[Requires(methods: 'POST')] +class MyPresenter extends Nette\Application\UI\Presenter +{ +} +``` + +Μπορείτε να καθορίσετε αυτούς τους περιορισμούς: +- σε μεθόδους HTTP: `#[Requires(methods: ['GET', 'POST'])]` +- AJAX: `#[Requires(ajax: true)]` +- πρόσβαση μόνο από την ίδια προέλευση: `#[Requires(sameOrigin: true)]` +- πρόσβαση μόνο μέσω προώθησης: `#[Requires(forward: true)]` +- περιορισμοί σε συγκεκριμένες ενέργειες: `#[Requires(actions: 'default')]` + +Οι συνθήκες μπορούν να συνδυαστούν με την απαρίθμηση πολλαπλών χαρακτηριστικών ή με τη συνένωσή τους σε ένα: + +```php +#[Requires(methods: 'POST', ajax: true)] +public function actionDelete(int $id) +{ +} + +// or + +#[Requires(methods: 'POST')] +#[Requires(ajax: true)] +public function actionDelete(int $id) +{ +} +``` + + Έλεγχος μεθόδου HTTP .[#toc-http-method-check] ---------------------------------------------- -Οι παρουσιαστές στη Nette ελέγχουν αυτόματα τη μέθοδο HTTP κάθε εισερχόμενης αίτησης. Ο κύριος λόγος για αυτή την επαλήθευση είναι η ασφάλεια. Ο έλεγχος της μεθόδου πραγματοποιείται στο `checkHttpMethod()`, το οποίο καθορίζει αν η μέθοδος που καθορίζεται στην αίτηση περιλαμβάνεται στον πίνακα `$presenter->allowedMethods`. Από προεπιλογή, αυτός ο πίνακας περιέχει τα στοιχεία `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`, που σημαίνει ότι αυτές οι μέθοδοι επιτρέπονται. +Στη Nette, οι παρουσιαστές επαληθεύουν αυτόματα τη μέθοδο HTTP κάθε εισερχόμενης αίτησης κυρίως για λόγους ασφαλείας. Από προεπιλογή, επιτρέπονται οι μέθοδοι `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`. + +Εάν θέλετε να ενεργοποιήσετε επιπλέον μεθόδους, όπως η `OPTIONS`, μπορείτε να χρησιμοποιήσετε την εντολή `#[Requires]` (από την εφαρμογή Nette Application v3.2): + +```php +#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])] +class MyPresenter extends Nette\Application\UI\Presenter +{ +} +``` -Αν θέλετε να επιτρέψετε επιπλέον τη μέθοδο `OPTIONS`, αυτό μπορεί να επιτευχθεί με τον ακόλουθο τρόπο: +Στην έκδοση 3.1, η επαλήθευση πραγματοποιείται στο `checkHttpMethod()`, το οποίο ελέγχει αν η μέθοδος που καθορίζεται στην αίτηση περιλαμβάνεται στον πίνακα `$presenter->allowedMethods`. Προσθέστε μια μέθοδο ως εξής: ```php class MyPresenter extends Nette\Application\UI\Presenter diff --git a/application/en/configuration.texy b/application/en/configuration.texy index 89036a69a8..fba71aa4fd 100644 --- a/application/en/configuration.texy +++ b/application/en/configuration.texy @@ -20,6 +20,9 @@ application: # name of error-presenter errorPresenter: Error # (string|array) defaults to 'Nette:Error' + # defines aliases for presenters and events + aliases: ... + # defines the rules for resolving the presenter name to a class mapping: ... @@ -39,6 +42,8 @@ application: Option `silentLinks` determines how Nette behaves in developer mode when link generation fails (for example, because there is no presenter, etc). The default value `false` means that Nette triggers `E_USER_WARNING`. Setting to `true` suppresses this error message. In a production environment, `E_USER_WARNING` is always invoked. We can also influence this behavior by setting the presenter variable [$invalidLinkMode |creating-links#Invalid Links]. +[Aliases simplify referencing |creating-links#aliases] frequently used presenters. + The [mapping defines the rules |modules#mapping] by which the class name is derived from the presenter name. diff --git a/application/en/creating-links.texy b/application/en/creating-links.texy index d80f9ce29b..f92d2c5894 100644 --- a/application/en/creating-links.texy +++ b/application/en/creating-links.texy @@ -223,6 +223,30 @@ $this->getPresenter()->link('Home:default') ``` +Aliases .{data-version:v3.2.2} +============================== + +Sometimes it's useful to assign an easily memorable alias to a Presenter:action pair. For example, you could name the homepage `Front:Home:default` simply as `home` or `Admin:Dashboard:default` as `admin`. + +Aliases are defined in the [configuration|configuration] under the key `application › aliases`: + +```neon +application: + aliases: + home: Front:Home:default + admin: Admin:Dashboard:default + sign: Front:Sign:in +``` + +In links, they are written using the at symbol, for example: + +```latte +administration +``` + +They are supported in all methods that work with links, such as `redirect()` and similar. + + Invalid Links ============= diff --git a/application/en/presenters.texy b/application/en/presenters.texy index a7b72959fb..324d00441d 100644 --- a/application/en/presenters.texy +++ b/application/en/presenters.texy @@ -447,12 +447,62 @@ $this->sendResponse(new Responses\CallbackResponse($callback)); ``` +Access Restriction Using `#[Requires]` .{data-version:3.2.2} +------------------------------------------------------------ + +The `#[Requires]` attribute provides advanced options for restricting access to presenters and their methods. It can be used to specify HTTP methods, require AJAX requests, limit access to the same origin, and restrict access to forwarding only. The attribute can be applied to presenter classes as well as individual methods such as `action()`, `render()`, `handle()`, and `createComponent()`. + +Here’s an example of using it to restrict access to only the HTTP `POST` method: + +```php +use Nette\Application\Attributes\Requires; + +#[Requires(methods: 'POST')] +class MyPresenter extends Nette\Application\UI\Presenter +{ +} +``` + +You can specify these restrictions: +- on HTTP methods: `#[Requires(methods: ['GET', 'POST'])]` +- requiring an AJAX request: `#[Requires(ajax: true)]` +- access only from the same origin: `#[Requires(sameOrigin: true)]` +- access only via forwarding: `#[Requires(forward: true)]` +- restrictions on specific actions: `#[Requires(actions: 'default')]` + +Conditions can be combined by listing multiple attributes or by joining them into one: + +```php +#[Requires(methods: 'POST', ajax: true)] +public function actionDelete(int $id) +{ +} + +// or + +#[Requires(methods: 'POST')] +#[Requires(ajax: true)] +public function actionDelete(int $id) +{ +} +``` + + HTTP Method Check ----------------- -Presenters in Nette automatically verify the HTTP method of every incoming request. The primary reason for this verification is security. The method check is carried out in `checkHttpMethod()`, which determines if the method specified in the request is included in the `$presenter->allowedMethods` array. By default, this array contains the items `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`, meaning these methods are allowed. +In Nette, presenters automatically verify the HTTP method of each incoming request primarily for security reasons. By default, the methods `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH` are allowed. + +If you want to enable additional methods such as `OPTIONS`, you can use the `#[Requires]` attribute (from Nette Application v3.2): + +```php +#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])] +class MyPresenter extends Nette\Application\UI\Presenter +{ +} +``` -If you wish to additionally allow the `OPTIONS` method, it can be achieved in the following manner: +In version 3.1, the verification is performed in `checkHttpMethod()`, which checks if the method specified in the request is included in the array `$presenter->allowedMethods`. Add a method like this: ```php class MyPresenter extends Nette\Application\UI\Presenter diff --git a/application/es/configuration.texy b/application/es/configuration.texy index 0aa01db958..bbde2bac4e 100644 --- a/application/es/configuration.texy +++ b/application/es/configuration.texy @@ -20,6 +20,9 @@ application: # nombre del presentador de errores errorPresenter: Error # (string|array) por defecto 'Nette:Error' + # define alias para presentadores y eventos + aliases: ... + # define las reglas para resolver el nombre del presentador a una clase mapping: ... @@ -39,6 +42,8 @@ application: La opción `silentLinks` determina cómo se comporta Nette en modo desarrollo cuando falla la generación de enlaces (por ejemplo, porque no hay presentador, etc). El valor por defecto `false` significa que Nette activa `E_USER_WARNING`. El valor `true` suprime este mensaje de error. En un entorno de producción, siempre se invoca `E_USER_WARNING`. También podemos influir en este comportamiento configurando la variable del presentador [$invalidLinkMode |creating-links#Invalid Links]. +[Los alias simplifican las referencias a |creating-links#aliases] los presentadores más utilizados. + El [mapeo define las reglas |modules#mapping] por las cuales el nombre de la clase se deriva del nombre del presentador. diff --git a/application/es/creating-links.texy b/application/es/creating-links.texy index 497734da6f..d22a004836 100644 --- a/application/es/creating-links.texy +++ b/application/es/creating-links.texy @@ -223,6 +223,30 @@ $this->getPresenter()->link('Home:default') ``` +Alias .[#toc-aliases]{data-version:v3.2.2} +========================================== + +A veces resulta útil asignar un alias fácil de recordar a un par Presentador:acción. Por ejemplo, puede nombrar la página de inicio `Front:Home:default` simplemente como `home` o `Admin:Dashboard:default` como `admin`. + +Los alias se definen en la [configuración |configuration] con la clave `application › aliases`: + +```neon +application: + aliases: + home: Front:Home:default + admin: Admin:Dashboard:default + sign: Front:Sign:in +``` + +En los enlaces, se escriben utilizando el símbolo arroba, por ejemplo: + +```latte +administration +``` + +Se admiten en todos los métodos que trabajan con enlaces, como `redirect()` y similares. + + Enlaces no válidos .[#toc-invalid-links] ======================================== diff --git a/application/es/presenters.texy b/application/es/presenters.texy index 8007ff63de..22cb178aa9 100644 --- a/application/es/presenters.texy +++ b/application/es/presenters.texy @@ -447,12 +447,62 @@ $this->sendResponse(new Responses\CallbackResponse($callback)); ``` +Restricción de acceso mediante `#[Requires]` .[#toc-access-restriction-using-requires]{data-version:3.2.2} +---------------------------------------------------------------------------------------------------------- + +El atributo `#[Requires]` ofrece opciones avanzadas para restringir el acceso a los presentadores y sus métodos. Puede utilizarse para especificar métodos HTTP, requerir solicitudes AJAX, limitar el acceso al mismo origen y restringir el acceso sólo al reenvío. El atributo puede aplicarse a clases de presentadores, así como a métodos individuales como `action()`, `render()`, `handle()`y `createComponent()`. + +He aquí un ejemplo de su uso para restringir el acceso únicamente al método HTTP `POST`: + +```php +use Nette\Application\Attributes\Requires; + +#[Requires(methods: 'POST')] +class MyPresenter extends Nette\Application\UI\Presenter +{ +} +``` + +Puede especificar estas restricciones +- en los métodos HTTP: `#[Requires(methods: ['GET', 'POST'])]` +- que requieren una petición AJAX: `#[Requires(ajax: true)]` +- acceso sólo desde el mismo origen: `#[Requires(sameOrigin: true)]` +- acceso sólo mediante reenvío: `#[Requires(forward: true)]` +- restricciones sobre acciones específicas: `#[Requires(actions: 'default')]` + +Las condiciones pueden combinarse enumerando varios atributos o uniéndolos en uno solo: + +```php +#[Requires(methods: 'POST', ajax: true)] +public function actionDelete(int $id) +{ +} + +// or + +#[Requires(methods: 'POST')] +#[Requires(ajax: true)] +public function actionDelete(int $id) +{ +} +``` + + Comprobación del método HTTP .[#toc-http-method-check] ------------------------------------------------------ -Los presentadores en Nette verifican automáticamente el método HTTP de cada solicitud entrante. La razón principal de esta verificación es la seguridad. La comprobación del método se lleva a cabo en `checkHttpMethod()`, que determina si el método especificado en la petición está incluido en la matriz `$presenter->allowedMethods`. Por defecto, esta matriz contiene los elementos `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`, lo que significa que estos métodos están permitidos. +En Nette, los presentadores verifican automáticamente el método HTTP de cada solicitud entrante, principalmente por razones de seguridad. Por defecto, se permiten los métodos `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`. + +Si desea habilitar métodos adicionales como `OPTIONS`, puede utilizar el atributo `#[Requires]` (a partir de Nette Application v3.2): + +```php +#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])] +class MyPresenter extends Nette\Application\UI\Presenter +{ +} +``` -Si desea permitir adicionalmente el método `OPTIONS`, puede conseguirlo de la siguiente manera: +En la versión 3.1, la verificación se realiza en `checkHttpMethod()`, que comprueba si el método especificado en la petición está incluido en el array `$presenter->allowedMethods`. Añade un método como este ```php class MyPresenter extends Nette\Application\UI\Presenter diff --git a/application/fr/configuration.texy b/application/fr/configuration.texy index cd0c4f07c0..4398c0e7fe 100644 --- a/application/fr/configuration.texy +++ b/application/fr/configuration.texy @@ -20,6 +20,9 @@ catchExceptions : ... # (bool) valeur par défaut : true # nom du présentateur d'erreur errorPresenter: Error # (string|array) vaut par défaut 'Nette:Error'. + # définit des alias pour les présentateurs et les événements + aliases: ... + # définit les règles pour résoudre le nom du présentateur vers une classe mapping: ... @@ -39,6 +42,8 @@ application: L'option `silentLinks` détermine comment Nette se comporte en mode développeur lorsque la génération de liens échoue (par exemple, parce qu'il n'y a pas de présentateur, etc). La valeur par défaut `false` signifie que Nette déclenche `E_USER_WARNING`. Le réglage sur `true` supprime ce message d'erreur. Dans un environnement de production, `E_USER_WARNING` est toujours invoqué. Nous pouvons également influencer ce comportement en définissant la variable du présentateur [$invalidLinkMode |creating-links#Invalid Links]. +Les [alias simplifient le référencement des |creating-links#aliases] présentateurs fréquemment utilisés. + Le [mappage définit les règles |modules#mapping] selon lesquelles le nom de la classe est dérivé du nom du présentateur. diff --git a/application/fr/creating-links.texy b/application/fr/creating-links.texy index 35b5171f65..00c87674f1 100644 --- a/application/fr/creating-links.texy +++ b/application/fr/creating-links.texy @@ -223,6 +223,30 @@ $this->getPresenter()->link('Home:default') ``` +Alias .[#toc-aliases]{data-version:v3.2.2} +========================================== + +Il est parfois utile d'attribuer un alias facilement mémorisable à une paire Présentateur:action. Par exemple, vous pouvez nommer la page d'accueil `Front:Home:default` simplement `home` ou `Admin:Dashboard:default` `admin` . + +Les alias sont définis dans la [configuration |configuration] sous la clé `application › aliases`: + +```neon +application: + aliases: + home: Front:Home:default + admin: Admin:Dashboard:default + sign: Front:Sign:in +``` + +Dans les liens, ils sont écrits en utilisant le symbole at, par exemple : + +```latte +administration +``` + +Ils sont pris en charge dans toutes les méthodes qui fonctionnent avec des liens, telles que `redirect()` et similaires. + + Liens non valides .[#toc-invalid-links] ======================================= diff --git a/application/fr/presenters.texy b/application/fr/presenters.texy index fb2e2e361c..bf1050cfa2 100644 --- a/application/fr/presenters.texy +++ b/application/fr/presenters.texy @@ -447,12 +447,62 @@ $this->sendResponse(new Responses\CallbackResponse($callback)); ``` +Restriction d'accès à l'aide de `#[Requires]` .[#toc-access-restriction-using-requires]{data-version:3.2.2} +----------------------------------------------------------------------------------------------------------- + +L'attribut `#[Requires]` fournit des options avancées pour restreindre l'accès aux présentateurs et à leurs méthodes. Il peut être utilisé pour spécifier des méthodes HTTP, exiger des requêtes AJAX, limiter l'accès à la même origine et restreindre l'accès à la transmission uniquement. L'attribut peut être appliqué aux classes de présentateurs ainsi qu'aux méthodes individuelles telles que `action()`, `render()`, `handle()`, et `createComponent()`. + +Voici un exemple d'utilisation pour restreindre l'accès à la seule méthode HTTP `POST`: + +```php +use Nette\Application\Attributes\Requires; + +#[Requires(methods: 'POST')] +class MyPresenter extends Nette\Application\UI\Presenter +{ +} +``` + +Vous pouvez spécifier ces restrictions : +- sur les méthodes HTTP : `#[Requires(methods: ['GET', 'POST'])]` +- nécessitant une requête AJAX : `#[Requires(ajax: true)]` +- accès uniquement à partir de la même origine : `#[Requires(sameOrigin: true)]` +- accès uniquement par le biais d'une redirection : `#[Requires(forward: true)]` +- restrictions sur des actions spécifiques : `#[Requires(actions: 'default')]` + +Les conditions peuvent être combinées en énumérant plusieurs attributs ou en les réunissant en un seul : + +```php +#[Requires(methods: 'POST', ajax: true)] +public function actionDelete(int $id) +{ +} + +// or + +#[Requires(methods: 'POST')] +#[Requires(ajax: true)] +public function actionDelete(int $id) +{ +} +``` + + Vérification de la méthode HTTP .[#toc-http-method-check] --------------------------------------------------------- -Les présentateurs de Nette vérifient automatiquement la méthode HTTP de chaque requête entrante. La raison principale de cette vérification est la sécurité. La vérification de la méthode est effectuée dans `checkHttpMethod()`, qui détermine si la méthode spécifiée dans la demande est incluse dans le tableau `$presenter->allowedMethods`. Par défaut, ce tableau contient les éléments `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`, ce qui signifie que ces méthodes sont autorisées. +Dans Nette, les présentateurs vérifient automatiquement la méthode HTTP de chaque requête entrante, principalement pour des raisons de sécurité. Par défaut, les méthodes `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH` sont autorisées. + +Si vous souhaitez activer d'autres méthodes telles que `OPTIONS`, vous pouvez utiliser l'attribut `#[Requires]` (à partir de Nette Application v3.2) : + +```php +#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])] +class MyPresenter extends Nette\Application\UI\Presenter +{ +} +``` -Si vous souhaitez autoriser en plus la méthode `OPTIONS`, vous pouvez le faire de la manière suivante : +Dans la version 3.1, la vérification est effectuée dans `checkHttpMethod()`, qui vérifie si la méthode spécifiée dans la requête est incluse dans le tableau `$presenter->allowedMethods`. Ajouter une méthode comme celle-ci : ```php class MyPresenter extends Nette\Application\UI\Presenter diff --git a/application/hu/configuration.texy b/application/hu/configuration.texy index 4daecdf769..2dc8e2a87a 100644 --- a/application/hu/configuration.texy +++ b/application/hu/configuration.texy @@ -20,6 +20,9 @@ application: # error-presenter neve errorPresenter: Error # (string|array) alapértelmezett értéke 'Nette:Error'. + # aliasokat definiál az előadókhoz és eseményekhez + aliases: ... + # meghatározza a prezenter nevének egy osztályra való feloldására vonatkozó szabályokat. mapping: ... @@ -39,6 +42,8 @@ application: A `silentLinks` opció határozza meg, hogy a Nette hogyan viselkedjen fejlesztői módban, ha a linkgenerálás sikertelen (például mert nincs prezenter stb.). Az alapértelmezett `false` érték azt jelenti, hogy a Nette a `E_USER_WARNING` opciót váltja ki. A `true` beállítása elnyomja ezt a hibaüzenetet. Gyártási környezetben a `E_USER_WARNING` mindig meghívásra kerül. Ezt a viselkedést a [$invalidLinkMode |creating-links#Invalid Links] prezenter változó beállításával is befolyásolhatjuk. +Az [álnevek leegyszerűsítik a |creating-links#aliases] gyakran használt [előadókra való hivatkozást |creating-links#aliases]. + A [leképezés meghatározza azokat a szabályokat |modules#mapping], amelyek alapján az osztály neve a prezenter nevéből származik. diff --git a/application/hu/creating-links.texy b/application/hu/creating-links.texy index 6adfa6d498..97cc830cf5 100644 --- a/application/hu/creating-links.texy +++ b/application/hu/creating-links.texy @@ -223,6 +223,30 @@ $this->getPresenter()->link('Home:default') ``` +Álnevek .[#toc-aliases]{data-version:v3.2.2} +============================================ + +Néha hasznos, ha egy könnyen megjegyezhető álnevet rendelünk egy Presenter:action pároshoz. Például a `Front:Home:default` honlapot egyszerűen elnevezheti `home` -nek, vagy a `Admin:Dashboard:default` -t `admin`-nak. + +Az aliasok a [konfigurációban |configuration] a `application › aliases` kulcs alatt kerülnek meghatározásra: + +```neon +application: + aliases: + home: Front:Home:default + admin: Admin:Dashboard:default + sign: Front:Sign:in +``` + +A hivatkozásokban az at szimbólummal íródnak, például: + +```latte +administration +``` + +A linkekkel dolgozó összes módszer támogatja őket, például a `redirect()` és hasonlók. + + Érvénytelen hivatkozások .[#toc-invalid-links] ============================================== diff --git a/application/hu/presenters.texy b/application/hu/presenters.texy index 64e5c2d8af..f66a220e73 100644 --- a/application/hu/presenters.texy +++ b/application/hu/presenters.texy @@ -447,12 +447,62 @@ $this->sendResponse(new Responses\CallbackResponse($callback)); ``` +Hozzáférés korlátozása `#[Requires]` .[#toc-access-restriction-using-requires]{data-version:3.2.2} +-------------------------------------------------------------------------------------------------- + +A `#[Requires]` attribútum speciális lehetőségeket biztosít az előadókhoz és módszereikhez való hozzáférés korlátozására. Használható HTTP-módszerek megadására, AJAX-kérések megkövetelésére, az azonos eredetű hozzáférések korlátozására és a hozzáférésnek csak a továbbításra való korlátozására. Az attribútum alkalmazható a prezenter osztályokra, valamint az egyes metódusokra, mint például a `action()`, `render()`, `handle()`, és `createComponent()`. + +Íme egy példa arra, hogy csak a HTTP `POST` módszerre korlátozzuk a hozzáférést: + +```php +use Nette\Application\Attributes\Requires; + +#[Requires(methods: 'POST')] +class MyPresenter extends Nette\Application\UI\Presenter +{ +} +``` + +Ezeket a korlátozásokat megadhatja: +- a HTTP-módszerekre: `#[Requires(methods: ['GET', 'POST'])]` +- AJAX-kérést igényel: `#[Requires(ajax: true)]` +- hozzáférés csak ugyanabból az eredetből: `#[Requires(sameOrigin: true)]` +- hozzáférés csak továbbítással: `#[Requires(forward: true)]` +- korlátozások bizonyos műveletekre: `#[Requires(actions: 'default')]` + +A feltételek kombinálhatók több attribútum felsorolásával vagy azok egyesítésével: + +```php +#[Requires(methods: 'POST', ajax: true)] +public function actionDelete(int $id) +{ +} + +// or + +#[Requires(methods: 'POST')] +#[Requires(ajax: true)] +public function actionDelete(int $id) +{ +} +``` + + HTTP módszer ellenőrzése .[#toc-http-method-check] -------------------------------------------------- -A Nette bemutatói automatikusan ellenőrzik minden bejövő kérés HTTP-módszerét. Az ellenőrzés elsődleges oka a biztonság. A módszerellenőrzés a `checkHttpMethod()` oldalon történik, amely meghatározza, hogy a kérelemben megadott módszer szerepel-e a `$presenter->allowedMethods` tömbben. Alapértelmezés szerint ez a tömb a `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH` elemeket tartalmazza, vagyis ezek a módszerek engedélyezettek. +A Nette rendszerben az előadók elsősorban biztonsági okokból automatikusan ellenőrzik minden bejövő kérés HTTP-módszerét. Alapértelmezés szerint a `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH` módszerek engedélyezettek. + +Ha további módszereket, például a `OPTIONS`, szeretne engedélyezni, akkor használhatja a `#[Requires]` attribútumot (a Nette Application v3.2-től): + +```php +#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])] +class MyPresenter extends Nette\Application\UI\Presenter +{ +} +``` -Ha a `OPTIONS` metódust is engedélyezni kívánja, akkor ezt a következő módon érheti el: +A 3.1-es verzióban az ellenőrzést a `checkHttpMethod()` végzi, amely ellenőrzi, hogy a kérelemben megadott módszer szerepel-e a `$presenter->allowedMethods` tömbben. Adjon hozzá egy ilyen módszert: ```php class MyPresenter extends Nette\Application\UI\Presenter diff --git a/application/it/configuration.texy b/application/it/configuration.texy index b51348623a..be8d2ebc12 100644 --- a/application/it/configuration.texy +++ b/application/it/configuration.texy @@ -20,6 +20,9 @@ application: # nome del presentatore di errori errorPresenter: Error # (string|array) predefinito a 'Nette:Error'. + # definisce gli alias per i presentatori e gli eventi + aliases: ... + # definisce le regole per risolvere il nome del presentatore in una classe mapping: ... @@ -39,6 +42,8 @@ application: L'opzione `silentLinks` determina il comportamento di Nette in modalità sviluppatore quando la generazione dei collegamenti fallisce (ad esempio, perché non c'è un presentatore, ecc.). Il valore predefinito `false` significa che Nette attiva `E_USER_WARNING`. L'impostazione di `true` sopprime questo messaggio di errore. In un ambiente di produzione, `E_USER_WARNING` viene sempre invocato. Si può anche influenzare questo comportamento impostando la variabile del presentatore [$invalidLinkMode |creating-links#Invalid Links]. +Gli [pseudonimi semplificano il riferimento ai |creating-links#aliases] presentatori utilizzati di frequente. + La [mappatura definisce le regole |modules#mapping] con cui il nome della classe viene derivato dal nome del presentatore. diff --git a/application/it/creating-links.texy b/application/it/creating-links.texy index 40648f85d6..1c83fc0b31 100644 --- a/application/it/creating-links.texy +++ b/application/it/creating-links.texy @@ -223,6 +223,30 @@ $this->getPresenter()->link('Home:default') ``` +Alias .[#toc-aliases]{data-version:v3.2.2} +========================================== + +A volte è utile assegnare un alias facilmente memorizzabile a una coppia Presentatore:azione. Per esempio, si può nominare la pagina iniziale `Front:Home:default` semplicemente come `home` o `Admin:Dashboard:default` come `admin`. + +Gli alias sono definiti nella [configurazione |configuration] sotto la chiave `application › aliases`: + +```neon +application: + aliases: + home: Front:Home:default + admin: Admin:Dashboard:default + sign: Front:Sign:in +``` + +Nei collegamenti, vengono scritti utilizzando il simbolo at, ad esempio: + +```latte +administration +``` + +Sono supportati in tutti i metodi che lavorano con i collegamenti, come `redirect()` e simili. + + Collegamenti non validi .[#toc-invalid-links] ============================================= diff --git a/application/it/presenters.texy b/application/it/presenters.texy index f9e9fb9473..874bdb7ccf 100644 --- a/application/it/presenters.texy +++ b/application/it/presenters.texy @@ -447,12 +447,62 @@ $this->sendResponse(new Responses\CallbackResponse($callback)); ``` +Limitazione dell'accesso tramite `#[Requires]` .[#toc-access-restriction-using-requires]{data-version:3.2.2} +------------------------------------------------------------------------------------------------------------ + +L'attributo `#[Requires]` fornisce opzioni avanzate per limitare l'accesso ai presentatori e ai loro metodi. Può essere usato per specificare metodi HTTP, richiedere richieste AJAX, limitare l'accesso alla stessa origine e limitare l'accesso al solo inoltro. L'attributo può essere applicato alle classi di presentatori e ai singoli metodi, come ad esempio `action()`, `render()`, `handle()`, e `createComponent()`. + +Ecco un esempio di utilizzo per limitare l'accesso al solo metodo HTTP `POST`: + +```php +use Nette\Application\Attributes\Requires; + +#[Requires(methods: 'POST')] +class MyPresenter extends Nette\Application\UI\Presenter +{ +} +``` + +È possibile specificare queste restrizioni: +- sui metodi HTTP: `#[Requires(methods: ['GET', 'POST'])]` +- che richiedono una richiesta AJAX: `#[Requires(ajax: true)]` +- accesso solo dalla stessa origine: `#[Requires(sameOrigin: true)]` +- accesso solo tramite inoltro: `#[Requires(forward: true)]` +- restrizioni su azioni specifiche: `#[Requires(actions: 'default')]` + +Le condizioni possono essere combinate elencando più attributi o unendoli in uno solo: + +```php +#[Requires(methods: 'POST', ajax: true)] +public function actionDelete(int $id) +{ +} + +// or + +#[Requires(methods: 'POST')] +#[Requires(ajax: true)] +public function actionDelete(int $id) +{ +} +``` + + Controllo del metodo HTTP .[#toc-http-method-check] --------------------------------------------------- -I presentatori di Nette verificano automaticamente il metodo HTTP di ogni richiesta in arrivo. Il motivo principale di questa verifica è la sicurezza. La verifica del metodo viene eseguita in `checkHttpMethod()`, che determina se il metodo specificato nella richiesta è incluso nell'array `$presenter->allowedMethods`. Per impostazione predefinita, questo array contiene gli elementi `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`, il che significa che questi metodi sono consentiti. +In Nette, i presentatori verificano automaticamente il metodo HTTP di ogni richiesta in arrivo, principalmente per motivi di sicurezza. Per impostazione predefinita, sono ammessi i metodi `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`. + +Se si desidera abilitare altri metodi, come ad esempio `OPTIONS`, è possibile utilizzare l'attributo `#[Requires]` (dall'applicazione Nette v3.2): + +```php +#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])] +class MyPresenter extends Nette\Application\UI\Presenter +{ +} +``` -Se si desidera consentire anche il metodo `OPTIONS`, è possibile farlo nel modo seguente: +Nella versione 3.1, la verifica viene eseguita in `checkHttpMethod()`, che controlla se il metodo specificato nella richiesta è incluso nell'array `$presenter->allowedMethods`. Aggiungere un metodo come questo: ```php class MyPresenter extends Nette\Application\UI\Presenter diff --git a/application/pl/configuration.texy b/application/pl/configuration.texy index e7de3cf4b9..7986b64e24 100644 --- a/application/pl/configuration.texy +++ b/application/pl/configuration.texy @@ -20,6 +20,9 @@ application: # error-presenter name errorPresenter: Error # (string|array) domyślnie 'Nette:Error' + # definiuje aliasy dla prezenterów i wydarzeń + aliases: ... + # definiuje zasady rozwiązywania nazwy prezentera do klasy mapping: ... @@ -39,6 +42,8 @@ application: Opcja `silentLinks` określa, jak Nette zachowuje się w trybie rozwoju, gdy generowanie linków nie powiedzie się (np. z powodu braku prezentera itp.). Domyślna wartość `false` oznacza, że Nette rzuci błąd `E_USER_WARNING`. Ustawienie go na `true` spowoduje wyeliminowanie tego komunikatu o błędzie. W środowisku produkcyjnym, `E_USER_WARNING` jest zawsze podniesiony. Na to zachowanie można również wpłynąć poprzez ustawienie zmiennej prezentera [$invalidLinkMode |creating-links#Invalid-Links]. +[Aliasy ułatwiają odwoływanie się do |creating-links#aliases] często używanych prezenterów. + [Odwzorowanie określa zasady |modules#Mapping], według których nazwa klasy jest wyprowadzana z nazwy prezentera. diff --git a/application/pl/creating-links.texy b/application/pl/creating-links.texy index bea0dda8d5..23d1be2671 100644 --- a/application/pl/creating-links.texy +++ b/application/pl/creating-links.texy @@ -223,6 +223,30 @@ $this->getPresenter()->link('Home:default') ``` +Pseudonimy .[#toc-aliases]{data-version:v3.2.2} +=============================================== + +Czasami przydatne jest przypisanie łatwego do zapamiętania aliasu do pary Presenter:action. Na przykład, można nazwać stronę główną `Front:Home:default` po prostu jako `home` lub `Admin:Dashboard:default` jako `admin`. + +Aliasy są definiowane w [konfiguracji |configuration] pod kluczem `application › aliases`: + +```neon +application: + aliases: + home: Front:Home:default + admin: Admin:Dashboard:default + sign: Front:Sign:in +``` + +W linkach są one zapisywane przy użyciu symbolu at, na przykład: + +```latte +administration +``` + +Są one obsługiwane we wszystkich metodach, które działają z linkami, takimi jak `redirect()` i podobne. + + Nieprawidłowe linki .[#toc-invalid-links] ========================================= diff --git a/application/pl/presenters.texy b/application/pl/presenters.texy index a95c9e7755..62d76b71a0 100644 --- a/application/pl/presenters.texy +++ b/application/pl/presenters.texy @@ -447,12 +447,62 @@ $this->sendResponse(new Responses\CallbackResponse($callback)); ``` +Ograniczenie dostępu przy użyciu `#[Requires]` .[#toc-access-restriction-using-requires]{data-version:3.2.2} +------------------------------------------------------------------------------------------------------------ + +Atrybut `#[Requires]` zapewnia zaawansowane opcje ograniczania dostępu do prezenterów i ich metod. Można go użyć do określenia metod HTTP, wymagania żądań AJAX, ograniczenia dostępu do tego samego źródła i ograniczenia dostępu tylko do przekazywania. Atrybut może być stosowany do klas prezenterów, jak również poszczególnych metod, takich jak `action()`, `render()`, `handle()`, i `createComponent()`. + +Oto przykład użycia go do ograniczenia dostępu tylko do metody HTTP `POST`: + +```php +use Nette\Application\Attributes\Requires; + +#[Requires(methods: 'POST')] +class MyPresenter extends Nette\Application\UI\Presenter +{ +} +``` + +Można określić te ograniczenia: +- na metodach HTTP: `#[Requires(methods: ['GET', 'POST'])]` +- wymagające żądania AJAX: `#[Requires(ajax: true)]` +- dostęp tylko z tego samego źródła: `#[Requires(sameOrigin: true)]` +- dostęp tylko przez przekierowanie: `#[Requires(forward: true)]` +- ograniczenia dotyczące określonych działań: `#[Requires(actions: 'default')]` + +Warunki można łączyć, wymieniając wiele atrybutów lub łącząc je w jeden: + +```php +#[Requires(methods: 'POST', ajax: true)] +public function actionDelete(int $id) +{ +} + +// or + +#[Requires(methods: 'POST')] +#[Requires(ajax: true)] +public function actionDelete(int $id) +{ +} +``` + + Sprawdzanie metod HTTP .[#toc-http-method-check] ------------------------------------------------ -Prezenterzy w Nette automatycznie weryfikują metodę HTTP każdego przychodzącego żądania. Głównym powodem tej weryfikacji jest bezpieczeństwo. Weryfikacja metody jest przeprowadzana w `checkHttpMethod()`, który określa, czy metoda określona w żądaniu znajduje się w tablicy `$presenter->allowedMethods`. Domyślnie tablica ta zawiera elementy `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`, co oznacza, że metody te są dozwolone. +W Nette prezenterzy automatycznie weryfikują metodę HTTP każdego przychodzącego żądania głównie ze względów bezpieczeństwa. Domyślnie dozwolone są metody `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`. + +Jeśli chcesz włączyć dodatkowe metody, takie jak `OPTIONS`, możesz użyć atrybutu `#[Requires]` (od wersji Nette Application v3.2): + +```php +#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])] +class MyPresenter extends Nette\Application\UI\Presenter +{ +} +``` -Jeśli chcesz dodatkowo zezwolić na metodę `OPTIONS`, można to osiągnąć w następujący sposób: +W wersji 3.1 weryfikacja jest wykonywana w `checkHttpMethod()`, która sprawdza, czy metoda określona w żądaniu znajduje się w tablicy `$presenter->allowedMethods`. Należy dodać taką metodę: ```php class MyPresenter extends Nette\Application\UI\Presenter diff --git a/application/pt/configuration.texy b/application/pt/configuration.texy index fa13aa7950..d83543aca8 100644 --- a/application/pt/configuration.texy +++ b/application/pt/configuration.texy @@ -20,6 +20,9 @@ application: # nome do apresentador de erro errorPresenter: Error # (string|array) padrão para 'Nette:Erro'. + # define aliases para apresentadores e eventos + aliases: ... + # define as regras para resolver o nome do apresentador para uma classe mapping: ... @@ -39,6 +42,8 @@ application: A opção `silentLinks` determina como Nette se comporta em modo desenvolvedor quando a geração de links falha (por exemplo, porque não há apresentador, etc.). O valor padrão `false` significa que a Nette aciona `E_USER_WARNING`. A configuração para `true` suprime esta mensagem de erro. Em um ambiente de produção, `E_USER_WARNING` é sempre invocado. Também podemos influenciar este comportamento definindo a variável apresentadora [$invalidLinkMode |creating-links#Invalid Links]. +[Os apelidos simplificam a referência a |creating-links#aliases] apresentadores usados com frequência. + O [mapeamento define as regras |modules#mapping] pelas quais o nome da classe é derivado do nome do apresentador. diff --git a/application/pt/creating-links.texy b/application/pt/creating-links.texy index 349e4358cd..fa9feeb9a8 100644 --- a/application/pt/creating-links.texy +++ b/application/pt/creating-links.texy @@ -223,6 +223,30 @@ $this->getPresenter()->link('Home:default') ``` +Pseudônimos .[#toc-aliases]{data-version:v3.2.2} +================================================ + +Às vezes, é útil atribuir um alias facilmente memorável a um par Presenter:action. Por exemplo, você poderia nomear a página inicial `Front:Home:default` simplesmente como `home` ou `Admin:Dashboard:default` como `admin`. + +Os aliases são definidos na [configuração |configuration] sob a chave `application › aliases`: + +```neon +application: + aliases: + home: Front:Home:default + admin: Admin:Dashboard:default + sign: Front:Sign:in +``` + +Nos links, eles são escritos usando o símbolo at, por exemplo: + +```latte +administration +``` + +Eles são compatíveis com todos os métodos que funcionam com links, como `redirect()` e similares. + + Links inválidos .[#toc-invalid-links] ===================================== diff --git a/application/pt/presenters.texy b/application/pt/presenters.texy index f0d78415f6..655e650b6f 100644 --- a/application/pt/presenters.texy +++ b/application/pt/presenters.texy @@ -447,12 +447,62 @@ $this->sendResponse(new Responses\CallbackResponse($callback)); ``` +Restrição de acesso usando `#[Requires]` .[#toc-access-restriction-using-requires]{data-version:3.2.2} +------------------------------------------------------------------------------------------------------ + +O atributo `#[Requires]` fornece opções avançadas para restringir o acesso aos apresentadores e seus métodos. Ele pode ser usado para especificar métodos HTTP, exigir solicitações AJAX, limitar o acesso à mesma origem e restringir o acesso somente ao encaminhamento. O atributo pode ser aplicado a classes de apresentadores, bem como a métodos individuais, como `action()`, `render()`, `handle()`, e `createComponent()`. + +Veja a seguir um exemplo de uso para restringir o acesso apenas ao método HTTP `POST`: + +```php +use Nette\Application\Attributes\Requires; + +#[Requires(methods: 'POST')] +class MyPresenter extends Nette\Application\UI\Presenter +{ +} +``` + +Você pode especificar essas restrições: +- em métodos HTTP: `#[Requires(methods: ['GET', 'POST'])]` +- que exigem uma solicitação AJAX: `#[Requires(ajax: true)]` +- acesso somente a partir da mesma origem: `#[Requires(sameOrigin: true)]` +- acesso somente por meio de encaminhamento: `#[Requires(forward: true)]` +- restrições a ações específicas: `#[Requires(actions: 'default')]` + +As condições podem ser combinadas listando vários atributos ou unindo-os em um só: + +```php +#[Requires(methods: 'POST', ajax: true)] +public function actionDelete(int $id) +{ +} + +// or + +#[Requires(methods: 'POST')] +#[Requires(ajax: true)] +public function actionDelete(int $id) +{ +} +``` + + Verificação do método HTTP .[#toc-http-method-check] ---------------------------------------------------- -Os apresentadores do Nette verificam automaticamente o método HTTP de cada solicitação recebida. O principal motivo para essa verificação é a segurança. A verificação do método é realizada em `checkHttpMethod()`, que determina se o método especificado na solicitação está incluído na matriz `$presenter->allowedMethods`. Por padrão, essa matriz contém os itens `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`, o que significa que esses métodos são permitidos. +No Nette, os apresentadores verificam automaticamente o método HTTP de cada solicitação recebida, principalmente por motivos de segurança. Por padrão, os métodos `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH` são permitidos. + +Se quiser habilitar métodos adicionais, como `OPTIONS`, você pode usar o atributo `#[Requires]` (do Nette Application v3.2): + +```php +#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])] +class MyPresenter extends Nette\Application\UI\Presenter +{ +} +``` -Se você quiser permitir adicionalmente o método `OPTIONS`, isso pode ser feito da seguinte maneira: +Na versão 3.1, a verificação é realizada em `checkHttpMethod()`, que verifica se o método especificado na solicitação está incluído na matriz `$presenter->allowedMethods`. Adicione um método como este: ```php class MyPresenter extends Nette\Application\UI\Presenter diff --git a/application/ro/configuration.texy b/application/ro/configuration.texy index a4c1e61233..4783df2ade 100644 --- a/application/ro/configuration.texy +++ b/application/ro/configuration.texy @@ -20,6 +20,9 @@ application: # numele prezentatorului de erori errorPresenter: Error # (string|array) valoarea implicită este "Nette:Error" (Nette:Error) + # definește pseudonimele pentru prezentatori și evenimente + aliases: ... + # definește regulile de rezolvare a numelui prezentatorului la o clasă mapping: ... @@ -39,6 +42,8 @@ application: Opțiunea `silentLinks` determină modul în care se comportă Nette în modul de dezvoltare atunci când generarea legăturilor eșuează (de exemplu, pentru că nu există un prezentator etc.). Valoarea implicită `false` înseamnă că Nette declanșează `E_USER_WARNING`. Setarea la `true` suprimă acest mesaj de eroare. Într-un mediu de producție, `E_USER_WARNING` este întotdeauna invocat. De asemenea, putem influența acest comportament prin setarea variabilei presenter [$invalidLinkMode |creating-links#Invalid Links]. +[Pseudonimele simplifică trimiterea |creating-links#aliases] la prezentatorii utilizați frecvent. + [Cartografierea definește regulile |modules#mapping] prin care numele clasei este derivat din numele prezentatorului. diff --git a/application/ro/creating-links.texy b/application/ro/creating-links.texy index c296f1546a..187cb01adf 100644 --- a/application/ro/creating-links.texy +++ b/application/ro/creating-links.texy @@ -223,6 +223,30 @@ $this->getPresenter()->link('Home:default') ``` +Aliasuri .[#toc-aliases]{data-version:v3.2.2} +============================================= + +Uneori este util să atribuiți un pseudonim ușor de memorat unei perechi prezentator:acțiune. De exemplu, ați putea numi pagina de pornire `Front:Home:default` simplu `home` sau `Admin:Dashboard:default` `admin` . + +Aliasurile sunt definite în [configurație |configuration] sub cheia `application › aliases`: + +```neon +application: + aliases: + home: Front:Home:default + admin: Admin:Dashboard:default + sign: Front:Sign:in +``` + +În legături, acestea se scriu folosind simbolul at, de exemplu: + +```latte +administration +``` + +Acestea sunt acceptate în toate metodele care lucrează cu legături, cum ar fi `redirect()` și altele similare. + + Legături nevalabile .[#toc-invalid-links] ========================================= diff --git a/application/ro/presenters.texy b/application/ro/presenters.texy index b8c7099587..76c214a56a 100644 --- a/application/ro/presenters.texy +++ b/application/ro/presenters.texy @@ -447,12 +447,62 @@ $this->sendResponse(new Responses\CallbackResponse($callback)); ``` +Restricții de acces Utilizarea `#[Requires]` .[#toc-access-restriction-using-requires]{data-version:3.2.2} +---------------------------------------------------------------------------------------------------------- + +Aplicația `#[Requires]` oferă opțiuni avansate pentru restricționarea accesului la prezentatori și la metodele acestora. Acesta poate fi utilizat pentru a specifica metodele HTTP, pentru a solicita cereri AJAX, pentru a limita accesul la aceeași origine și pentru a restricționa accesul doar la redirecționare. Atributul poate fi aplicat atât claselor de prezentatori, cât și metodelor individuale, cum ar fi `action()`, `render()`, `handle()`, și `createComponent()`. + +Iată un exemplu de utilizare pentru a restricționa accesul doar la metoda HTTP `POST`: + +```php +use Nette\Application\Attributes\Requires; + +#[Requires(methods: 'POST')] +class MyPresenter extends Nette\Application\UI\Presenter +{ +} +``` + +Puteți specifica aceste restricții: +- pe metodele HTTP: `#[Requires(methods: ['GET', 'POST'])]` +- care necesită o cerere AJAX: `#[Requires(ajax: true)]` +- accesul numai de la aceeași origine: `#[Requires(sameOrigin: true)]` +- acces numai prin redirecționare: `#[Requires(forward: true)]` +- restricții privind anumite acțiuni: `#[Requires(actions: 'default')]` + +Condițiile pot fi combinate prin enumerarea mai multor atribute sau prin unirea lor într-unul singur: + +```php +#[Requires(methods: 'POST', ajax: true)] +public function actionDelete(int $id) +{ +} + +// or + +#[Requires(methods: 'POST')] +#[Requires(ajax: true)] +public function actionDelete(int $id) +{ +} +``` + + Verificarea metodei HTTP .[#toc-http-method-check] -------------------------------------------------- -Prezentatorii din Nette verifică automat metoda HTTP a fiecărei cereri primite. Motivul principal al acestei verificări este securitatea. Verificarea metodei se efectuează în `checkHttpMethod()`, care determină dacă metoda specificată în cerere este inclusă în matricea `$presenter->allowedMethods`. În mod implicit, această matrice conține elementele `GET`, `POST`, `HEAD`, , `PUT`, `DELETE`, `PATCH`, ceea ce înseamnă că aceste metode sunt permise. +În Nette, prezentatorii verifică automat metoda HTTP a fiecărei cereri primite, în primul rând din motive de securitate. În mod implicit, sunt permise metodele `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`. + +Dacă doriți să activați metode suplimentare, cum ar fi `OPTIONS`, puteți utiliza opțiunea `#[Requires]` attribute (din aplicația Nette Application v3.2): + +```php +#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])] +class MyPresenter extends Nette\Application\UI\Presenter +{ +} +``` -Dacă doriți să permiteți în plus metoda `OPTIONS`, acest lucru poate fi realizat în felul următor: +În versiunea 3.1, verificarea se efectuează în `checkHttpMethod()`, care verifică dacă metoda specificată în cerere este inclusă în matricea `$presenter->allowedMethods`. Adăugați o metodă de genul următor: ```php class MyPresenter extends Nette\Application\UI\Presenter diff --git a/application/ru/configuration.texy b/application/ru/configuration.texy index 0d3382d5ac..9cb80fc192 100644 --- a/application/ru/configuration.texy +++ b/application/ru/configuration.texy @@ -20,6 +20,9 @@ application: # имя презентера ошибок errorPresenter: Error # (string|array) по умолчанию 'Nette:Error' + # определяет псевдонимы для ведущих и событий + aliases: ... + # определяет правила для преобразования имени ведущего в класс mapping: ... @@ -39,6 +42,8 @@ application: Опция `silentLinks` определяет, как Nette ведет себя в режиме разработчика, когда генерация ссылок не удается (например, из-за отсутствия презентера и т. д.). Значение по умолчанию `false` означает, что Nette запускает `E_USER_WARNING`. Установка значения `true` подавляет это сообщение об ошибке. В производственной среде всегда вызывается `E_USER_WARNING`. Мы также можем повлиять на это поведение, установив переменную презентера [$invalidLinkMode |creating-links#Invalid-Links]. +[Псевдонимы упрощают обращение к |creating-links#aliases] часто используемым ведущим. + Карта [mapping определяет правила |modules#Mapping], по которым имя класса выводится из имени ведущего. diff --git a/application/ru/creating-links.texy b/application/ru/creating-links.texy index ad3f4f361f..02cd240f36 100644 --- a/application/ru/creating-links.texy +++ b/application/ru/creating-links.texy @@ -223,6 +223,30 @@ $this->getPresenter()->link('Home:default') ``` +Псевдонимы .[#toc-aliases]{data-version:v3.2.2} +=============================================== + +Иногда полезно назначить легко запоминающийся псевдоним для пары Ведущий:действие. Например, вы можете назвать домашнюю страницу `Front:Home:default` просто `home` или `Admin:Dashboard:default` - `admin`. + +Псевдонимы задаются в [конфигурации |configuration] под ключом `application › aliases`: + +```neon +application: + aliases: + home: Front:Home:default + admin: Admin:Dashboard:default + sign: Front:Sign:in +``` + +В ссылках они записываются с использованием символа at, например: + +```latte +administration +``` + +Они поддерживаются во всех методах, работающих со ссылками, таких как `redirect()` и подобные. + + Недействительные ссылки .[#toc-invalid-links] ============================================= diff --git a/application/ru/presenters.texy b/application/ru/presenters.texy index b3b9fa2713..1e75735ac8 100644 --- a/application/ru/presenters.texy +++ b/application/ru/presenters.texy @@ -447,12 +447,62 @@ $this->sendResponse(new Responses\CallbackResponse($callback)); ``` +Ограничение доступа с помощью `#[Requires]` .[#toc-access-restriction-using-requires]{data-version:3.2.2} +--------------------------------------------------------------------------------------------------------- + +Атрибут `#[Requires]` предоставляет расширенные возможности для ограничения доступа к ведущим и их методам. С его помощью можно указать HTTP-методы, потребовать AJAX-запросы, ограничить доступ к одному и тому же источнику и ограничить доступ только пересылкой. Атрибут может применяться как к классам ведущих, так и к отдельным методам, таким как `action()`, `render()`, `handle()`, и `createComponent()`. + +Вот пример использования этого метода для ограничения доступа только к методу HTTP `POST`: + +```php +use Nette\Application\Attributes\Requires; + +#[Requires(methods: 'POST')] +class MyPresenter extends Nette\Application\UI\Presenter +{ +} +``` + +Вы можете указать эти ограничения: +- на методы HTTP: `#[Requires(methods: ['GET', 'POST'])]` +- требующих AJAX-запроса: `#[Requires(ajax: true)]` +- доступ только из одного источника: `#[Requires(sameOrigin: true)]` +- доступ только через переадресацию: `#[Requires(forward: true)]` +- ограничения на определенные действия: `#[Requires(actions: 'default')]` + +Условия можно комбинировать, перечисляя несколько атрибутов или объединяя их в один: + +```php +#[Requires(methods: 'POST', ajax: true)] +public function actionDelete(int $id) +{ +} + +// or + +#[Requires(methods: 'POST')] +#[Requires(ajax: true)] +public function actionDelete(int $id) +{ +} +``` + + Проверка метода HTTP .[#toc-http-method-check] ---------------------------------------------- -Презентаторы в Nette автоматически проверяют HTTP-метод каждого входящего запроса. Основной причиной такой проверки является безопасность. Проверка метода осуществляется в `checkHttpMethod()`, который определяет, включен ли указанный в запросе метод в массив `$presenter->allowedMethods`. По умолчанию этот массив содержит элементы `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`, что означает, что эти методы разрешены. +В Nette ведущие автоматически проверяют HTTP-метод каждого входящего запроса, прежде всего, из соображений безопасности. По умолчанию разрешены методы `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`. + +Если вы хотите разрешить дополнительные методы, такие как `OPTIONS`, вы можете использовать атрибут `#[Requires]` атрибут (из Nette Application v3.2): + +```php +#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])] +class MyPresenter extends Nette\Application\UI\Presenter +{ +} +``` -Если необходимо дополнительно разрешить метод `OPTIONS`, то это можно сделать следующим образом: +В версии 3.1 проверка осуществляется в методе `checkHttpMethod()`, который проверяет, включен ли указанный в запросе метод в массив `$presenter->allowedMethods`. Добавьте метод следующим образом: ```php class MyPresenter extends Nette\Application\UI\Presenter diff --git a/application/sl/configuration.texy b/application/sl/configuration.texy index 8111f98635..b12fdcd385 100644 --- a/application/sl/configuration.texy +++ b/application/sl/configuration.texy @@ -20,6 +20,9 @@ application: # ime programa error-presenter errorPresenter: Error # (string|array) privzeto 'Nette:Error' + # določa vzdevke za voditelje in dogodke + aliases: ... + # določa pravila za razrešitev imena predstavnika na razred mapping: ... @@ -39,6 +42,8 @@ application: Možnost `silentLinks` določa, kako se Nette obnaša v razvojnem načinu, ko generiranje povezav ne uspe (na primer ker ni predstavnika itd.). Privzeta vrednost `false` pomeni, da Nette sproži `E_USER_WARNING`. Nastavitev na `true` to sporočilo o napaki odpravi. V produkcijskem okolju se vedno sproži `E_USER_WARNING`. Na to obnašanje lahko vplivamo tudi z nastavitvijo spremenljivke presenterja [$invalidLinkMode |creating-links#Invalid Links]. +[Psevdonimi poenostavijo sklicevanje na |creating-links#aliases] pogosto uporabljene predstavnike. + [Prikazovanje določa pravila, |modules#mapping] po katerih se ime razreda izpelje iz imena predstavnika. diff --git a/application/sl/creating-links.texy b/application/sl/creating-links.texy index 1fb0ff24c2..3f8341829c 100644 --- a/application/sl/creating-links.texy +++ b/application/sl/creating-links.texy @@ -223,6 +223,30 @@ $this->getPresenter()->link('Home:default') ``` +Vzdevki .[#toc-aliases]{data-version:v3.2.2} +============================================ + +Včasih je koristno, da paru predavatelj:dejanje dodelite lahko zapomljiv vzdevek. Na primer, domačo stran `Front:Home:default` lahko poimenujete preprosto kot `home` ali `Admin:Dashboard:default` kot `admin`. + +Vzdevki so v [konfiguraciji |configuration] opredeljeni pod ključem `application › aliases`: + +```neon +application: + aliases: + home: Front:Home:default + admin: Admin:Dashboard:default + sign: Front:Sign:in +``` + +V povezavah so zapisani s simbolom at, na primer: + +```latte +administration +``` + +Podprte so v vseh metodah, ki delajo s povezavami, na primer `redirect()` in podobno. + + Neveljavne povezave .[#toc-invalid-links] ========================================= diff --git a/application/sl/presenters.texy b/application/sl/presenters.texy index dd08914fe0..8e33a702e0 100644 --- a/application/sl/presenters.texy +++ b/application/sl/presenters.texy @@ -447,12 +447,62 @@ $this->sendResponse(new Responses\CallbackResponse($callback)); ``` +Omejitev dostopa z uporabo `#[Requires]` .[#toc-access-restriction-using-requires]{data-version:3.2.2} +------------------------------------------------------------------------------------------------------ + +. `#[Requires]` atribut zagotavlja napredne možnosti za omejevanje dostopa do predavateljev in njihovih metod. Z njim lahko določite metode HTTP, zahtevate zahteve AJAX, omejite dostop do istega izvora in omejite dostop samo na posredovanje. Atribut je mogoče uporabiti za razrede predstavnikov in posamezne metode, kot so `action()`, `render()`, `handle()`, in `createComponent()`. + +Tukaj je primer uporabe za omejitev dostopa samo na metodo HTTP `POST`: + +```php +use Nette\Application\Attributes\Requires; + +#[Requires(methods: 'POST')] +class MyPresenter extends Nette\Application\UI\Presenter +{ +} +``` + +Določite lahko te omejitve: +- za metode HTTP: `#[Requires(methods: ['GET', 'POST'])]` +- ki zahteva zahtevo AJAX: `#[Requires(ajax: true)]` +- dostop samo iz istega izvora: `#[Requires(sameOrigin: true)]` +- dostop samo prek posredovanja: `#[Requires(forward: true)]` +- omejitve za določena dejanja: `#[Requires(actions: 'default')]` + +Pogoje lahko združite tako, da navedete več atributov ali jih združite v enega: + +```php +#[Requires(methods: 'POST', ajax: true)] +public function actionDelete(int $id) +{ +} + +// or + +#[Requires(methods: 'POST')] +#[Requires(ajax: true)] +public function actionDelete(int $id) +{ +} +``` + + Preverjanje metode HTTP .[#toc-http-method-check] ------------------------------------------------- -Predstavniki v Nette samodejno preverijo metodo HTTP vsake prejete zahteve. Glavni razlog za to preverjanje je varnost. Preverjanje metode se izvede v `checkHttpMethod()`, ki ugotovi, ali je metoda, navedena v zahtevi, vključena v polje `$presenter->allowedMethods`. Privzeto to polje vsebuje elemente `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`, kar pomeni, da so te metode dovoljene. +V omrežju Nette predstavniki samodejno preverijo metodo HTTP vsake prejete zahteve predvsem iz varnostnih razlogov. Privzeto so dovoljene metode `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`. + +Če želite omogočiti dodatne metode, kot je `OPTIONS`, lahko uporabite `#[Requires]` atribut (od različice Nette Application v3.2): + +```php +#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])] +class MyPresenter extends Nette\Application\UI\Presenter +{ +} +``` -Če želite dodatno dovoliti metodo `OPTIONS`, lahko to dosežete na naslednji način: +V različici 3.1 se preverjanje izvaja v `checkHttpMethod()`, ki preveri, ali je metoda, navedena v zahtevi, vključena v polje `$presenter->allowedMethods`. Dodajte metodo, kot je ta: ```php class MyPresenter extends Nette\Application\UI\Presenter diff --git a/application/tr/configuration.texy b/application/tr/configuration.texy index 14027ca069..2f1ed45c00 100644 --- a/application/tr/configuration.texy +++ b/application/tr/configuration.texy @@ -20,6 +20,9 @@ application: # hata sunucusunun adı errorPresenter: Error # (string|array) varsayılan olarak 'Nette:Error' + # sunum yapanlar ve etkinlikler için takma adlar tanımlar + aliases: ... + # sunum yapan kişinin adını bir sınıfa çözümlemek için kuralları tanımlar mapping: ... @@ -39,6 +42,8 @@ application: `silentLinks` seçeneği, bağlantı oluşturma başarısız olduğunda (örneğin, sunum yapan kişi olmadığından vb.) Nette'in geliştirici modunda nasıl davranacağını belirler. Varsayılan değer olan `false`, Nette'in `E_USER_WARNING` adresini tetikleyeceği anlamına gelir. `true` olarak ayarlanması bu hata mesajını bastırır. Bir üretim ortamında, `E_USER_WARNING` her zaman çağrılır. Bu davranışı, sunum yapan değişken [$invalidLinkMode'u |creating-links#Invalid Links] ayarlayarak da etkileyebiliriz. +[Takma adlar |creating-links#aliases], sık kullanılan sunum yapanlara [atıfta bulunmayı kolaylaştırır |creating-links#aliases]. + [Eşleme |modules#mapping], sınıf adının sunum yapan kişinin adından türetildiği [kuralları tanımlar |modules#mapping]. diff --git a/application/tr/creating-links.texy b/application/tr/creating-links.texy index 34cde301ee..cbdb8c5b7d 100644 --- a/application/tr/creating-links.texy +++ b/application/tr/creating-links.texy @@ -223,6 +223,30 @@ $this->getPresenter()->link('Home:default') ``` +Takma Adlar .[#toc-aliases]{data-version:v3.2.2} +================================================ + +Bazen bir Presenter:action çiftine kolayca hatırlanabilir bir takma ad atamak yararlı olabilir. Örneğin, `Front:Home:default` ana sayfasını basitçe `home` veya `Admin:Dashboard:default` ana sayfasını `admin` olarak adlandırabilirsiniz. + +Takma adlar [yapılandırmada |configuration] `application › aliases` anahtarı altında tanımlanır: + +```neon +application: + aliases: + home: Front:Home:default + admin: Admin:Dashboard:default + sign: Front:Sign:in +``` + +Bağlantılarda, örneğin at sembolü kullanılarak yazılırlar: + +```latte +administration +``` + + `redirect()` ve benzeri gibi bağlantılarla çalışan tüm yöntemlerde desteklenirler. + + Geçersiz Bağlantılar .[#toc-invalid-links] ========================================== diff --git a/application/tr/presenters.texy b/application/tr/presenters.texy index f269c3e2c7..512b73e142 100644 --- a/application/tr/presenters.texy +++ b/application/tr/presenters.texy @@ -447,12 +447,62 @@ $this->sendResponse(new Responses\CallbackResponse($callback)); ``` +Erişim Kısıtlaması Kullanımı `#[Requires]` .[#toc-access-restriction-using-requires]{data-version:3.2.2} +-------------------------------------------------------------------------------------------------------- + +Bu `#[Requires]` özniteliği, sunum yapanlara ve yöntemlerine erişimi kısıtlamak için gelişmiş seçenekler sağlar. HTTP yöntemlerini belirtmek, AJAX istekleri gerektirmek, erişimi aynı kaynakla sınırlamak ve erişimi yalnızca yönlendirme ile kısıtlamak için kullanılabilir. Öznitelik, sunum yapan sınıfların yanı sıra aşağıdaki gibi bireysel yöntemlere de uygulanabilir `action()`, `render()`, `handle()`ve `createComponent()`. + +İşte sadece HTTP `POST` yöntemine erişimi kısıtlamak için bir kullanım örneği: + +```php +use Nette\Application\Attributes\Requires; + +#[Requires(methods: 'POST')] +class MyPresenter extends Nette\Application\UI\Presenter +{ +} +``` + +Bu kısıtlamaları belirtebilirsiniz: +- HTTP yöntemleri üzerinde: `#[Requires(methods: ['GET', 'POST'])]` +- AJAX isteği gerektiriyor: `#[Requires(ajax: true)]` +- yalnızca aynı kaynaktan erişim: `#[Requires(sameOrigin: true)]` +- yalnızca yönlendirme yoluyla erişim: `#[Requires(forward: true)]` +- belirli eylemlere ilişkin kısıtlamalar: `#[Requires(actions: 'default')]` + +Koşullar, birden fazla öznitelik listelenerek veya bir araya getirilerek birleştirilebilir: + +```php +#[Requires(methods: 'POST', ajax: true)] +public function actionDelete(int $id) +{ +} + +// or + +#[Requires(methods: 'POST')] +#[Requires(ajax: true)] +public function actionDelete(int $id) +{ +} +``` + + HTTP Yöntem Kontrolü .[#toc-http-method-check] ---------------------------------------------- -Nette'deki sunucular, gelen her isteğin HTTP yöntemini otomatik olarak doğrular. Bu doğrulamanın birincil nedeni güvenliktir. Yöntem kontrolü, istekte belirtilen yöntemin `$presenter->allowedMethods` dizisinde yer alıp almadığını belirleyen `checkHttpMethod()` adresinde gerçekleştirilir. Varsayılan olarak, bu dizi `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH` öğelerini içerir, yani bu yöntemlere izin verilir. +Nette'de sunum yapanlar, öncelikle güvenlik nedenleriyle gelen her isteğin HTTP yöntemini otomatik olarak doğrular. Varsayılan olarak `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH` yöntemlerine izin verilir. + + `OPTIONS` gibi ek yöntemleri etkinleştirmek istiyorsanız `#[Requires]` özniteliği (Nette Uygulaması v3.2'den): + +```php +#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])] +class MyPresenter extends Nette\Application\UI\Presenter +{ +} +``` -Ek olarak `OPTIONS` yöntemine izin vermek isterseniz, bu aşağıdaki şekilde gerçekleştirilebilir: +Sürüm 3.1'de doğrulama, istekte belirtilen yöntemin `$presenter->allowedMethods` dizisine dahil edilip edilmediğini kontrol eden `checkHttpMethod()` içinde gerçekleştirilir. Bunun gibi bir yöntem ekleyin: ```php class MyPresenter extends Nette\Application\UI\Presenter diff --git a/application/uk/configuration.texy b/application/uk/configuration.texy index c6c1fe55bf..3fe82774a3 100644 --- a/application/uk/configuration.texy +++ b/application/uk/configuration.texy @@ -20,6 +20,9 @@ application: # ім'я презентера помилок errorPresenter: Error # (string|array) за замовчуванням 'Nette:Error' + # визначає псевдоніми для доповідачів та подій + aliases: ... + # визначає правила для перетворення імені ведучого в клас mapping: ... @@ -39,6 +42,8 @@ application: Опція `silentLinks` визначає, як Nette поводиться в режимі розробника, коли генерація посилань не вдається (наприклад, через відсутність презентера тощо). Значення за замовчуванням `false` означає, що Nette запускає `E_USER_WARNING`. Встановлення значення `true` пригнічує це повідомлення про помилку. У виробничому середовищі завжди викликається `E_USER_WARNING`. Ми також можемо вплинути на цю поведінку, встановивши змінну презентера [$invalidLinkMode |creating-links#Invalid-Links]. +[Псевдоніми спрощують посилання |creating-links#aliases] на часто використовуваних доповідачів. + Карта [mapping визначає правила |modules#Mapping], за якими ім'я класу виводиться з імені ведучого. diff --git a/application/uk/creating-links.texy b/application/uk/creating-links.texy index 3f605ac54a..5a13a43c77 100644 --- a/application/uk/creating-links.texy +++ b/application/uk/creating-links.texy @@ -223,6 +223,30 @@ $this->getPresenter()->link('Home:default') ``` +Псевдоніми .[#toc-aliases]{data-version:v3.2.2} +=============================================== + +Іноді корисно присвоїти парі доповідач:дія псевдонім, який легко запам'ятовується. Наприклад, ви можете назвати домашню сторінку `Front:Home:default` просто як `home` або `Admin:Dashboard:default` як `admin`. + +Псевдоніми визначаються у [конфігурації |configuration] за допомогою ключа `application › aliases`: + +```neon +application: + aliases: + home: Front:Home:default + admin: Admin:Dashboard:default + sign: Front:Sign:in +``` + +У посиланнях вони пишуться за допомогою символу at, наприклад: + +```latte +administration +``` + +Вони підтримуються у всіх методах, які працюють з посиланнями, таких як `redirect()` та подібних. + + Недійсні посилання .[#toc-invalid-links] ======================================== diff --git a/application/uk/presenters.texy b/application/uk/presenters.texy index d10e79fb17..9f85a0c5cb 100644 --- a/application/uk/presenters.texy +++ b/application/uk/presenters.texy @@ -447,12 +447,62 @@ $this->sendResponse(new Responses\CallbackResponse($callback)); ``` +Обмеження доступу за допомогою `#[Requires]` .[#toc-access-restriction-using-requires]{data-version:3.2.2} +---------------------------------------------------------------------------------------------------------- + +Атрибут `#[Requires]` надає розширені можливості для обмеження доступу до доповідачів та їхніх методів. Його можна використовувати для визначення HTTP-методів, вимагати AJAX-запитів, обмежувати доступ до одного і того ж джерела та обмежувати доступ лише пересиланням. Атрибут можна застосовувати до класів презентера, а також до окремих методів, таких як `action()`, `render()`, `handle()`та `createComponent()`. + +Ось приклад його використання для обмеження доступу лише до методу HTTP `POST`: + +```php +use Nette\Application\Attributes\Requires; + +#[Requires(methods: 'POST')] +class MyPresenter extends Nette\Application\UI\Presenter +{ +} +``` + +Ви можете вказати такі обмеження: +- на HTTP-методи: `#[Requires(methods: ['GET', 'POST'])]` +- що вимагають AJAX-запиту: `#[Requires(ajax: true)]` +- доступ тільки з одного джерела: `#[Requires(sameOrigin: true)]` +- доступ тільки через переадресацію: `#[Requires(forward: true)]` +- обмеження на певні дії: `#[Requires(actions: 'default')]` + +Умови можна комбінувати, перераховуючи кілька атрибутів або об'єднуючи їх в один: + +```php +#[Requires(methods: 'POST', ajax: true)] +public function actionDelete(int $id) +{ +} + +// or + +#[Requires(methods: 'POST')] +#[Requires(ajax: true)] +public function actionDelete(int $id) +{ +} +``` + + Перевірка методу HTTP .[#toc-http-method-check] ----------------------------------------------- -Доповідачі в Nette автоматично перевіряють HTTP-метод кожного вхідного запиту. Основною причиною цієї перевірки є безпека. Перевірка методу здійснюється в `checkHttpMethod()`, де визначається, чи входить вказаний у запиті метод до масиву `$presenter->allowedMethods`. За замовчуванням цей масив містить елементи `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`, що означає, що ці методи дозволені. +У Nette доповідачі автоматично перевіряють HTTP-метод кожного вхідного запиту, головним чином з міркувань безпеки. За замовчуванням дозволені методи `GET`, `POST`, `HEAD`, `PUT`, `DELETE`, `PATCH`. + +Якщо ви хочете увімкнути додаткові методи, такі як `OPTIONS`, ви можете використовувати атрибут `#[Requires]` (починаючи з версії Nette Application v3.2): + +```php +#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])] +class MyPresenter extends Nette\Application\UI\Presenter +{ +} +``` -Якщо ви хочете додатково дозволити метод `OPTIONS`, це можна зробити наступним чином: +У версії 3.1 перевірка виконується в `checkHttpMethod()`, який перевіряє, чи входить вказаний в запиті метод в масив `$presenter->allowedMethods`. Додайте такий метод: ```php class MyPresenter extends Nette\Application\UI\Presenter diff --git a/nette/cs/vulnerability-protection.texy b/nette/cs/vulnerability-protection.texy index fa2d349d49..d5323d3566 100644 --- a/nette/cs/vulnerability-protection.texy +++ b/nette/cs/vulnerability-protection.texy @@ -59,12 +59,12 @@ public function handleXyz() } ``` -V PHP 8 můžete použít také atributy: +V Nette Application 3.2 můžete použít také atributy: ```php -use Nette\Application\Attributes\CrossOrigin; +use Nette\Application\Attributes\Requires; -#[CrossOrigin] +#[Requires(sameOrigin: false)] public function handleXyz() { } diff --git a/nette/en/vulnerability-protection.texy b/nette/en/vulnerability-protection.texy index 0eedf7cade..f5e8f5c88f 100644 --- a/nette/en/vulnerability-protection.texy +++ b/nette/en/vulnerability-protection.texy @@ -59,12 +59,12 @@ public function handleXyz() } ``` -In PHP 8, you can also use attributes: +In Nette Application 3.2 you can also use attributes: ```php -use Nette\Application\Attributes\CrossOrigin; +use Nette\Application\Attributes\Requires; -#[CrossOrigin] +#[Requires(sameOrigin: false)] public function handleXyz() { } From 69ba64b226bc03b7f1211baf9111b77f19e0b4b5 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 18 Apr 2024 22:40:12 +0200 Subject: [PATCH 073/137] nette/application 3.2.3: new directory structure --- application/bg/how-it-works.texy | 25 +++--- application/bg/modules.texy | 128 +++++++++++++++++++----------- application/bg/templates.texy | 84 +++++++++++++++----- application/cs/how-it-works.texy | 25 +++--- application/cs/modules.texy | 118 +++++++++++++++++---------- application/cs/templates.texy | 76 ++++++++++++++---- application/de/how-it-works.texy | 25 +++--- application/de/modules.texy | 132 ++++++++++++++++++++----------- application/de/templates.texy | 84 +++++++++++++++----- application/el/how-it-works.texy | 25 +++--- application/el/modules.texy | 128 +++++++++++++++++++----------- application/el/templates.texy | 84 +++++++++++++++----- application/en/how-it-works.texy | 25 +++--- application/en/modules.texy | 128 +++++++++++++++++++----------- application/en/templates.texy | 84 +++++++++++++++----- application/es/how-it-works.texy | 25 +++--- application/es/modules.texy | 132 ++++++++++++++++++++----------- application/es/templates.texy | 84 +++++++++++++++----- application/fr/how-it-works.texy | 25 +++--- application/fr/modules.texy | 128 +++++++++++++++++++----------- application/fr/templates.texy | 84 +++++++++++++++----- application/hu/how-it-works.texy | 25 +++--- application/hu/modules.texy | 132 ++++++++++++++++++++----------- application/hu/templates.texy | 84 +++++++++++++++----- application/it/how-it-works.texy | 25 +++--- application/it/modules.texy | 126 ++++++++++++++++++----------- application/it/templates.texy | 84 +++++++++++++++----- application/pl/how-it-works.texy | 25 +++--- application/pl/modules.texy | 128 +++++++++++++++++++----------- application/pl/templates.texy | 84 +++++++++++++++----- application/pt/how-it-works.texy | 25 +++--- application/pt/modules.texy | 128 +++++++++++++++++++----------- application/pt/templates.texy | 84 +++++++++++++++----- application/ro/how-it-works.texy | 25 +++--- application/ro/modules.texy | 128 +++++++++++++++++++----------- application/ro/templates.texy | 84 +++++++++++++++----- application/ru/how-it-works.texy | 25 +++--- application/ru/modules.texy | 126 ++++++++++++++++++----------- application/ru/templates.texy | 84 +++++++++++++++----- application/sl/how-it-works.texy | 25 +++--- application/sl/modules.texy | 126 ++++++++++++++++++----------- application/sl/templates.texy | 84 +++++++++++++++----- application/tr/how-it-works.texy | 25 +++--- application/tr/modules.texy | 128 +++++++++++++++++++----------- application/tr/templates.texy | 84 +++++++++++++++----- application/uk/how-it-works.texy | 25 +++--- application/uk/modules.texy | 130 +++++++++++++++++++----------- application/uk/templates.texy | 84 +++++++++++++++----- 48 files changed, 2523 insertions(+), 1259 deletions(-) diff --git a/application/bg/how-it-works.texy b/application/bg/how-it-works.texy index 3cdb0786e2..f005029599 100644 --- a/application/bg/how-it-works.texy +++ b/application/bg/how-it-works.texy @@ -22,13 +22,13 @@ /--pre web-project/ ├── app/ ← каталог с приложением -│ ├── Presenters/ ← классы презентеров -│ │ ├── HomePresenter.php ← Класс презентера главной страницы -│ │ └── templates/ ← директория шаблонов -│ │ ├── @layout.latte ← шаблон общего макета -│ │ └── Home/ ← шаблоны презентера главной страницы -│ │ └── default.latte ← шаблон действия `default` -│ ├── Router/ ← конфигурация URL-адресов +│ ├── Core/ ← основни необходими класове +│ │ └── RouterFactory.php ← конфигуриране на URL адреси +│ ├── Presentation/ ← презентатори, шаблони и др. +│ │ ├── @layout.latte ← шаблон на споделено оформление +│ │ └── Home/ ← Директория за водещи +│ │ ├── HomePresenter.php ← Клас на Home Presenter +│ │ └── default.latte ← шаблон за действие default │ └── Bootstrap.php ← загрузочный класс Bootstrap ├── bin/ ← скрипты командной строки ├── config/ ← файлы конфигурации @@ -91,7 +91,7 @@ Nette е наставник, който ви напътства да пишет Приложението започва с искане към т.нар. маршрутизатор да реши на кой от презентаторите да изпрати текущата заявка за обработка. Маршрутизаторът решава чия е отговорността. Той разглежда входния URL адрес `https://example.com/product/123`, който иска продукт `показать` с `id: 123` като действие. Добър навик е да записвате двойките водещ + действие, разделени с двоеточие: `Продукт:показать`. -Следователно маршрутизаторът е преобразувал URL адреса в двойка `Presenter:action` + параметри, в нашия случай `Product:show` + `id`: 123`. Вы можете увидеть, как выглядит маршрутизатор в файле `app/Router/RouterFactory.php`, и ще го опишем подробно в главата [Маршрутизация |routing]. +Следователно маршрутизаторът е преобразувал URL адреса в двойка `Presenter:action` + параметри, в нашия случай `Product:show` + `id`: 123`. Вы можете увидеть, как выглядит маршрутизатор в файле `app/Core/RouterFactory.php`, и ще го опишем подробно в главата [Маршрутизация |routing]. Да продължим. Приложението вече знае името на водещия и може да продължи. Чрез създаване на обект `ProductPresenter`, който е кодът на предентера `Product`. По-точно, той иска от контейнера DI да създаде презентатора, тъй като създаването на обекти е негова работа. @@ -121,12 +121,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter След това водещият връща отговор. Това може да бъде HTML страница, изображение, XML документ, файл, изпратен от диска, JSON или пренасочване към друга страница. Важно е да се отбележи, че ако не посочим изрично как да се отговори (какъвто е случаят с `ProductPresenter`), отговорът ще бъде шаблон, показващ HTML страница. Защо? Ами защото в 99% от случаите искаме да покажем шаблон, водещият приема това поведение по подразбиране и иска да улесни работата ни. Това е гледната точка на Нете. -Дори не е необходимо да указваме кой шаблон да се покаже, той сам извежда пътя до него според проста логика. В случая с водещия `Product` и действието `show`, той се опитва да провери дали някой от тези файлове с шаблони съществува спрямо директорията, в която се намира класът `ProductPresenter`: +Дори не е необходимо да посочваме кой шаблон да се визуализира; рамката сама ще определи пътя. В случая с действието `show` тя просто се опитва да зареди шаблона `show.latte` в директорията с класа `ProductPresenter`. Тя също така се опитва да намери оформлението във файла `@layout.latte` (повече за [търсенето на шаблони |templates#Template Lookup]). -- `templates/Product/show.latte` -- `templates/Product.show.latte` - -След това се показва шаблонът. Задачата на водещия и на цялото приложение вече е изпълнена. Ако шаблонът не съществува, ще бъде върната страница за грешка 404. Можете да прочетете повече за водещите на страницата [Водещи |presenters]. +Впоследствие шаблоните се визуализират. С това задачата на презентатора и на цялото приложение е изпълнена и работата е приключила. Ако шаблонът не съществува, ще бъде върната страница с грешка 404. Можете да прочетете повече за презентаторите на страницата [Презентатори |presenters]. [* request-flow.svg *] @@ -137,7 +134,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter 3) маршрутизаторът декодира URL адреса като двойка `Home:default` 4) обектът е създаден `HomePresenter` 5) извиква се методът `renderDefault()` (ако съществува) -6) шаблонът `templates/Home/default.latte` с оформлението `templates/@layout.latte` се визуализира +6) шаблонът `default.latte` с оформлението `@layout.latte` се визуализира Може би сега ще се сблъскате с много нови концепции, но ние смятаме, че те имат смисъл. Създаването на приложения в Nette е лесно. diff --git a/application/bg/modules.texy b/application/bg/modules.texy index ddecd3f1a8..fdf7bdfb65 100644 --- a/application/bg/modules.texy +++ b/application/bg/modules.texy @@ -2,29 +2,31 @@ ****** .[perex] -В Nette модулите са логическите единици, от които се състои едно приложение. Те включват главни модули, шаблони, евентуално компоненти и класове модели. +Модулите внасят яснота в приложенията на Nette, като улесняват лесното им разделяне на логически единици. -Един компонент за презентатори и един за шаблони няма да са достатъчни за реални проекти. Натрупването на десетки файлове в една папка е меко казано неорганизирано. Как да излезем от тази ситуация? Просто ги разделяме на поддиректории на диска и на пространства от имена в кода. Точно това правят модулите Nette. - -Така че нека забравим за една папка за презентатори и шаблони и вместо това да създадем модули като `Admin` и `Front`. +Подобно на организирането на файловете в папки на твърдия диск, в Nette можем да разделим презентатори, шаблони и други спомагателни класове на модули. Как работи това на практика? Просто чрез включване на нови поддиректории в структурата. Ето един пример за структура с два модула - Front и Admin: /--pre -app/ -├── Presenters/ -├── Modules/ ← директория с модулями -│ ├── Admin/ ← модуль Admin -│ │ ├── Presenters/ ← его презентеры -│ │ │ ├── DashboardPresenter.php -│ │ │ └── templates/ -│ └── Front/ ← модуль Front -│ └── Presenters/ ← его презентеры -│ └── ... +app/ +├── Presentation/ +│ ├── Admin/ ← Admin module +│ │ ├── @layout.latte +│ │ ├── Dashboard/ +│ │ │ ├── DashboardPresenter.php +│ │ │ └── default.latte +│ │ └── ... +│ ├── Front/ ← Front module +│ │ ├── @layout.latte +│ │ ├── Home/ +│ │ │ ├── HomePresenter.php +│ │ │ └── default.latte +│ │ └── ... \-- -Тази структура на директориите ще бъде отразена в пространствата за имена на класовете, така че например `DashboardPresenter` ще бъде в пространството `App\Modules\Admin\Presenters`: +Тази структура на директориите е отразена в пространствата от имена на класовете, така че например `DashboardPresenter` се намира в пространството от имена `App\Presentation\Admin\Dashboard`: ```php -namespace App\Modules\Admin\Presenters; +namespace App\Presentation\Admin\Dashboard; class DashboardPresenter extends Nette\Application\UI\Presenter { @@ -32,35 +34,49 @@ class DashboardPresenter extends Nette\Application\UI\Presenter } ``` -Главното устройство `Dashboard` в модула `Admin` се обозначава в приложението с помощта на запис с двойна точка като `Admin:Dashboard`, а неговото действие `default` се обозначава като `Admin:Dashboard:default`. -И откъде Nette знае, че `Admin:Dashboard` представлява класа `App\Modules\Admin\Presenters\DashboardPresenter`? Говорим за това, като използваме [картографирането |#Mapping] в конфигурацията. -Така че дадената структура не е фиксирана и можете да я променяте по свое усмотрение. +В приложението се позоваваме на презентатора `Dashboard` в рамките на модула `Admin`, като използваме запис с двоеточие като `Admin:Dashboard`. За неговото действие `default` го наричаме `Admin:Dashboard:default`. -Модулите, разбира се, могат да съдържат всички други части, освен презентатори и шаблони, като компоненти, класове модели и др. +Представената структура не е твърда; в конфигурацията можете [напълно |#mapping] да [я адаптирате към вашите нужди |#mapping]. .[tip] + +Модулите могат да включват всички други файлове, като компоненти и спомагателни класове, в допълнение към презентаторите и шаблоните. Ако обмисляте къде да ги поставите, помислете за използването на папка `Accessory`: + +/--pre +app/ +├── Presentation/ +│ ├── Admin/ +│ │ ├── Accessory/ +│ │ │ ├── FormFactory.php +│ │ │ └── AdminLayout.php +│ │ ├── Dashboard/ +│ │ └── ... +\-- Вложени модули .[#toc-nested-modules] ------------------------------------- -Модулите не трябва да образуват само плоска структура, можете да създавате и подмодули, например: +Модулите могат да имат няколко нива на влагане, подобно на структурата на директориите на диска: /--pre -app/ -├── Modules/ ← директория с модулями -│ ├── Blog/ ← модуль Blog -│ │ ├── Admin/ ← подмодуль Admin -│ │ │ ├── Presenters/ +app/ +├── Presentation/ +│ ├── Blog/ ← Blog module +│ │ ├── Admin/ ← Admin submodule +│ │ │ ├── Dashboard/ +│ │ │ └── ... +│ │ ├── Front/ ← Front submodule +│ │ │ ├── @layout.latte +│ │ │ ├── Home/ │ │ │ └── ... -│ │ └── Front/ ← подмодуль Front -│ │ ├── Presenters/ -│ │ └── ... -│ ├── Forum/ ← модуль Forum +│ ├── Forum/ ← Forum module │ │ └── ... \-- -Така модулът `Blog` се разделя на подмодули `Admin` и `Front`. Това отново ще бъде отразено в пространствата от имена, които ще бъдат `App\Modules\Blog\Admin\Presenters` и т.н. Главният модул `Dashboard` в рамките на подмодула се нарича `Blog:Admin:Dashboard`. +Модулът `Blog` е разделен на подмодули `Admin` и `Front`. Това е отразено и в пространствата от имена, които след това се появяват като `App\Presentation\Blog\Admin` и по подобен начин. За да се позовем на презентатора `Dashboard` в рамките на подмодула `Admin`, го наричаме `Blog:Admin:Dashboard`. -Разклоненията могат да бъдат толкова дълбоки, колкото искате, така че можете да създавате подмодули. +Влагането може да бъде толкова дълбоко, колкото е необходимо, като позволява създаването на подмодули. + +Например, ако в администрацията имате много презентатори, свързани с управлението на поръчки, като `OrderDetail`, `OrderEdit`, `OrderDispatch` и т.н., може да създадете модул `Order`, в който ще бъдат организирани презентатори като `Detail`, `Edit`, `Dispatch` и други. Създаване на връзки .[#toc-creating-links] @@ -102,46 +118,66 @@ class DashboardPresenter extends Nette\Application\UI\Presenter Картографиране .[#toc-mapping] ------------------------------ -Определя правилата, по които името на класа се извежда от главното име. Записваме ги в [конфигурацията |configuration] под ключа `application › mapping`. +Съпоставянето определя правилата за извеждане на името на класа от името на водещия. Тези правила се посочват в [конфигурацията |configuration] под ключа `application › mapping`. + +Структурите на директориите, споменати по-рано на тази страница, се основават на следното съпоставяне: + +```neon +application: + mapping: App\Presentation\*\**Presenter +``` -Нека започнем с пример, при който не се използват модули. Искаме само главните класове да имат пространството от имена `App\Presenters`. Това означава, че искаме главното име, например `Home`, да се съпостави с класа `App\Presenters\HomePresenter`. Това може да се постигне със следната конфигурация: +Как работи картографирането? За по-добро разбиране нека първо си представим приложение без модули. Искаме класовете на презентаторите да попадат в пространството от имена `App\UI`, така че презентаторът `Home` да се съпостави с класа `App\Presentation\HomePresenter`. Това може да се постигне с тази конфигурация: ```neon application: - mapping: App\Presenters\*Presenter + mapping: App\Presentation\*Presenter ``` -Името на водещия се заменя със звездичка и резултатът е името на класа. Лесно! +Това съпоставяне се извършва чрез замяна на звездичката в маската `App\Presentation\*Presenter` с името на презентатора `Home`, в резултат на което се получава крайното име на класа `App\Presentation\HomePresenter`. Просто! + +Въпреки това, както можете да видите в примерите в тази и други глави, ние поставяме класовете на водещите в едноименни поддиректории, например водещият `Home` е картографиран към клас `App\Presentation\Home\HomePresenter`. Това се постига чрез удвояване на звездичката (изисква Nette Application 3.2): + +```neon +application: + mapping: App\Presentation\**Presenter +``` -Ако разделим презентаторите на модули, можем да използваме различни карти за всеки модул: +Сега нека преминем към картографиране на презентатори в модули. Можем да дефинираме специфични съпоставки за всеки модул: ```neon application: mapping: - Front: App\Modules\Front\Presenters\*Presenter - Admin: App\Modules\Admin\Presenters\*Presenter + Front: App\Presentation\Front\**Presenter + Admin: App\Presentation\Admin\**Presenter Api: App\Api\*Presenter ``` -Сега водещият `Front:Home` е определен от класа `App\Modules\Front\HomePresenter`, а презентер `Admin:Dashboard` - `App\AdminModule\DashboardPresenter`. +Според тази конфигурация презентаторът `Front:Home` се съотнася към класа `App\Presentation\Front\Home\HomePresenter`, а презентаторът `Api:OAuth` се съотнася към класа `App\Api\OAuthPresenter`. -Би било по-удобно да се създаде общо правило (звездичка), което да замени първите две правила, и да се добави допълнителна звездичка само за модула: +Тъй като модулите `Front` и `Admin` имат сходен подход на картографиране и вероятно има повече такива модули, е възможно да се създаде общо правило, което да ги замени. Към маската на класа се добавя нова звездичка за модула: ```neon application: mapping: - *: App\Modules\*\Presenters\*Presenter + *: App\Presentation\*\**Presenter Api: App\Api\*Presenter ``` -Но какво става, ако използваме няколко вложени модула и имаме например главен модул `Admin:User:Edit`? В този случай сегментът със звездичка, представляващ модула за всяко ниво, просто ще се повтори и резултатът ще бъде класът `App\Modules\Admin\User\Presenters\EditPresenter`. +За вложени модули на няколко нива, като например водещия `Admin:User:Edit`, сегментът със звездичка се повтаря за всяко ниво, в резултат на което се получава клас `App\Presentation\Admin\User\Edit\EditPresenter`. -Алтернативен начин за записване е използването на масив от три сегмента вместо низ. Този запис е еквивалентен на предишния: +Алтернативен запис е да се използва масив, съставен от три сегмента, вместо низ. Този запис е еквивалентен на предишния: ```neon application: mapping: - *: [App\Modules, *, Presenters\*Presenter] + *: [App\UI, *, **Presenter] + Api: [App\Api, '', *Presenter] ``` -Стойността по подразбиране е `*Module\*Presenter`. +Ако имаме само едно правило в конфигурацията, общото, можем да го напишем накратко: + +```neon +application: + mapping: App\Presentation\*\**Presenter +``` diff --git a/application/bg/templates.texy b/application/bg/templates.texy index 850d3e2ecd..156b2cd541 100644 --- a/application/bg/templates.texy +++ b/application/bg/templates.texy @@ -34,35 +34,81 @@ Nette използва системата за шаблони [Latte |latte:]. L Той дефинира блок `content`, който се вмъква вместо `{include content}` в оформлението, и замества блока `title`, който презаписва `{block title}` в оформлението. Опитайте се да си представите резултата. -Търсене на шаблони .[#toc-search-for-templates] ------------------------------------------------ +Търсене на шаблони .[#toc-template-lookup] +------------------------------------------ + +В презентаторите не е необходимо да посочвате кой шаблон трябва да бъде визуализиран; рамката автоматично ще определи пътя, което ще ви улесни при кодирането. + +Ако използвате структура от директории, в която всеки презентатор има своя собствена директория, просто поставете шаблона в тази директория под името на действието (т.е. изглед). Например, за действието `default` използвайте шаблона `default.latte`: -Пътят към шаблоните се определя от главния модул с помощта на проста логика. Той ще се опита да провери дали има някой от тези файлове, разположен спрямо главната директория на класа, където `` е името на текущия главен модул, а `` е името на текущото събитие: +/--pre +app/ +└── Presentation/ + └── Home/ + ├── HomePresenter.php + └── default.latte +\-- -- `templates//.latte` -- `templates/..latte` +Ако използвате структура, в която презентаторите са заедно в една директория, а шаблоните - в папка `templates`, запишете я или във файл `..latte` или `/.latte`: -Ако шаблонът не бъде намерен, ще се опита да търси в директорията `templates` едно ниво по-нагоре, т.е. на същото ниво като директорията с класа на водещия. +/--pre +app/ +└── Presenters/ + ├── HomePresenter.php + └── templates/ + ├── Home.default.latte ← 1st variant + └── Home/ + └── default.latte ← 2nd variant +\-- -Ако шаблонът не бъде намерен и там, отговорът ще бъде [грешка 404 |presenters#Error 404 etc.]. +Директорията `templates` може да бъде поставена и едно ниво по-нагоре, на същото ниво като директорията с класовете на водещите. -Можете също така да промените изгледа с помощта на `$this->setView('jineView')`. Или вместо да търсите директно, посочете името на файла с шаблона, като използвате `$this->template->setFile('/path/to/template.latte')`. +Ако шаблонът не бъде намерен, презентаторът отговаря с [грешка 404 - страница не е намерена |presenters#Error 404 etc]. + +Можете да промените изгледа, като използвате `$this->setView('anotherView')`. Възможно е също така директно да посочите файла с шаблона с помощта на `$this->template->setFile('/path/to/template.latte')`. .[note] -Файловете, които се търсят за шаблони, могат да се променят чрез наслагване на метода [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()], който връща масив от възможни имена на файлове. +Файловете, в които се търсят шаблони, могат да се променят чрез надграждане на метода [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()], който връща масив от възможни имена на файлове. + + +Търсене на шаблони за оформление .[#toc-layout-template-lookup] +--------------------------------------------------------------- + +Nette също така автоматично търси файла с оформлението. + +Ако използвате структура на директориите, в която всеки водещ има своя собствена директория, поставете макета или в папката с водещия, ако е специфичен само за него, или на по-високо ниво, ако е общ за няколко водещи: + +/--pre +app/ +└── Presentation/ + ├── @layout.latte ← common layout + └── Home/ + ├── @layout.latte ← only for Home presenter + ├── HomePresenter.php + └── default.latte +\-- + +Ако използвате структура, в която презентаторите са групирани в една директория, а шаблоните са в папка `templates`, макетът ще се очаква на следните места: -В тези файлове се очаква оформление: +/--pre +app/ +└── Presenters/ + ├── HomePresenter.php + └── templates/ + ├── @layout.latte ← common layout + ├── Home.@layout.latte ← only for Home, 1st variant + └── Home/ + └── @layout.latte ← only for Home, 2nd variant +\-- -- `templates//@.latte` -- `templates/.@.latte` -- `templates/@.latte` Разположение, общо за няколко високоговорителя +Ако презентаторът е в [модул |modules], той ще търси и по-нагоре в дървото на директориите според вложеността на модула. -Къде: `` е името на текущия водещ, а `` е името на оформлението, което по подразбиране е `'layout'`. Името може да бъде променено с помощта на `$this->setLayout('jinyLayout')`, така че ще бъдат изпробвани файлове `@jinyLayout.latte`. +Името на макета може да бъде променено с помощта на `$this->setLayout('layoutAdmin')` и тогава то ще бъде очаквано във файла `@layoutAdmin.latte`. Можете също така директно да посочите файла с шаблона на оформлението, като използвате `$this->setLayout('/path/to/template.latte')`. -Можете също така директно да посочите името на файла на шаблона за оформление, като използвате `$this->setLayout('/path/to/template.latte')`. Използването на `$this->setLayout(false)` деактивира проследяването на оформлението. +Използването на `$this->setLayout(false)` или на тага `{layout none}` вътре в шаблона деактивира търсенето на оформление. .[note] -Файловете, в които се търсят шаблоните за оформление, могат да се променят чрез наслагване на метода [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], който връща масив от възможни имена на файлове. +Файловете, в които се търсят шаблони за оформление, могат да бъдат променяни чрез надграждане на метода [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], който връща масив от възможни имена на файлове. Променливи в шаблона .[#toc-variables-in-the-template] @@ -104,7 +150,7 @@ class ArticleTemplate extends Nette\Bridges\ApplicationLatte\Template Можете също така да си позволите лукса да шепнете в шаблоните, просто инсталирайте плъгина Latte в PhpStorm и поставете името на класа в началото на шаблона, за повече информация вижте статията "Latte: как да въведем системата":https://blog.nette.org/bg/latte-kak-da-izpolzvame-sistemata-ot-tipove: ```latte -{templateType App\Presenters\ArticleTemplate} +{templateType App\Presentation\Article\ArticleTemplate} ... ``` @@ -176,7 +222,7 @@ public function beforeRender(): void Версия 3 на Latte предлага по-усъвършенстван начин за създаване на [разширение за |latte:creating-extension] всеки уеб проект. Ето кратък пример за такъв клас: ```php -namespace App\Templating; +namespace App\Presentation\Accessory; final class LatteExtension extends Latte\Extension { @@ -214,7 +260,7 @@ final class LatteExtension extends Latte\Extension ```neon latte: extensions: - - App\Templating\LatteExtension + - App\Presentation\Accessory\LatteExtension ``` diff --git a/application/cs/how-it-works.texy b/application/cs/how-it-works.texy index 92ff5e9d9b..4c4266d339 100644 --- a/application/cs/how-it-works.texy +++ b/application/cs/how-it-works.texy @@ -22,13 +22,13 @@ Adresářová struktura vypadá nějak takto: /--pre web-project/ ├── app/ ← adresář s aplikací -│ ├── Presenters/ ← presentery a šablony -│ │ ├── HomePresenter.php ← třída presenteru Home -│ │ └── templates/ ← adresář se šablonami -│ │ ├── @layout.latte ← šablona layoutu -│ │ └── Home/ ← šablony presenteru Home -│ │ └── default.latte ← šablona akce 'default' -│ ├── Router/ ← konfigurace URL adres +│ ├── Core/ ← základní třídy nutné pro chod +│ │ └── RouterFactory.php ← konfigurace URL adres +│ ├── Presentation/ ← presentery, šablony & spol. +│ │ ├── @layout.latte ← šablona layoutu +│ │ └── Home/ ← adresář presenteru Home +│ │ ├── HomePresenter.php ← třída presenteru Home +│ │ └── default.latte ← šablona akce default │ └── Bootstrap.php ← zaváděcí třída Bootstrap ├── bin/ ← skripty spouštěné z příkazové řádky ├── config/ ← konfigurační soubory @@ -91,7 +91,7 @@ Aplikace psané v Nette se člení do spousty tzv. presenterů (v jiných framew Application začne tím, že požádá tzv. router, aby rozhodl, kterému z presenterů předat aktuální požadavek k vyřízení. Router rozhodne, čí je to zodpovědnost. Podívá se na vstupní URL `https://example.com/product/123` a na základě toho, jak je nastavený, rozhodne, že tohle je práce např. pro **presenter** `Product`, po kterém bude chtít jako **akci** zobrazení (`show`) produktu s `id: 123`. Dvojici presenter + akce je dobrým zvykem zapisovat oddělené dvojtečkou jako `Product:show`. -Tedy router transformoval URL na dvojici `Presenter:action` + parametry, v našem případě `Product:show` + `id: 123`. Jak takový router vypadá se můžete podívat v souboru `app/Router/RouterFactory.php` a podrobně ho popisujeme v kapitole [Routing]. +Tedy router transformoval URL na dvojici `Presenter:action` + parametry, v našem případě `Product:show` + `id: 123`. Jak takový router vypadá se můžete podívat v souboru `app/Core/RouterFactory.php` a podrobně ho popisujeme v kapitole [Routing]. Pojďme dál. Application už zná jméno presenteru a může pokračovat dál. Tím že vyrobí objekt třídy `ProductPresenter`, což je kód presenteru `Product`. Přesněji řečeno, požádá DI kontejner, aby presenter vyrobil, protože od vyrábění je tu on. @@ -121,12 +121,9 @@ Takže, zavolala se metoda `renderShow(123)`, jejíž kód je sice smyšlený p Následně presenter vrátí odpověď. Tou může být HTML stránka, obrázek, XML dokument, odeslání souboru z disku, JSON nebo třeba přesměrování na jinou stránku. Důležité je, že pokud explicitně neřekneme, jak má odpovědět (což je případ `ProductPresenter`), bude odpovědí vykreslení šablony s HTML stránkou. Proč? Protože v 99 % případů chceme vykreslit šablonu, tudíž presenter tohle chování bere jako výchozí a chce nám ulehčit práci. To je smyslem Nette. -Nemusíme ani uvádět, jakou šablonu vykreslit, cestu k ní si odvodí podle jednoduché logiky. V případě presenteru `Product` a akce `show` zkusí, zda existuje jeden z těchto souborů se šablonou uložených relativně od adresáře s třídou `ProductPresenter`: +Nemusíme ani uvádět, jakou šablonu vykreslit, cestu k ní si odvodí sám. V případě akce `show` jednodušše zkusí načíst šablonu `show.latte` v adresáři s třídou `ProductPresenter`. Taktéž se pokusí dohledat layout v souboru `@layout.latte` (podrobněji o [dohledávání šablon|templates#hledani-sablon]). -- `templates/Product/show.latte` -- `templates/Product.show.latte` - -Taktéž se pokusí dohledat layout v souboru `@layout.latte` a následně šablonu vykreslí. Tím je úkol presenteru i celé aplikace dokonán a dílo jest završeno. Pokud by šablona neexistovala, vrátí se stránka s chybou 404. Více se o presenterech dočtete na stránce [Presentery|presenters]. +A následně šablony vykreslí. Tím je úkol presenteru i celé aplikace dokonán a dílo jest završeno. Pokud by šablona neexistovala, vrátí se stránka s chybou 404. Více se o presenterech dočtete na stránce [Presentery|presenters]. [* request-flow.svg *] @@ -137,7 +134,7 @@ Pro jistotu, zkusme si zrekapitulovat celý proces s trošku jinou URL: 3) router URL dekóduje jako dvojici `Home:default` 4) vytvoří se objekt třídy `HomePresenter` 5) zavolá se metoda `renderDefault()` (pokud existuje) -6) vykreslí se šablona např. `templates/Home/default.latte` s layoutem např. `templates/@layout.latte` +6) vykreslí se šablona např. `default.latte` s layoutem např. `@layout.latte` Možná jste se teď setkali s velkou spoustou nových pojmů, ale věříme, že dávají smysl. Tvorba aplikací v Nette je ohromná pohodička. diff --git a/application/cs/modules.texy b/application/cs/modules.texy index dd58b910d4..e0cae4dee9 100644 --- a/application/cs/modules.texy +++ b/application/cs/modules.texy @@ -2,29 +2,31 @@ Moduly ****** .[perex] -Moduly představují v Nette logické celky, ze kterých se aplikace skládá. Jejich součástí jsou presentery, šablony, případně i komponenty a modelové třídy. +Moduly vnášejí do Nette aplikací přehlednost díky snadnému členění do logických celků. -S jednou složkou pro presentery a jednou pro šablony bychom si u reálných projektů nevystačili. Mít v jedné složce desítky souborů je minimálně nepřehledné. Jak z toho ven? Jednoduše je na disku rozdělíme do podadresářů a v kódu do jmenných prostorů. A přesně to jsou v Nette moduly. - -Zapomeňme tedy na jednu složku pro presentery a šablony a místo toho vytvoříme moduly, například `Admin` a `Front`. +Podobně jako na pevném disku organizujeme soubory do jednotlivých složek, tak i v Nette můžeme presentery, šablony a další pomocné třídy rozdělovat do modulů. Jak to funguje v praxi? Jednoduše začleníme do struktury nové podadresáře. Příklad takové struktury se dvěma moduly Front a Admin: /--pre -app/ -├── Presenters/ -├── Modules/ ← adresář s moduly +app/ +├── Presentation/ │ ├── Admin/ ← modul Admin -│ │ ├── Presenters/ ← jeho presentery -│ │ │ ├── DashboardPresenter.php -│ │ │ └── templates/ -│ └── Front/ ← modul Front -│ └── Presenters/ ← jeho presentery -│ └── ... +│ │ ├── @layout.latte +│ │ ├── Dashboard/ +│ │ │ ├── DashboardPresenter.php +│ │ │ └── default.latte +│ │ └── ... +│ ├── Front/ ← modul Front +│ │ ├── @layout.latte +│ │ ├── Home/ +│ │ │ ├── HomePresenter.php +│ │ │ └── default.latte +│ │ └── ... \-- -Tuto adresářovou strukturu budou reflektovat jmenné prostory tříd, takže třeba `DashboardPresenter` bude v prostoru `App\Modules\Admin\Presenters`: +Tato adresářová struktura se odráží ve jmenných prostorech tříd, takže například `DashboardPresenter` se nachází ve jmenném prostoru `App\Presentation\Admin\Dashboard`: ```php -namespace App\Modules\Admin\Presenters; +namespace App\Presentation\Admin\Dashboard; class DashboardPresenter extends Nette\Application\UI\Presenter { @@ -32,35 +34,49 @@ class DashboardPresenter extends Nette\Application\UI\Presenter } ``` -Na presenter `Dashboard` uvnitř modulu `Admin` se v rámci aplikace odkazujeme pomocí dvojtečkové notace jako na `Admin:Dashboard`, na jeho akci `default` potom jako na `Admin:Dashboard:default`. -A jak Nette vlastní ví, že `Admin:Dashboard` představuje třídu `App\Modules\Admin\Presenters\DashboardPresenter`? To mu řekneme pomocí [#mapování] v konfiguraci. -Tedy uvedená struktura není pevná a můžete si ji upravit podle potřeb. +Na presenter `Dashboard` uvnitř modulu `Admin` odkazujeme v aplikaci pomocí dvojtečkové notace jako na `Admin:Dashboard`. Na jeho akci `default` potom jako na `Admin:Dashboard:default`. -Moduly mohou kromě presenterů a šablon samozřejmě obsahovat všechny další součásti, jako jsou třeba komponenty, modelové třídy, atd. +Představená struktura není pevná; můžete si ji zcela [přizpůsobit dle svých potřeb|#mapování] v konfiguraci. .[tip] + +Moduly mohou kromě presenterů a šablon samozřejmě zahrnovat všechny ostatní soubory, jako jsou například komponenty a pomocné třídy. Pokud uvažujete, kam je zařadit, zvažte využití složky `Accessory`: + +/--pre +app/ +├── Presentation/ +│ ├── Admin/ +│ │ ├── Accessory/ +│ │ │ ├── FormFactory.php +│ │ │ └── AdminLayout.php +│ │ ├── Dashboard/ +│ │ └── ... +\-- Vnořené moduly -------------- -Moduly nemusí tvořit jen plochou strukturu, lze vytvářet i submoduly, například: +Moduly mohou mít více úrovní zanoření, podobně jako adresářová struktura na disku: /--pre -app/ -├── Modules/ ← adresář s moduly +app/ +├── Presentation/ │ ├── Blog/ ← modul Blog │ │ ├── Admin/ ← submodul Admin -│ │ │ ├── Presenters/ +│ │ │ ├── Dashboard/ +│ │ │ └── ... +│ │ ├── Front/ ← submodul Front +│ │ │ ├── @layout.latte +│ │ │ ├── Home/ │ │ │ └── ... -│ │ └── Front/ ← submodul Front -│ │ ├── Presenters/ -│ │ └── ... │ ├── Forum/ ← modul Forum │ │ └── ... \-- -Tedy modul `Blog` je rozdělen do submodulů `Admin` a `Front`. A opět se to odrazí na jmenných prostorech, které budou `App\Modules\Blog\Admin\Presenters` apod. Na presenter `Dashboard` uvnitř submodulu se odkazujeme jako `Blog:Admin:Dashboard`. +Modul `Blog` je rozdělen na submoduly `Admin` a `Front`. To se projeví i ve jmenných prostorech, které pak budou vypadat jako `App\Presentation\Blog\Admin` a podobně. Na presenter `Dashboard` v rámci submodulu odkazujeme jako na `Blog:Admin:Dashboard`. -Zanořování může pokračovat libovolně hluboko, lze tedy vytvářet sub-submoduly. +Zanoření může být libovolně hluboké, což umožňuje vytvářet sub-submoduly. + +Pokud například v administraci máte mnoho presenterů týkajících se správy objednávek, jako jsou `OrderDetail`, `OrderEdit`, `OrderDispatch` atd., můžete pro lepší organizovanost vytvořit modul `Order`, ve kterém budou presentery `Detail`, `Edit`, `Dispatch` a další. Vytváření odkazů @@ -102,46 +118,66 @@ Viz [kapitola o routování |routing#Moduly]. Mapování -------- -Definuje pravidla, podle kterých se z názvu presenteru odvodí název třídy. Zapisujeme je v [konfiguraci|configuration] pod klíčem `application › mapping`. +Mapování definuje pravidla pro odvozování názvu třídy z názvu presenteru. Specifikujeme je v [konfiguraci|configuration] pod klíčem `application › mapping`. + +Adresářové struktury uváděné výše na této stránce vycházejí z tohoto mapování: + +```neon +application: + mapping: App\Presentation\*\**Presenter +``` -Začněme ukázkou, která moduly nepoužívá. Budeme jen chtít, aby třídy presenterů měly jmenný prostor `App\Presenters`. Tedy aby se presenter například `Home` mapoval na třídu `App\Presenters\HomePresenter`. Toho lze docílit následující konfigurací: +Jak mapování funguje? Pro lepší pochopení si nejprve představme aplikaci bez modulů. Chceme, aby třídy presenterů spadaly do jmenného prostoru `App\UI`, aby se presenter `Home` mapoval na třídu `App\Presentation\HomePresenter`. Což dosáhneme touto konfigurací: ```neon application: - mapping: App\Presenters\*Presenter + mapping: App\Presentation\*Presenter ``` -Název presenteru se nahradí za hvezdičku v masce třídy a výsledkem je název třídy. Snadné! +Mapování funguje tak, že název presenteru `Home` nahradí hvězdičku v masce `App\Presentation\*Presenter`, čímž získáme výsledný název třídy `App\Presentation\HomePresenter`. Jednoduché! + +Jak ale vidíte v ukázkách v této a dalších kapitolách, třídy presenterů umisťujeme do eponymních podadresářů, například presenter `Home` se mapuje na třídu `App\Presentation\Home\HomePresenter`. Toho dosáhneme zdvojením dvojtečky (vyžaduje Nette Application 3.2): + +```neon +application: + mapping: App\Presentation\**Presenter +``` -Pokud presentery členíme do modulů, můžeme pro každý modul mít vlastní mapování: +Nyní přistoupíme k mapování presenterů do modulů. Pro každý modul můžeme definovat specifické mapování: ```neon application: mapping: - Front: App\Modules\Front\Presenters\*Presenter - Admin: App\Modules\Admin\Presenters\*Presenter + Front: App\Presentation\Front\**Presenter + Admin: App\Presentation\Admin\**Presenter Api: App\Api\*Presenter ``` -Nyní se presenter `Front:Home` mapuje na třídu `App\Modules\Front\Presenters\HomePresenter` a presenter `Admin:Dashboard` na třídu `App\Modules\Admin\Presenters\DashboardPresenter`. +Podle této konfigurace se presenter `Front:Home` mapuje na třídu `App\Presentation\Front\Home\HomePresenter`, zatímco presenter `Api:OAuth` na třídu `App\Api\OAuthPresenter`. -Praktičtější bude vytvořit obecné (hvězdičkové) pravidlo, které první dvě nahradí. V masce třídy přibude hvezdička navíc právě pro modul: +Protože moduly `Front` i `Admin` mají podobný způsob mapování a takových modulů bude nejspíš více, je možné vytvořit obecné pravidlo, které je nahradí. Do masky třídy tak přibude nová hvězdička pro modul: ```neon application: mapping: - *: App\Modules\*\Presenters\*Presenter + *: App\Presentation\*\**Presenter Api: App\Api\*Presenter ``` -Ale co když používáme vícenásobně zanořené moduly a máme třeba presenter `Admin:User:Edit`? V takovém případě se segment s hvězdičkou představující modul pro každou úroveň jednoduše zopakuje a výsledkem bude třída `App\Modules\Admin\User\Presenters\EditPresenter`. +Pro vícenásobně zanořené moduly, jako je například presenter `Admin:User:Edit`, se segment s hvězdičkou opakuje pro každou úroveň a výsledkem je třída `App\Presentation\Admin\User\Edit\EditPresenter`. Alternativním zápisem je místo řetězce použít pole skládající se ze tří segmentů. Tento zápis je ekvivaletní s předchozím: ```neon application: mapping: - *: [App\Modules, *, Presenters\*Presenter] + *: [App\UI, *, **Presenter] + Api: [App\Api, '', *Presenter] ``` -Výchozí hodnotou je `*Module\*Presenter`. +Pokud bychom měli v konfiguraci jen jediné pravidlo, ono obecné, můžeme zkráceně zapsat: + +```neon +application: + mapping: App\Presentation\*\**Presenter +``` diff --git a/application/cs/templates.texy b/application/cs/templates.texy index 5d0de8dc1a..fe54200c7f 100644 --- a/application/cs/templates.texy +++ b/application/cs/templates.texy @@ -37,29 +37,75 @@ Ta definuje blok `content`, který se vloží na místo `{include content}` v la Hledání šablon -------------- -Cestu k šablonám odvodí presenter podle jednoduché logiky. Zkusí, zda existuje jeden z těchto souborů umístěných relativně od adresáře s třídou presenteru, kde `` je název aktuálního presenteru a `` je název aktuální akce: +Nemusíte v presenterech uvádět, jaká šablona se má vykreslit, framework cestu odvodí sám a ušetří vám psaní. -- `templates//.latte` -- `templates/..latte` +Pokud používáte adresářovou strukturu, kde každý presenter má vlastní adresář, jednodušše umístěte šablonu do tohoto adresáře pod jménem akce (resp. view), tj. pro akci `default` použijte šablonu `default.latte`: -Pokud šablonu nenajde, zkusí hledat ještě v adresáři `templates` o úroveň výš, tj. na stejné úrovni, jako je adresář s třídou presenteru. +/--pre +app/ +└── Presentation/ + └── Home/ + ├── HomePresenter.php + └── default.latte +\-- -Pokud ani tam šablonu nenajde, je odpovědí [chyba 404|presenters#Chyba 404 a spol.]. +Pokud používáte strukturu, kde jsou společně presentery v jednom adresáři a šablony ve složce `templates`, uložte ji buď do souboru `..latte` nebo `/.latte`: -Můžete také změnit view pomocí `$this->setView('jineView')`. Nebo místo dohledávání přímo určit jméno souboru se šablonou pomocí `$this->template->setFile('/path/to/template.latte')`. +/--pre +app/ +└── Presenters/ + ├── HomePresenter.php + └── templates/ + ├── Home.default.latte ← 1. varianta + └── Home/ + └── default.latte ← 2. varianta +\-- + +Adresář `templates` může být umístěn také o úroveň výš, tj. na stejné úrovni, jako je adresář s třídami presenterů. + +Pokud se šablona nenajde, presenter odpoví [chybou 404 - page not found|presenters#Chyba 404 a spol]. + +View změníte pomocí `$this->setView('jineView')`. Také lze přímo určit soubor se šablonou pomocí `$this->template->setFile('/path/to/template.latte')`. .[note] Soubory, kde se dohledávají šablony, lze změnit překrytím metody [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()], která vrací pole možných názvů souborů. -Layout se očekává v těchto souborech: -- `templates//@.latte` -- `templates/.@.latte` -- `templates/@.latte` layout společný pro více presenterů +Hledání šablony layoutu +----------------------- + +Nette také automaticky dohledává soubor s layoutem. + +Pokud používáte adresářovou strukturu, kde každý presenter má vlastní adresář, umístěte layout buď do složky s presenterem, pokud je specifický jen pro něj, nebo o úroveň výš, pokud je společný pro více presenterů: + +/--pre +app/ +└── Presentation/ + ├── @layout.latte ← společný layout + └── Home/ + ├── @layout.latte ← jen pro presenter Home + ├── HomePresenter.php + └── default.latte +\-- + +Pokud používáte strukturu, kde jsou společně presentery v jednom adresáři a šablony ve složce `templates`, bude se layout očekávat na těchto místech: + +/--pre +app/ +└── Presenters/ + ├── HomePresenter.php + └── templates/ + ├── @layout.latte ← společný layout + ├── Home.@layout.latte ← jen pro Home, 1. varianta + └── Home/ + └── @layout.latte ← jen pro Home, 2. varianta +\-- + +Pokud se presenter nachází v [modulu|modules], bude se dohledávat i o další adresářové úrovně výš, podle zanoření modulu. -Kde `` je název aktuálního presenteru a `` je název layoutu, což je standardně `'layout'`. Název lze změnit pomocí `$this->setLayout('jinyLayout')`, takže se budou zkoušet soubory `@jinyLayout.latte`. +Název layoutu lze změnit pomocí `$this->setLayout('layoutAdmin')` a pak se bude očekávat v souboru `@layoutAdmin.latte`. Také lze přímo určit soubor se šablonou layoutu pomocí `$this->setLayout('/path/to/template.latte')`. -Můžete také přímo určit jméno souboru se šablonou layoutu pomocí `$this->setLayout('/path/to/template.latte')`. Pomocí `$this->setLayout(false)` se dohledávání layoutu vypne. +Pomocí `$this->setLayout(false)` nebo značky `{layout none}` uvnitř šablony se dohledávání layoutu vypne. .[note] Soubory, kde se dohledávají šablony layoutu, lze změnit překrytím metody [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], která vrací pole možných názvů souborů. @@ -104,7 +150,7 @@ Anotace `@property-read` je určená pro IDE a statickou analýzu, díky ní bud 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: ```latte -{templateType App\Presenters\ArticleTemplate} +{templateType App\Presentation\Article\ArticleTemplate} ... ``` @@ -176,7 +222,7 @@ public function beforeRender(): void 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: ```php -namespace App\Templating; +namespace App\Presentation\Accessory; final class LatteExtension extends Latte\Extension { @@ -214,7 +260,7 @@ Zaregistrujeme ji pomocí [konfigurace |configuration#Šablony Latte]: ```neon latte: extensions: - - App\Templating\LatteExtension + - App\Presentation\Accessory\LatteExtension ``` diff --git a/application/de/how-it-works.texy b/application/de/how-it-works.texy index 010ba04907..caa51fc7a3 100644 --- a/application/de/how-it-works.texy +++ b/application/de/how-it-works.texy @@ -22,13 +22,13 @@ Die Verzeichnisstruktur sieht in etwa so aus: /--pre web-project/ ├── app/ ← Verzeichnis mit Anwendung -│ ├── Presenters/ ← Presenter-Klassen -│ │ ├── HomePresenter.php ← Home presenterklasse -│ │ └── templates/ ← Vorlagenverzeichnis -│ │ ├── @layout.latte ← Vorlage für gemeinsames Layout -│ │ └── Home/ ← Vorlagen für Home-presenter -│ │ └── default.latte ← Vorlage für Aktion `default` -│ ├── Router/ ← Konfiguration von URL-Adressen +│ ├── Core/ ← grundlegende notwendige Klassen +│ │ └── RouterFactory.php ← Konfiguration der URL-Adressen +│ ├── Presentation/ ← Moderatoren, Vorlagen & Co. +│ │ ├── @layout.latte ← Vorlage für gemeinsames Layout +│ │ └── Home/ ← Home Presenter Verzeichnis +│ │ ├── HomePresenter.php ← Home Presenter Klasse +│ │ └── default.latte ← Vorlage für Aktion default │ └── Bootstrap.php ← bootende Klasse Bootstrap ├── bin/ ← Skripte für die Kommandozeile ├── config/ ← Konfigurationsdateien @@ -91,7 +91,7 @@ In Nette geschriebene Anwendungen sind in viele so genannte Presenter unterteilt Die Anwendung beginnt damit, dass sie den so genannten Router bittet, zu entscheiden, an welchen der Presenter die aktuelle Anfrage zur Bearbeitung weitergeleitet werden soll. Der Router entscheidet, wer dafür zuständig ist. Er sieht sich die Eingabe-URL `https://example.com/product/123` handelt, der ein Produkt mit `id: 123` als Aktion an `show` weiterleiten möchte. Es ist eine gute Angewohnheit, ein durch einen Doppelpunkt getrenntes Paar aus Präsentator + Aktion als `Product:show` zu schreiben. -Der Router verwandelt also die URL in ein Paar `Presenter:action` + Parameter, in unserem Fall `Product:show` + `id: 123`. Sie können sehen, wie ein Router in der Datei `app/Router/RouterFactory.php` aussieht, und wir werden ihn im Kapitel [Routing] ausführlich beschreiben. +Der Router verwandelt also die URL in ein Paar `Presenter:action` + Parameter, in unserem Fall `Product:show` + `id: 123`. Sie können sehen, wie ein Router in der Datei `app/Core/RouterFactory.php` aussieht, und wir werden ihn im Kapitel [Routing] ausführlich beschreiben. Machen wir weiter. Die Anwendung kennt bereits den Namen des Präsentators und kann fortfahren. Sie erstellt ein Objekt `ProductPresenter`, das den Code des Presenters `Product` darstellt. Genauer gesagt, sie bittet den DI-Container um die Erstellung des Presenters, denn die Erstellung von Objekten ist seine Aufgabe. @@ -121,12 +121,9 @@ So wurde die Methode `renderShow(123)` aufgerufen, deren Code ein fiktives Beisp Anschließend gibt der Präsentator die Antwort zurück. Dies kann eine HTML-Seite, ein Bild, ein XML-Dokument, das Senden einer Datei von der Festplatte, JSON oder die Routing zu einer anderen Seite sein. Wichtig ist, dass, wenn wir nicht ausdrücklich sagen, wie zu antworten ist (was bei `ProductPresenter` der Fall ist), die Antwort darin besteht, die Vorlage mit einer HTML-Seite wiederzugeben. Und warum? Nun, weil wir in 99 % der Fälle eine Vorlage zeichnen wollen, so dass der Präsentator dieses Verhalten als Standard annimmt und uns die Arbeit erleichtern will. Das ist der Punkt von Nette. -Wir müssen nicht einmal angeben, welche Vorlage gezeichnet werden soll, er leitet den Pfad dorthin nach einer einfachen Logik ab. Im Fall von presenter `Product` und action `show` versucht er zu sehen, ob eine dieser Vorlagendateien relativ zu dem Verzeichnis existiert, in dem sich die Klasse `ProductPresenter` befindet: +Wir müssen nicht einmal angeben, welche Vorlage gerendert werden soll; das Framework wird den Pfad selbst ermitteln. Im Fall der Aktion `show` versucht es einfach, die Vorlage `show.latte` im Verzeichnis mit der Klasse `ProductPresenter` zu laden. Es versucht auch, das Layout in der Datei `@layout.latte` zu finden (mehr über die [Vorlagensuche |templates#Template Lookup]). -- `templates/Product/show.latte` -- `templates/Product.show.latte` - -Außerdem wird versucht, das Layout in der Datei `@layout.latte` zu finden, und dann wird die Vorlage gerendert. Nun ist die Aufgabe des Präsentators und der gesamten Anwendung abgeschlossen. Wenn die Vorlage nicht existiert, wird eine Seite mit dem Fehler 404 zurückgegeben. Weitere Informationen über Präsentatoren finden Sie auf der Seite [Präsentatoren |Presenters]. +Anschließend werden die Vorlagen gerendert. Damit ist die Aufgabe des Präsentators und der gesamten Anwendung abgeschlossen, und die Arbeit ist getan. Wenn die Vorlage nicht vorhanden wäre, würde eine 404-Fehlerseite zurückgegeben werden. Weitere Informationen über Präsentatoren finden Sie auf der Seite [Präsentatoren |presenters]. [* request-flow.svg *] @@ -137,7 +134,7 @@ Um sicherzugehen, versuchen wir, den gesamten Prozess mit einer etwas anderen UR 3) der Router dekodiert die URL als ein Paar `Home:default` 4) ein `HomePresenter` Objekt wird erstellt 5) die Methode `renderDefault()` wird aufgerufen (falls vorhanden) -6) eine Vorlage `templates/Home/default.latte` mit einem Layout `templates/@layout.latte` wird gerendert +6) eine Vorlage `default.latte` mit einem Layout `@layout.latte` wird gerendert Vielleicht sind Sie jetzt auf eine Menge neuer Konzepte gestoßen, aber wir glauben, dass sie sinnvoll sind. Das Erstellen von Anwendungen in Nette ist ein Kinderspiel. diff --git a/application/de/modules.texy b/application/de/modules.texy index 090bd4702e..5c17ea2975 100644 --- a/application/de/modules.texy +++ b/application/de/modules.texy @@ -2,29 +2,31 @@ Module ****** .[perex] -In Nette stellen Module die logischen Einheiten dar, aus denen eine Anwendung besteht. Sie umfassen Presenter, Templates, eventuell auch Komponenten und Modellklassen. +Module bringen Klarheit in Nette-Anwendungen, indem sie eine einfache Unterteilung in logische Einheiten ermöglichen. -Ein Verzeichnis für Presenter und eines für Templates würde für echte Projekte nicht ausreichen. Dutzende von Dateien in einem Ordner zu haben, ist zumindest unorganisiert. Wie kommt man da wieder raus? Wir teilen sie einfach in Unterverzeichnisse auf der Festplatte und in Namensräume im Code auf. Und das ist genau das, was die Nette-Module tun. - -Vergessen wir also einen einzigen Ordner für Präsentatoren und Vorlagen und erstellen wir stattdessen Module, zum Beispiel `Admin` und `Front`. +Ähnlich wie bei der Organisation von Dateien in Ordnern auf einer Festplatte, können wir in Nette Presenter, Vorlagen und andere Hilfsklassen in Module unterteilen. Wie funktioniert das in der Praxis? Ganz einfach, indem man neue Unterverzeichnisse in die Struktur einfügt. Hier ist ein Beispiel für eine Struktur mit zwei Modulen, Front und Admin: /--pre -app/ -├── Presenters/ -├── Modules/ ← Verzeichnis mit Modulen -│ ├── Admin/ ← Modul Admin -│ │ ├── Presenters/ ← seine Presenters -│ │ │ ├── DashboardPresenter.php -│ │ │ └── templates/ -│ └── Front/ ← Modul Front -│ └── Presenters/ ← seine Presenters -│ └── ... +app/ +├── Presentation/ +│ ├── Admin/ ← Admin module +│ │ ├── @layout.latte +│ │ ├── Dashboard/ +│ │ │ ├── DashboardPresenter.php +│ │ │ └── default.latte +│ │ └── ... +│ ├── Front/ ← Front module +│ │ ├── @layout.latte +│ │ ├── Home/ +│ │ │ ├── HomePresenter.php +│ │ │ └── default.latte +│ │ └── ... \-- -Diese Verzeichnisstruktur spiegelt sich in den Klassennamensräumen wider, so dass z. B. `DashboardPresenter` im Namensraum `App\Modules\Admin\Presenters` liegt: +Diese Verzeichnisstruktur spiegelt sich in den Namespaces der Klassen wider, so befindet sich z.B. `DashboardPresenter` im Namespace `App\Presentation\Admin\Dashboard`: ```php -namespace App\Modules\Admin\Presenters; +namespace App\Presentation\Admin\Dashboard; class DashboardPresenter extends Nette\Application\UI\Presenter { @@ -32,35 +34,49 @@ class DashboardPresenter extends Nette\Application\UI\Presenter } ``` -Der Präsentator `Dashboard` innerhalb des Moduls `Admin` wird innerhalb der Anwendung mit der Doppelpunktschreibweise als `Admin:Dashboard` referenziert, und seine Aktion `default` als `Admin:Dashboard:default`. -Und woher weiß Nette selbst, dass `Admin:Dashboard` die Klasse `App\Modules\Admin\Presenters\DashboardPresenter` repräsentiert? Dies wird durch ein [Mapping |#mapping] in der Konfiguration festgelegt. -Die vorgegebene Struktur ist also nicht fest vorgegeben und kann nach Belieben verändert werden. +In der Anwendung wird der Presenter `Dashboard` innerhalb des Moduls `Admin` mit Doppelpunkt als `Admin:Dashboard` bezeichnet. Für die Aktion `default` wird er als `Admin:Dashboard:default` bezeichnet. -Module können neben Presentern und Templates natürlich auch alle anderen Elemente enthalten, wie z.B. Komponenten, Modellklassen, etc. +Die vorgestellte Struktur ist nicht starr; Sie können [sie |#mapping] in der Konfiguration [vollständig an Ihre Bedürfnisse anpassen |#mapping]. .[tip] + +Module können neben Presentern und Vorlagen auch alle anderen Dateien, wie Komponenten und Hilfsklassen, enthalten. Wenn Sie überlegen, wo Sie diese ablegen wollen, sollten Sie einen Ordner `Accessory` verwenden: + +/--pre +app/ +├── Presentation/ +│ ├── Admin/ +│ │ ├── Accessory/ +│ │ │ ├── FormFactory.php +│ │ │ └── AdminLayout.php +│ │ ├── Dashboard/ +│ │ └── ... +\-- Verschachtelte Module .[#toc-nested-modules] -------------------------------------------- -Module müssen nicht nur eine flache Struktur bilden, Sie können auch Untermodule erstellen, zum Beispiel: +Module können mehrere Verschachtelungsebenen haben, ähnlich wie eine Verzeichnisstruktur auf einer Festplatte: /--pre -app/ -├── Modules/ ← Verzeichnis mit Modulen -│ ├── Blog/ ← Modul Blog -│ │ ├── Admin/ ← Submodul Admin -│ │ │ ├── Presenters/ +app/ +├── Presentation/ +│ ├── Blog/ ← Blog module +│ │ ├── Admin/ ← Admin submodule +│ │ │ ├── Dashboard/ +│ │ │ └── ... +│ │ ├── Front/ ← Front submodule +│ │ │ ├── @layout.latte +│ │ │ ├── Home/ │ │ │ └── ... -│ │ └── Front/ ← Submodul Front -│ │ ├── Presenters/ -│ │ └── ... -│ ├── Forum/ ← Modul Forum +│ ├── Forum/ ← Forum module │ │ └── ... \-- -So wird das Modul `Blog` in die Untermodule `Admin` und `Front` aufgeteilt. Dies spiegelt sich auch in den Namensräumen wider, die dann `App\Modules\Blog\Admin\Presenters` usw. lauten. Der Präsentator `Dashboard` innerhalb des Submoduls wird als `Blog:Admin:Dashboard` bezeichnet. +Das Modul `Blog` ist in die Untermodule `Admin` und `Front` unterteilt. Dies spiegelt sich auch in den Namespaces wider, die dann als `App\Presentation\Blog\Admin` und ähnlich erscheinen. Um auf den Präsentator `Dashboard` innerhalb des Submoduls `Admin` zu verweisen, wird er als `Blog:Admin:Dashboard` bezeichnet. -Die Verschachtelung kann beliebig tief gehen, so dass Sub-Submodule erstellt werden können. +Die Verschachtelung kann so tief wie nötig sein und erlaubt die Erstellung von Sub-Submodulen. + +Wenn Sie zum Beispiel in der Verwaltung viele Präsentatoren haben, die mit der Auftragsverwaltung zusammenhängen, wie `OrderDetail`, `OrderEdit`, `OrderDispatch`, usw., könnten Sie ein `Order` Modul erstellen, in dem Präsentatoren wie `Detail`, `Edit`, `Dispatch` und andere organisiert werden. Erstellen von Links .[#toc-creating-links] @@ -99,49 +115,69 @@ Routing .[#toc-routing] Siehe [Kapitel über Routing |routing#Modules]. -Abbildung .[#toc-mapping] -------------------------- +Kartierung .[#toc-mapping] +-------------------------- + +Mapping definiert die Regeln für die Ableitung des Klassennamens aus dem Presenter-Namen. Diese Regeln werden in der [Konfiguration |configuration] unter dem Schlüssel `application › mapping` angegeben. + +Die oben auf dieser Seite erwähnten Verzeichnisstrukturen basieren auf der folgenden Zuordnung: -Legt die Regeln fest, nach denen der Klassenname aus dem Namen des Präsentators abgeleitet wird. Wir schreiben sie in die [Konfiguration |configuration] unter dem Schlüssel `application › mapping`. +```neon +application: + mapping: App\Presentation\*\**Presenter +``` -Beginnen wir mit einem Beispiel, das keine Module verwendet. Wir wollen nur, dass die Presenter-Klassen den Namespace `App\Presenters` haben. Das bedeutet, dass ein Presenter wie `Home` auf die Klasse `App\Presenters\HomePresenter` abgebildet werden soll. Dies kann durch die folgende Konfiguration erreicht werden: +Wie funktioniert das Mapping? Zum besseren Verständnis stellen wir uns zunächst eine Anwendung ohne Module vor. Wir wollen, dass die Presenter-Klassen in den Namensraum `App\UI` fallen, so dass der Presenter `Home` auf die Klasse `App\Presentation\HomePresenter` abgebildet wird. Dies kann mit dieser Konfiguration erreicht werden: ```neon application: - mapping: App\Presenters\*Presenter + mapping: App\Presentation\*Presenter ``` -Der Name des Presenters wird durch das Sternchen in der Klassenmaske ersetzt und das Ergebnis ist der Klassenname. Einfach! +Diese Zuordnung funktioniert, indem das Sternchen in der Maske `App\Presentation\*Presenter` durch den Presenter-Namen `Home` ersetzt wird, was zu dem endgültigen Klassennamen `App\Presentation\HomePresenter` führt. Einfach! + +Wie Sie jedoch in den Beispielen in diesem und anderen Kapiteln sehen können, platzieren wir Presenter-Klassen in gleichnamigen Unterverzeichnissen, z. B. wird der Presenter `Home` der Klasse `App\Presentation\Home\HomePresenter` zugeordnet. Dies wird durch die Verdoppelung des Sternchens erreicht (erfordert Nette Application 3.2): + +```neon +application: + mapping: App\Presentation\**Presenter +``` -Wenn wir die Vortragenden in Module unterteilen, können wir für jedes Modul eine eigene Zuordnung vornehmen: +Gehen wir nun dazu über, Presenter in Modulen abzubilden. Für jedes Modul können wir spezifische Zuordnungen definieren: ```neon application: mapping: - Front: App\Modules\Front\Presenters\*Presenter - Admin: App\Modules\Admin\Presenters\*Presenter + Front: App\Presentation\Front\**Presenter + Admin: App\Presentation\Admin\**Presenter Api: App\Api\*Presenter ``` -Der Referent `Front:Home` wird der Klasse `App\Modules\Front\Presenters\HomePresenter` zugeordnet und der Referent `Admin:Dashboard` der Klasse `App\Modules\Admin\Presenters\DashboardPresenter`. +Nach dieser Konfiguration wird der Präsentator `Front:Home` der Klasse `App\Presentation\Front\Home\HomePresenter` zugeordnet, während der Präsentator `Api:OAuth` der Klasse `App\Api\OAuthPresenter` zugeordnet wird. -Es ist praktischer, eine allgemeine (Stern-)Regel zu erstellen, um die ersten beiden zu ersetzen. Das zusätzliche Sternchen wird der Klassenmaske nur für dieses Modul hinzugefügt: +Da die Module `Front` und `Admin` einen ähnlichen Zuordnungsansatz haben und es wahrscheinlich noch mehr solcher Module gibt, ist es möglich, eine allgemeine Regel zu erstellen, die sie ersetzt. In der Klassenmaske wird ein neues Sternchen für das Modul hinzugefügt: ```neon application: mapping: - *: App\Modules\*\Presenters\*Presenter + *: App\Presentation\*\**Presenter Api: App\Api\*Presenter ``` -Was aber, wenn wir verschachtelte Module verwenden und einen Präsentator `Admin:User:Edit` haben? In diesem Fall wird das Segment mit dem Sternchen, das das Modul für jede Ebene darstellt, einfach wiederholt und das Ergebnis ist die Klasse `App\Modules\Admin\User\Presenters\EditPresenter`. +Bei mehrstufig verschachtelten Modulen, wie z. B. dem Moderator `Admin:User:Edit`, wird das Sternchen-Segment für jede Stufe wiederholt, was zu der Klasse `App\Presentation\Admin\User\Edit\EditPresenter` führt. -Eine alternative Schreibweise ist die Verwendung eines Arrays, das aus drei Segmenten anstelle einer Zeichenkette besteht. Diese Notation ist gleichwertig mit der vorherigen: +Eine alternative Schreibweise ist die Verwendung eines Arrays, das aus drei Segmenten besteht, anstelle einer Zeichenkette. Diese Notation ist äquivalent zur vorherigen: ```neon application: mapping: - *: [App\Modules, *, Presenters\*Presenter] + *: [App\UI, *, **Presenter] + Api: [App\Api, '', *Presenter] ``` -Der Standardwert ist `*Module\*Presenter`. +Wenn wir nur eine Regel in der Konfiguration haben, die allgemeine, können wir kurz schreiben: + +```neon +application: + mapping: App\Presentation\*\**Presenter +``` diff --git a/application/de/templates.texy b/application/de/templates.texy index a21bd7266f..319de261a4 100644 --- a/application/de/templates.texy +++ b/application/de/templates.texy @@ -34,35 +34,81 @@ Und dies könnte die Aktionsvorlage sein: Sie definiert den Block `content`, der anstelle von `{include content}` in das Layout eingefügt wird, und definiert auch den Block `title` neu, der `{block title}` im Layout überschreibt. Versuchen Sie, sich das Ergebnis vorzustellen. -Suche nach Templates .[#toc-search-for-templates] -------------------------------------------------- +Vorlage nachschlagen .[#toc-template-lookup] +-------------------------------------------- + +In Presentern müssen Sie nicht angeben, welche Vorlage gerendert werden soll; das Framework bestimmt den Pfad automatisch, was die Codierung für Sie einfacher macht. + +Wenn Sie eine Verzeichnisstruktur verwenden, in der jeder Präsentator sein eigenes Verzeichnis hat, legen Sie die Vorlage einfach in diesem Verzeichnis unter dem Namen der Aktion (d. h. der Ansicht) ab. Verwenden Sie zum Beispiel für die Aktion `default` die Vorlage `default.latte`: -Der Pfad zu den Vorlagen wird nach einer einfachen Logik hergeleitet. Es wird versucht zu sehen, ob eine dieser Vorlagendateien relativ zu dem Verzeichnis existiert, in dem sich die Presenter-Klasse befindet, wobei `` der Name des aktuellen Präsentators ist und `` der Name der aktuellen Aktion ist: +/--pre +app/ +└── Presentation/ + └── Home/ + ├── HomePresenter.php + └── default.latte +\-- -- `templates//.latte` -- `templates/..latte` +Wenn Sie eine Struktur verwenden, bei der sich die Präsentatoren in einem Verzeichnis und die Vorlagen in einem Ordner `templates` befinden, speichern Sie sie entweder in einer Datei `..latte` oder `/.latte`: -Wird die Vorlage nicht gefunden, wird versucht, im Verzeichnis `templates` eine Ebene höher zu suchen, d. h. auf der gleichen Ebene wie das Verzeichnis mit der Presenter-Klasse. +/--pre +app/ +└── Presenters/ + ├── HomePresenter.php + └── templates/ + ├── Home.default.latte ← 1st variant + └── Home/ + └── default.latte ← 2nd variant +\-- -Wenn die Vorlage auch dort nicht gefunden wird, ist die Antwort ein [404-Fehler |presenters#Error 404 etc.]. +Das Verzeichnis `templates` kann auch eine Ebene höher platziert werden, auf derselben Ebene wie das Verzeichnis mit den Presenter-Klassen. -Sie können die Ansicht auch mit `$this->setView('otherView')` ändern. Oder geben Sie statt der Suche direkt den Namen der Vorlagendatei mit `$this->template->setFile('/path/to/template.latte')` an. +Wenn die Vorlage nicht gefunden wird, antwortet der Präsentator mit dem [Fehler 404 - Seite nicht gefunden |presenters#Error 404 etc]. + +Sie können die Ansicht mit `$this->setView('anotherView')` ändern. Es ist auch möglich, die Vorlagendatei direkt mit `$this->template->setFile('/path/to/template.latte')` anzugeben. .[note] -Sie können die Pfade, in denen Vorlagen gesucht werden, ändern, indem Sie die Methode [formatTemplateFiles |api:Nette\Application\UI\Presenter::formatTemplateFiles()] überschreiben, die ein Array mit möglichen Dateipfaden zurückgibt. +Dateien, in denen Vorlagen gesucht werden, können durch Überschreiben der Methode [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()] geändert werden, die ein Array mit möglichen Dateinamen zurückgibt. + + +Layout-Vorlagen-Suche .[#toc-layout-template-lookup] +---------------------------------------------------- + +Nette sucht auch automatisch nach der Layout-Datei. + +Wenn Sie eine Verzeichnisstruktur verwenden, in der jeder Präsentator sein eigenes Verzeichnis hat, legen Sie das Layout entweder in dem Ordner mit dem Präsentator ab, wenn es nur für diesen spezifisch ist, oder eine Ebene höher, wenn es für mehrere Präsentatoren gemeinsam ist: + +/--pre +app/ +└── Presentation/ + ├── @layout.latte ← common layout + └── Home/ + ├── @layout.latte ← only for Home presenter + ├── HomePresenter.php + └── default.latte +\-- + +Wenn Sie eine Struktur verwenden, bei der die Vortragenden in einem Verzeichnis zusammengefasst sind und sich die Vorlagen in einem Ordner `templates` befinden, wird das Layout an den folgenden Stellen erwartet: -Das Layout wird in den folgenden Dateien erwartet: +/--pre +app/ +└── Presenters/ + ├── HomePresenter.php + └── templates/ + ├── @layout.latte ← common layout + ├── Home.@layout.latte ← only for Home, 1st variant + └── Home/ + └── @layout.latte ← only for Home, 2nd variant +\-- -- `templates//@.latte` -- `templates/.@.latte` -- `templates/@.latte` gemeinsames Layout für mehrere Präsentatoren +Befindet sich der Präsentator in einem [Modul |modules], wird er auch weiter oben im Verzeichnisbaum entsprechend der Verschachtelung des Moduls gesucht. -`` ist der Name des aktuellen Präsentators und `` ist der Name des Layouts, der standardmäßig `'layout'` lautet. Der Name kann mit `$this->setLayout('otherLayout')` geändert werden, so dass `@otherLayout.latte` Dateien ausprobiert werden. +Der Name des Layouts kann mit `$this->setLayout('layoutAdmin')` geändert werden und wird dann in der Datei `@layoutAdmin.latte` erwartet. Sie können die Layout-Vorlagendatei auch direkt mit `$this->setLayout('/path/to/template.latte')` angeben. -Sie können auch direkt den Dateinamen der Layoutvorlage mit `$this->setLayout('/path/to/template.latte')` angeben. Durch die Verwendung von `$this->setLayout(false)` wird die Layout-Suche deaktiviert. +Die Verwendung von `$this->setLayout(false)` oder des Tags `{layout none}` innerhalb der Vorlage deaktiviert die Layout-Suche. .[note] -Sie können die Pfade, in denen Vorlagen gesucht werden, ändern, indem Sie die Methode [formatLayoutTemplateFiles |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()] überschreiben, die ein Array mit möglichen Dateipfaden zurückgibt. +Die Dateien, in denen Layoutvorlagen gesucht werden, können durch Überschreiben der Methode [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()] geändert werden, die ein Array mit möglichen Dateinamen zurückgibt. Variablen in der Vorlage .[#toc-variables-in-the-template] @@ -104,7 +150,7 @@ Die `@property-read` Annotation ist für die IDE und die statische Analyse, sie Sie können sich auch den Luxus gönnen, in Vorlagen zu flüstern. Installieren Sie einfach das Latte-Plugin in PhpStorm und geben Sie den Klassennamen am Anfang der Vorlage an, siehe den Artikel "Latte: how to type system":https://blog.nette.org/de/latte-wie-benutzt-man-das-typensystem: ```latte -{templateType App\Presenters\ArticleTemplate} +{templateType App\Presentation\Article\ArticleTemplate} ... ``` @@ -176,7 +222,7 @@ public function beforeRender(): void Latte Version 3 bietet einen fortgeschritteneren Weg, indem es eine [Erweiterung |latte:creating-extension] für jedes Webprojekt erstellt. Hier ist ein grobes Beispiel für eine solche Klasse: ```php -namespace App\Templating; +namespace App\Presentation\Accessory; final class LatteExtension extends Latte\Extension { @@ -214,7 +260,7 @@ Wir registrieren sie mit [configuration |configuration#Latte]: ```neon latte: extensions: - - App\Templating\LatteExtension + - App\Presentation\Accessory\LatteExtension ``` diff --git a/application/el/how-it-works.texy b/application/el/how-it-works.texy index f7a4be0a0b..df02f8e113 100644 --- a/application/el/how-it-works.texy +++ b/application/el/how-it-works.texy @@ -22,13 +22,13 @@ /--pre web-project/ ├── app/ ← directory with application -│ ├── Presenters/ ← presenter classes -│ │ ├── HomePresenter.php ← Home presenter class -│ │ └── templates/ ← templates directory -│ │ ├── @layout.latte ← template of shared layout -│ │ └── Home/ ← templates for Home presenter -│ │ └── default.latte ← template for action `default` -│ ├── Router/ ← configuration of URL addresses +│ ├── Core/ ← βασικές αναγκαίες τάξεις +│ │ └── RouterFactory.php ← διαμόρφωση των διευθύνσεων URL +│ ├── Presentation/ ← παρουσιαστές, πρότυπα και λοιπά. +│ │ ├── @layout.latte ← πρότυπο κοινής διάταξης +│ │ └── Home/ ← Αρχικός κατάλογος παρουσιαστών +│ │ ├── HomePresenter.php ← Κλάση οικιακού παρουσιαστή +│ │ └── default.latte ← πρότυπο για τη δράση default │ └── Bootstrap.php ← booting class Bootstrap ├── bin/ ← scripts for the command line ├── config/ ← configuration files @@ -91,7 +91,7 @@ composer create-project nette/web-project Η εφαρμογή ξεκινά ζητώντας από τον λεγόμενο δρομολογητή να αποφασίσει ποιος από τους παρουσιαστές θα περάσει το τρέχον αίτημα για επεξεργασία. Ο δρομολογητής αποφασίζει ποιανού ευθύνη είναι. Κοιτάζει τη διεύθυνση URL εισόδου `https://example.com/product/123`, ο οποίος θέλει να `show` ένα προϊόν με `id: 123` ως ενέργεια. Είναι καλή συνήθεια να γράφετε τα ζεύγη παρουσιαστής + δράση χωρισμένα με άνω και κάτω τελεία ως `Product:show`. -Έτσι, ο δρομολογητής μετατρέπει τη διεύθυνση URL σε ένα ζεύγος `Presenter:action` + παράμετροι, στην περίπτωσή μας `Product:show` + `id: 123`. Μπορείτε να δείτε πώς μοιάζει ένας δρομολογητής στο αρχείο `app/Router/RouterFactory.php` και θα τον περιγράψουμε αναλυτικά στο κεφάλαιο [Δρομολόγηση |Routing]. +Έτσι, ο δρομολογητής μετατρέπει τη διεύθυνση URL σε ένα ζεύγος `Presenter:action` + παράμετροι, στην περίπτωσή μας `Product:show` + `id: 123`. Μπορείτε να δείτε πώς μοιάζει ένας δρομολογητής στο αρχείο `app/Core/RouterFactory.php` και θα τον περιγράψουμε αναλυτικά στο κεφάλαιο [Δρομολόγηση |Routing]. Ας συνεχίσουμε. Η εφαρμογή γνωρίζει ήδη το όνομα του παρουσιαστή και μπορεί να συνεχίσει. Δημιουργώντας ένα αντικείμενο `ProductPresenter`, το οποίο είναι ο κώδικας του παρουσιαστή `Product`. Πιο συγκεκριμένα, ζητάει από το DI container τη δημιουργία του presenter, επειδή η παραγωγή αντικειμένων είναι η δουλειά του. @@ -121,12 +121,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter Στη συνέχεια, ο παρουσιαστής επιστρέφει την απάντηση. Αυτό μπορεί να είναι μια σελίδα HTML, μια εικόνα, ένα έγγραφο XML, η αποστολή ενός αρχείου από το δίσκο, JSON ή η ανακατεύθυνση σε μια άλλη σελίδα. Σημαντικό είναι ότι, αν δεν πούμε ρητά πώς να απαντήσουμε (κάτι που συμβαίνει στην περίπτωση του `ProductPresenter`), η απάντηση θα είναι η απόδοση του προτύπου με μια σελίδα HTML. Γιατί; Λοιπόν, επειδή στο 99% των περιπτώσεων θέλουμε να σχεδιάσουμε ένα πρότυπο, οπότε ο παρουσιαστής θεωρεί αυτή τη συμπεριφορά ως προεπιλεγμένη και θέλει να διευκολύνει τη δουλειά μας. Αυτό είναι το νόημα της Nette. -Δεν χρειάζεται καν να δηλώσουμε ποιο πρότυπο θέλουμε να σχεδιάσουμε, αυτός εξάγει τη διαδρομή προς αυτό σύμφωνα με απλή λογική. Στην περίπτωση του presenter `Product` και της δράσης `show`, προσπαθεί να δει αν ένα από αυτά τα αρχεία προτύπων υπάρχει σε σχέση με τον κατάλογο όπου βρίσκεται η κλάση `ProductPresenter`: +Δεν χρειάζεται καν να καθορίσουμε ποιο πρότυπο θα αναπαραχθεί- το πλαίσιο θα βρει μόνο του τη διαδρομή. Στην περίπτωση της ενέργειας `show`, απλώς προσπαθεί να φορτώσει το πρότυπο `show.latte` στον κατάλογο με την κλάση `ProductPresenter`. Προσπαθεί επίσης να βρει τη διάταξη στο αρχείο `@layout.latte` (περισσότερα για την [αναζήτηση προτύπων |templates#Template Lookup]). -- `templates/Product/show.latte` -- `templates/Product.show.latte` - -Θα προσπαθήσει επίσης να βρει τη διάταξη στο αρχείο `@layout.latte` και στη συνέχεια θα αποδώσει το πρότυπο. Τώρα ολοκληρώνεται η εργασία του παρουσιαστή και ολόκληρης της εφαρμογής. Εάν το πρότυπο δεν υπάρχει, θα επιστραφεί μια σελίδα με σφάλμα 404. Μπορείτε να διαβάσετε περισσότερα για τους παρουσιαστές στη σελίδα [Παρουσιαστές |Presenters]. +Στη συνέχεια, τα πρότυπα αποδίδονται. Με αυτόν τον τρόπο ολοκληρώνεται η εργασία του παρουσιαστή και ολόκληρης της εφαρμογής, και η εργασία έχει τελειώσει. Εάν το πρότυπο δεν υπήρχε, θα επιστρεφόταν μια σελίδα σφάλματος 404. Μπορείτε να διαβάσετε περισσότερα για τους παρουσιαστές στη σελίδα [Παρουσιαστές |presenters]. [* request-flow.svg *] @@ -137,7 +134,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter 3) ο δρομολογητής αποκωδικοποιεί τη διεύθυνση URL ως ζεύγος `Home:default` 4) δημιουργείται ένα αντικείμενο `HomePresenter` 5) καλείται η μέθοδος `renderDefault()` (αν υπάρχει) -6) αποδίδεται ένα πρότυπο `templates/Home/default.latte` με διάταξη `templates/@layout.latte` +6) αποδίδεται ένα πρότυπο `default.latte` με διάταξη `@layout.latte` Μπορεί να έχετε συναντήσει πολλές νέες έννοιες τώρα, αλλά πιστεύουμε ότι βγάζουν νόημα. Η δημιουργία εφαρμογών στη Nette είναι πανεύκολη. diff --git a/application/el/modules.texy b/application/el/modules.texy index 3277cccce0..1983e3fa4f 100644 --- a/application/el/modules.texy +++ b/application/el/modules.texy @@ -2,29 +2,31 @@ ******** .[perex] -Στη Nette, οι ενότητες αντιπροσωπεύουν τις λογικές μονάδες που συνθέτουν μια εφαρμογή. Περιλαμβάνουν παρουσιαστές, πρότυπα, ενδεχομένως επίσης συστατικά και κλάσεις μοντέλων. +Οι ενότητες φέρνουν σαφήνεια στις εφαρμογές Nette διευκολύνοντας τον εύκολο διαχωρισμό σε λογικές μονάδες. -Ένας κατάλογος για τους παρουσιαστές και ένας για τα πρότυπα δεν θα ήταν αρκετός για πραγματικά έργα. Το να έχετε δεκάδες αρχεία σε έναν φάκελο είναι τουλάχιστον ανοργάνωτο. Πώς να απαλλαγείτε από αυτό; Απλώς τα χωρίζουμε σε υποκαταλόγους στο δίσκο και σε χώρους ονομάτων στον κώδικα. Και αυτό ακριβώς κάνουν τα modules της Nette. - -Ας ξεχάσουμε λοιπόν έναν ενιαίο φάκελο για τους παρουσιαστές και τα πρότυπα και ας δημιουργήσουμε αντ' αυτού ενότητες, για παράδειγμα `Admin` και `Front`. +Παρόμοια με την οργάνωση των αρχείων σε φακέλους σε ένα σκληρό δίσκο, στη Nette μπορούμε να χωρίσουμε τους παρουσιαστές, τα πρότυπα και άλλες βοηθητικές κλάσεις σε ενότητες. Πώς λειτουργεί αυτό στην πράξη; Απλά με την ενσωμάτωση νέων υποκαταλόγων στη δομή. Ακολουθεί ένα παράδειγμα δομής με δύο ενότητες, Front και Admin: /--pre -app/ -├── Presenters/ -├── Modules/ ← directory with modules -│ ├── Admin/ ← module Admin -│ │ ├── Presenters/ ← its presenters -│ │ │ ├── DashboardPresenter.php -│ │ │ └── templates/ -│ └── Front/ ← module Front -│ └── Presenters/ ← its presenters -│ └── ... +app/ +├── Presentation/ +│ ├── Admin/ ← Admin module +│ │ ├── @layout.latte +│ │ ├── Dashboard/ +│ │ │ ├── DashboardPresenter.php +│ │ │ └── default.latte +│ │ └── ... +│ ├── Front/ ← Front module +│ │ ├── @layout.latte +│ │ ├── Home/ +│ │ │ ├── HomePresenter.php +│ │ │ └── default.latte +│ │ └── ... \-- -Αυτή η δομή καταλόγου θα αντικατοπτρίζεται από τα namespaces των κλάσεων, έτσι για παράδειγμα το `DashboardPresenter` θα βρίσκεται στο namespace `App\Modules\Admin\Presenters`: +Αυτή η δομή καταλόγου αντικατοπτρίζεται στα namespaces των κλάσεων, έτσι για παράδειγμα, η `DashboardPresenter` βρίσκεται στο namespace `App\Presentation\Admin\Dashboard`: ```php -namespace App\Modules\Admin\Presenters; +namespace App\Presentation\Admin\Dashboard; class DashboardPresenter extends Nette\Application\UI\Presenter { @@ -32,35 +34,49 @@ class DashboardPresenter extends Nette\Application\UI\Presenter } ``` -Ο παρουσιαστής `Dashboard` μέσα στην ενότητα `Admin` αναφέρεται μέσα στην εφαρμογή χρησιμοποιώντας τον συμβολισμό της άνω και κάτω τελείας ως `Admin:Dashboard`, και η ενέργεια `default` ως `Admin:Dashboard:default`. -Και πώς γνωρίζει η Nette proper ότι το `Admin:Dashboard` αντιπροσωπεύει την κλάση `App\Modules\Admin\Presenters\DashboardPresenter`; Αυτό καθορίζεται από την [αντιστοίχιση |#mapping] στη διαμόρφωση. -Έτσι, η δεδομένη δομή δεν είναι αυστηρά καθορισμένη και μπορείτε να την τροποποιήσετε ανάλογα με τις ανάγκες σας. +Στην εφαρμογή, αναφερόμαστε στον παρουσιαστή `Dashboard` μέσα στην ενότητα `Admin` χρησιμοποιώντας τον συμβολισμό της άνω και κάτω τελείας ως `Admin:Dashboard`. Για τη δράση του `default`, αναφερόμαστε σε αυτόν ως `Admin:Dashboard:default`. -Οι ενότητες μπορούν φυσικά να περιέχουν όλα τα άλλα στοιχεία εκτός από τους παρουσιαστές και τα πρότυπα, όπως συστατικά, κλάσεις μοντέλων κ.λπ. +Η δομή που παρουσιάζεται δεν είναι άκαμπτη- μπορείτε να [την προσαρμόσετε πλήρως στις ανάγκες σας |#mapping] στη διαμόρφωση. .[tip] + +Οι ενότητες μπορούν να περιλαμβάνουν όλα τα άλλα αρχεία, όπως συστατικά και βοηθητικές κλάσεις, εκτός από τους παρουσιαστές και τα πρότυπα. Αν σκέφτεστε πού να τα τοποθετήσετε αυτά, σκεφτείτε να χρησιμοποιήσετε έναν φάκελο `Accessory`: + +/--pre +app/ +├── Presentation/ +│ ├── Admin/ +│ │ ├── Accessory/ +│ │ │ ├── FormFactory.php +│ │ │ └── AdminLayout.php +│ │ ├── Dashboard/ +│ │ └── ... +\-- Ενσωματωμένες ενότητες .[#toc-nested-modules] --------------------------------------------- -Οι ενότητες δεν χρειάζεται να σχηματίζουν μόνο μια επίπεδη δομή, μπορείτε επίσης να δημιουργήσετε υποενότητες, για παράδειγμα: +Οι ενότητες μπορούν να έχουν πολλαπλά επίπεδα ένθεσης, παρόμοια με μια δομή καταλόγου σε ένα δίσκο: /--pre -app/ -├── Modules/ ← directory with modules -│ ├── Blog/ ← module Blog -│ │ ├── Admin/ ← submodule Admin -│ │ │ ├── Presenters/ +app/ +├── Presentation/ +│ ├── Blog/ ← Blog module +│ │ ├── Admin/ ← Admin submodule +│ │ │ ├── Dashboard/ +│ │ │ └── ... +│ │ ├── Front/ ← Front submodule +│ │ │ ├── @layout.latte +│ │ │ ├── Home/ │ │ │ └── ... -│ │ └── Front/ ← submodule Front -│ │ ├── Presenters/ -│ │ └── ... -│ ├── Forum/ ← module Forum +│ ├── Forum/ ← Forum module │ │ └── ... \-- -Έτσι, η ενότητα `Blog` χωρίζεται σε υποενότητες `Admin` και `Front`. Και πάλι, αυτό θα αντικατοπτρίζεται στα namespaces, τα οποία θα είναι `App\Modules\Blog\Admin\Presenters` κ.λπ. Ο παρουσιαστής `Dashboard` μέσα στην υποενότητα αναφέρεται ως `Blog:Admin:Dashboard`. +Η ενότητα `Blog` χωρίζεται σε υποενότητες `Admin` και `Front`. Αυτό αντικατοπτρίζεται επίσης στα namespaces, τα οποία εμφανίζονται ως `App\Presentation\Blog\Admin` και παρόμοια. Για να αναφερθούμε στον παρουσιαστή `Dashboard` μέσα στην υποενότητα `Admin`, αναφερόμαστε σε αυτόν ως `Blog:Admin:Dashboard`. -Η ένθεση μπορεί να προχωρήσει όσο βαθιά θέλετε, οπότε μπορούν να δημιουργηθούν υπο-υποενότητες. +Η φωλεοποίηση μπορεί να είναι όσο βαθιά χρειάζεται, επιτρέποντας τη δημιουργία υπο-υπομονάδων. + +Για παράδειγμα, αν στη διαχείριση έχετε πολλούς παρουσιαστές που σχετίζονται με τη διαχείριση παραγγελιών, όπως `OrderDetail`, `OrderEdit`, `OrderDispatch`, κ.λπ., μπορείτε να δημιουργήσετε μια ενότητα `Order` στην οποία θα οργανωθούν παρουσιαστές όπως `Detail`, `Edit`, `Dispatch` και άλλοι. Δημιουργία συνδέσμων .[#toc-creating-links] @@ -102,46 +118,66 @@ class DashboardPresenter extends Nette\Application\UI\Presenter Χαρτογράφηση .[#toc-mapping] ---------------------------- -Καθορίζει τους κανόνες με τους οποίους το όνομα της κλάσης προκύπτει από το όνομα του παρουσιαστή. Τους γράφουμε στη [διαμόρφωση |configuration] κάτω από το κλειδί `application › mapping`. +Η αντιστοίχιση ορίζει τους κανόνες για την εξαγωγή του ονόματος της κλάσης από το όνομα του παρουσιαστή. Οι κανόνες αυτοί καθορίζονται στη [διαμόρφωση |configuration] στο κλειδί `application › mapping`. + +Οι δομές καταλόγων που αναφέρθηκαν νωρίτερα σε αυτή τη σελίδα βασίζονται στην ακόλουθη αντιστοίχιση: + +```neon +application: + mapping: App\Presentation\*\**Presenter +``` -Ας ξεκινήσουμε με ένα δείγμα που δεν χρησιμοποιεί ενότητες. Θα θέλουμε απλώς οι κλάσεις presenter να έχουν το namespace `App\Presenters`. Αυτό σημαίνει ότι ένας παρουσιαστής όπως το `Home` θα πρέπει να αντιστοιχίζεται στην κλάση `App\Presenters\HomePresenter`. Αυτό μπορεί να επιτευχθεί με την ακόλουθη διαμόρφωση: +Πώς λειτουργεί η χαρτογράφηση; Για καλύτερη κατανόηση, ας φανταστούμε πρώτα μια εφαρμογή χωρίς ενότητες. Θέλουμε οι κλάσεις του παρουσιαστή να υπάγονται στο χώρο ονομάτων `App\UI`, έτσι ώστε ο παρουσιαστής `Home` να αντιστοιχίζεται στην κλάση `App\Presentation\HomePresenter`. Αυτό μπορεί να επιτευχθεί με αυτή τη διαμόρφωση: ```neon application: - mapping: App\Presenters\*Presenter + mapping: App\Presentation\*Presenter ``` -Το όνομα του παρουσιαστή αντικαθίσταται με τον αστερίσκο στη μάσκα κλάσης και το αποτέλεσμα είναι το όνομα της κλάσης. Εύκολο! +Αυτή η αντιστοίχιση λειτουργεί αντικαθιστώντας τον αστερίσκο στη μάσκα `App\Presentation\*Presenter` με το όνομα του παρουσιαστή `Home`, με αποτέλεσμα το τελικό όνομα της κλάσης `App\Presentation\HomePresenter`. Απλό! + +Ωστόσο, όπως μπορείτε να δείτε στα παραδείγματα σε αυτό και σε άλλα κεφάλαια, τοποθετούμε τις κλάσεις παρουσιαστή σε επώνυμους υποκαταλόγους, π.χ. ο παρουσιαστής `Home` αντιστοιχίζεται στην κλάση `App\Presentation\Home\HomePresenter`. Αυτό επιτυγχάνεται με τον διπλασιασμό του αστερίσκου (απαιτεί Nette Application 3.2): + +```neon +application: + mapping: App\Presentation\**Presenter +``` -Αν χωρίσουμε τους παρουσιαστές σε ενότητες, μπορούμε να έχουμε τη δική μας χαρτογράφηση για κάθε ενότητα: +Τώρα, ας προχωρήσουμε στην αντιστοίχιση των παρουσιαστών σε ενότητες. Μπορούμε να ορίσουμε συγκεκριμένες αντιστοιχίσεις για κάθε ενότητα: ```neon application: mapping: - Front: App\Modules\Front\Presenters\*Presenter - Admin: App\Modules\Admin\Presenters\*Presenter + Front: App\Presentation\Front\**Presenter + Admin: App\Presentation\Admin\**Presenter Api: App\Api\*Presenter ``` -Τώρα ο παρουσιαστής `Front:Home` αντιστοιχίζεται στην κλάση `App\Modules\Front\Presenters\HomePresenter` και ο παρουσιαστής `Admin:Dashboard` στην κλάση `App\Modules\Admin\Presenters\DashboardPresenter`. +Σύμφωνα με αυτή τη διαμόρφωση, ο παρουσιαστής `Front:Home` αντιστοιχίζεται στην κλάση `App\Presentation\Front\Home\HomePresenter`, ενώ ο παρουσιαστής `Api:OAuth` αντιστοιχίζεται στην κλάση `App\Api\OAuthPresenter`. -Είναι πιο πρακτικό να δημιουργήσετε έναν γενικό κανόνα (αστέρι) για να αντικαταστήσετε τους δύο πρώτους. Ο επιπλέον αστερίσκος θα προστεθεί στη μάσκα κλάσης μόνο για την ενότητα: +Δεδομένου ότι οι ενότητες `Front` και `Admin` έχουν παρόμοια προσέγγιση αντιστοίχισης και είναι πιθανό να υπάρχουν περισσότερες τέτοιες ενότητες, είναι δυνατόν να δημιουργηθεί ένας γενικός κανόνας που να τις αντικαθιστά. Ένας νέος αστερίσκος για την ενότητα προστίθεται στη μάσκα κλάσης: ```neon application: mapping: - *: App\Modules\*\Presenters\*Presenter + *: App\Presentation\*\**Presenter Api: App\Api\*Presenter ``` -Τι γίνεται όμως αν χρησιμοποιούμε φωλιασμένες ενότητες και έχουμε έναν παρουσιαστή `Admin:User:Edit`; Σε αυτή την περίπτωση, το τμήμα με τον αστερίσκο που αντιπροσωπεύει την ενότητα για κάθε επίπεδο απλώς επαναλαμβάνεται και το αποτέλεσμα είναι η κλάση `App\Modules\Admin\User\Presenters\EditPresenter`. +Για πολυεπίπεδες φωλιασμένες ενότητες, όπως ο παρουσιαστής `Admin:User:Edit`, το τμήμα αστερίσκου επαναλαμβάνεται για κάθε επίπεδο, με αποτέλεσμα την κλάση `App\Presentation\Admin\User\Edit\EditPresenter`. -Ένας εναλλακτικός συμβολισμός είναι η χρήση ενός πίνακα που αποτελείται από τρία τμήματα αντί για συμβολοσειρά. Αυτή η σημειογραφία είναι ισοδύναμη με την προηγούμενη: +Ένας εναλλακτικός συμβολισμός είναι η χρήση ενός πίνακα που αποτελείται από τρία τμήματα αντί για μια συμβολοσειρά. Αυτός ο συμβολισμός είναι ισοδύναμος με τον προηγούμενο: ```neon application: mapping: - *: [App\Modules, *, Presenters\*Presenter] + *: [App\UI, *, **Presenter] + Api: [App\Api, '', *Presenter] ``` -Η προεπιλεγμένη τιμή είναι `*Module\*Presenter`. +Αν έχουμε μόνο έναν κανόνα στη διαμόρφωση, τον γενικό, μπορούμε να γράψουμε συνοπτικά: + +```neon +application: + mapping: App\Presentation\*\**Presenter +``` diff --git a/application/el/templates.texy b/application/el/templates.texy index 4b83599f45..bb8918ffaf 100644 --- a/application/el/templates.texy +++ b/application/el/templates.texy @@ -34,35 +34,81 @@ Ορίζει το μπλοκ `content`, το οποίο εισάγεται στη θέση του `{include content}` στη διάταξη, και επίσης επαναπροσδιορίζει το μπλοκ `title`, το οποίο αντικαθιστά το `{block title}` στη διάταξη. Προσπαθήστε να φανταστείτε το αποτέλεσμα. -Αναζήτηση προτύπων .[#toc-search-for-templates] ------------------------------------------------ +Αναζήτηση προτύπου .[#toc-template-lookup] +------------------------------------------ -Η διαδρομή προς τα πρότυπα προκύπτει σύμφωνα με μια απλή λογική. Προσπαθεί να δει αν ένα από αυτά τα αρχεία προτύπων υπάρχει σε σχέση με τον κατάλογο όπου βρίσκεται η κλάση presenter, όπου `` είναι το όνομα του τρέχοντος παρουσιαστή και `` είναι το όνομα της τρέχουσας δράσης: +Στους παρουσιαστές, δεν χρειάζεται να καθορίσετε ποιο πρότυπο πρέπει να αποδοθεί- το πλαίσιο θα καθορίσει αυτόματα τη διαδρομή, διευκολύνοντας την κωδικοποίηση για εσάς. -- `templates//.latte` -- `templates/..latte` +Αν χρησιμοποιείτε μια δομή καταλόγου όπου κάθε παρουσιαστής έχει το δικό του κατάλογο, απλά τοποθετήστε το πρότυπο σε αυτόν τον κατάλογο κάτω από το όνομα της ενέργειας (π.χ. προβολή). Για παράδειγμα, για τη δράση `default`, χρησιμοποιήστε το πρότυπο `default.latte`: -Αν το πρότυπο δεν βρεθεί, θα προσπαθήσει να ψάξει στον κατάλογο `templates` ένα επίπεδο πιο πάνω, δηλαδή στο ίδιο επίπεδο με τον κατάλογο με την κλάση παρουσιαστή. +/--pre +app/ +└── Presentation/ + └── Home/ + ├── HomePresenter.php + └── default.latte +\-- -Εάν το πρότυπο δεν βρεθεί ούτε εκεί, η απάντηση είναι ένα [σφάλμα 404 |presenters#Error 404 etc.]. +Εάν χρησιμοποιείτε μια δομή όπου οι παρουσιαστές βρίσκονται μαζί σε έναν κατάλογο και τα πρότυπα σε έναν φάκελο `templates`, αποθηκεύστε το είτε σε ένα αρχείο `..latte` είτε στο `/.latte`: -Μπορείτε επίσης να αλλάξετε την προβολή χρησιμοποιώντας το `$this->setView('otherView')`. Ή, αντί για αναζήτηση, καθορίστε απευθείας το όνομα του αρχείου προτύπου χρησιμοποιώντας τη διεύθυνση `$this->template->setFile('/path/to/template.latte')`. +/--pre +app/ +└── Presenters/ + ├── HomePresenter.php + └── templates/ + ├── Home.default.latte ← 1st variant + └── Home/ + └── default.latte ← 2nd variant +\-- + +Ο κατάλογος `templates` μπορεί επίσης να τοποθετηθεί ένα επίπεδο ψηλότερα, στο ίδιο επίπεδο με τον κατάλογο με τις κλάσεις παρουσιαστών. + +Εάν το πρότυπο δεν βρεθεί, ο παρουσιαστής απαντά με το [σφάλμα 404 - σελίδα δεν βρέθηκε |presenters#Error 404 etc]. + +Μπορείτε να αλλάξετε την προβολή χρησιμοποιώντας το `$this->setView('anotherView')`. Είναι επίσης δυνατό να καθορίσετε απευθείας το αρχείο προτύπου με το `$this->template->setFile('/path/to/template.latte')`. .[note] -Μπορείτε να αλλάξετε τις διαδρομές στις οποίες αναζητούνται τα πρότυπα υπερκαλύπτοντας τη μέθοδο [formatTemplateFiles |api:Nette\Application\UI\Presenter::formatTemplateFiles()], η οποία επιστρέφει έναν πίνακα πιθανών διαδρομών αρχείων. +Τα αρχεία στα οποία αναζητούνται τα πρότυπα μπορούν να αλλάξουν με την παράκαμψη της μεθόδου [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()], η οποία επιστρέφει έναν πίνακα πιθανών ονομάτων αρχείων. + + +Αναζήτηση προτύπων διάταξης .[#toc-layout-template-lookup] +---------------------------------------------------------- + +Η Nette αναζητά επίσης αυτόματα το αρχείο διάταξης. + +Εάν χρησιμοποιείτε μια δομή καταλόγου όπου κάθε παρουσιαστής έχει το δικό του κατάλογο, τοποθετήστε τη διάταξη είτε στο φάκελο με τον παρουσιαστή, εάν αφορά μόνο αυτόν, είτε ένα επίπεδο ψηλότερα εάν είναι κοινή για πολλούς παρουσιαστές: + +/--pre +app/ +└── Presentation/ + ├── @layout.latte ← common layout + └── Home/ + ├── @layout.latte ← only for Home presenter + ├── HomePresenter.php + └── default.latte +\-- + +Εάν χρησιμοποιείτε μια δομή όπου οι παρουσιαστές είναι ομαδοποιημένοι σε έναν κατάλογο και τα πρότυπα βρίσκονται σε έναν φάκελο `templates`, η διάταξη αναμένεται στις ακόλουθες θέσεις: -Η διάταξη αναμένεται στα ακόλουθα αρχεία: +/--pre +app/ +└── Presenters/ + ├── HomePresenter.php + └── templates/ + ├── @layout.latte ← common layout + ├── Home.@layout.latte ← only for Home, 1st variant + └── Home/ + └── @layout.latte ← only for Home, 2nd variant +\-- -- `templates//@.latte` -- `templates/.@.latte` -- `templates/@.latte` διάταξη κοινή για πολλούς παρουσιαστές +Εάν ο παρουσιαστής βρίσκεται σε μια [ενότητα |modules], θα αναζητήσει επίσης πιο πάνω στο δέντρο καταλόγων σύμφωνα με την ένθεση της ενότητας. -`` είναι το όνομα του τρέχοντος παρουσιαστή και `` είναι το όνομα της διάταξης, η οποία είναι εξ ορισμού `'layout'`. Το όνομα μπορεί να αλλάξει με το `$this->setLayout('otherLayout')`, έτσι ώστε να δοκιμάζονται τα αρχεία `@otherLayout.latte`. +Το όνομα της διάταξης μπορεί να αλλάξει χρησιμοποιώντας το `$this->setLayout('layoutAdmin')` και τότε θα αναμένεται στο αρχείο `@layoutAdmin.latte`. Μπορείτε επίσης να καθορίσετε απευθείας το αρχείο προτύπου διάταξης χρησιμοποιώντας το `$this->setLayout('/path/to/template.latte')`. -Μπορείτε επίσης να καθορίσετε απευθείας το όνομα του αρχείου του προτύπου διάταξης χρησιμοποιώντας το `$this->setLayout('/path/to/template.latte')`. Η χρήση του `$this->setLayout(false)` θα απενεργοποιήσει την αναζήτηση διάταξης. +Η χρήση του `$this->setLayout(false)` ή της ετικέτας `{layout none}` μέσα στο πρότυπο απενεργοποιεί την αναζήτηση διάταξης. .[note] -Μπορείτε να αλλάξετε τις διαδρομές στις οποίες αναζητούνται τα πρότυπα με την παράκαμψη της μεθόδου [formatLayoutTemplateFiles |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], η οποία επιστρέφει έναν πίνακα πιθανών διαδρομών αρχείων. +Τα αρχεία στα οποία αναζητούνται τα πρότυπα διάταξης μπορούν να αλλάξουν με την παράκαμψη της μεθόδου [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], η οποία επιστρέφει έναν πίνακα πιθανών ονομάτων αρχείων. Μεταβλητές στο πρότυπο .[#toc-variables-in-the-template] @@ -104,7 +150,7 @@ class ArticleTemplate extends Nette\Bridges\ApplicationLatte\Template Μπορείτε επίσης να αφεθείτε στην πολυτέλεια του ψιθυρίσματος στα πρότυπα, απλά εγκαταστήστε το πρόσθετο Latte στο PhpStorm και καθορίστε το όνομα της κλάσης στην αρχή του προτύπου, δείτε το άρθρο "Latte: πώς να πληκτρολογήσετε το σύστημα":https://blog.nette.org/el/latte-pos-na-chresimopoiesete-to-systema-typon: ```latte -{templateType App\Presenters\ArticleTemplate} +{templateType App\Presentation\Article\ArticleTemplate} ... ``` @@ -176,7 +222,7 @@ public function beforeRender(): void Latte έκδοση 3 προσφέρει έναν πιο προηγμένο τρόπο δημιουργώντας μια [επέκταση |latte:creating-extension] για κάθε έργο ιστού. Εδώ είναι ένα πρόχειρο παράδειγμα μιας τέτοιας κλάσης: ```php -namespace App\Templating; +namespace App\Presentation\Accessory; final class LatteExtension extends Latte\Extension { @@ -214,7 +260,7 @@ final class LatteExtension extends Latte\Extension ```neon latte: extensions: - - App\Templating\LatteExtension + - App\Presentation\Accessory\LatteExtension ``` diff --git a/application/en/how-it-works.texy b/application/en/how-it-works.texy index 612d192393..8ba86fd694 100644 --- a/application/en/how-it-works.texy +++ b/application/en/how-it-works.texy @@ -22,13 +22,13 @@ The directory structure looks something like this: /--pre web-project/ ├── app/ ← directory with application -│ ├── Presenters/ ← presenter classes -│ │ ├── HomePresenter.php ← Home presenter class -│ │ └── templates/ ← templates directory -│ │ ├── @layout.latte ← template of shared layout -│ │ └── Home/ ← templates for Home presenter -│ │ └── default.latte ← template for action `default` -│ ├── Router/ ← configuration of URL addresses +│ ├── Core/ ← basic necessary classes +│ │ └── RouterFactory.php ← configuration of URL addresses +│ ├── Presentation/ ← presenters, templates & co. +│ │ ├── @layout.latte ← template of shared layout +│ │ └── Home/ ← Home presenter directory +│ │ ├── HomePresenter.php ← Home presenter class +│ │ └── default.latte ← template for action default │ └── Bootstrap.php ← booting class Bootstrap ├── bin/ ← scripts for the command line ├── config/ ← configuration files @@ -91,7 +91,7 @@ Applications written in Nette are divided into many so-called presenters (in oth The application starts by asking the so-called router to decide which of the presenters to pass the current request for processing. The router decides whose responsibility it is. It looks at the input URL `https://example.com/product/123` and, based on how it is set up, decides that this is a job, for example, for **presenter** `Product`, who wants to `show` a product with `id: 123` as an action. It is a good habit to write a pairs of presenter + action separated by a colon as `Product:show`. -So the router transformed the URL into a pair `Presenter:action` + parameters, in our case `Product:show` + `id: 123`. You can see how a router looks like in file `app/Router/RouterFactory.php` and we will describe it in detail in chapter [Routing]. +So the router transformed the URL into a pair `Presenter:action` + parameters, in our case `Product:show` + `id: 123`. You can see how a router looks like in file `app/Core/RouterFactory.php` and we will describe it in detail in chapter [Routing]. Let's move on. The application already knows the name of the presenter and can continue. By creating an object `ProductPresenter`, which is the code of presenter `Product`. More precisely, it asks the DI container for creating the presenter, because producting objects is its job. @@ -121,12 +121,9 @@ So, the method `renderShow(123)` was called, whose code is fictional example, bu Subsequently, the presenter returns the answer. This can be an HTML page, an image, an XML document, sending a file from disk, JSON or redirecting to another page. Importantly, if we do not explicitly say how to respond (which is the case of `ProductPresenter`), the answer will be to render the template with an HTML page. Why? Well, because in 99% of cases we want to draw a template, so the presenter takes this behavior as the default and wants to make our work easier. That's Nette's point. -We don't even have to state which template to draw, he derives the path to it according to simple logic. In the case of presenter `Product` and action `show`, it tries to see if one of these template files exists relative to the directory where class `ProductPresenter` is located: +We don't even need to specify which template to render; the framework will deduce the path itself. In the case of the `show` action, it simply tries to load the `show.latte` template in the directory with the `ProductPresenter` class. It also attempts to find the layout in the `@layout.latte` file (more about [template searching |templates#Template Lookup]). -- `templates/Product/show.latte` -- `templates/Product.show.latte` - -It will also try to find the layout in file `@layout.latte` and then it renders the template. Now the task of the presenter and the entire application is completed. If the template does not exist, a page with error 404 will be returned. You can read more about presenters on the [Presenters] page. +Subsequently, the templates are rendered. This completes the task of the presenter and the entire application, and the work is done. If the template did not exist, a 404 error page would be returned. You can read more about presenters on the page [Presenters|presenters]. [* request-flow.svg *] @@ -137,7 +134,7 @@ Just to be sure, let's try to recap the whole process with a slightly different 3) the router decodes the URL as a pair `Home:default` 4) an `HomePresenter` object is created 5) method `renderDefault()` is called (if exists) -6) a template `templates/Home/default.latte` with a layout `templates/@layout.latte` is rendered +6) a template `default.latte` with a layout `@layout.latte` is rendered You may have come across a lot of new concepts now, but we believe they make sense. Creating applications in Nette is a breeze. diff --git a/application/en/modules.texy b/application/en/modules.texy index 376ac872b9..317716feaf 100644 --- a/application/en/modules.texy +++ b/application/en/modules.texy @@ -2,29 +2,31 @@ Modules ******* .[perex] -In Nette, modules represent the logical units that make up an application. They include presenters, templates, possibly also components and model classes. +Modules bring clarity to Nette applications by facilitating easy division into logical units. -One directory for presenters and one for templates would not be enough for real projects. Having dozens of files in one folder is at least unorganized. How to get out of it? We simply split them into subdirectories on disk and into namespaces in the code. And that's exactly what the Nette modules do. - -So let's forget about a single folder for presenters and templates and instead create modules, for example `Admin` and `Front`. +Similar to organizing files into folders on a hard drive, in Nette we can divide presenters, templates, and other auxiliary classes into modules. How does this work in practice? Simply by incorporating new subdirectories into the structure. Here’s an example of a structure with two modules, Front and Admin: /--pre -app/ -├── Presenters/ -├── Modules/ ← directory with modules -│ ├── Admin/ ← module Admin -│ │ ├── Presenters/ ← its presenters -│ │ │ ├── DashboardPresenter.php -│ │ │ └── templates/ -│ └── Front/ ← module Front -│ └── Presenters/ ← its presenters -│ └── ... +app/ +├── Presentation/ +│ ├── Admin/ ← Admin module +│ │ ├── @layout.latte +│ │ ├── Dashboard/ +│ │ │ ├── DashboardPresenter.php +│ │ │ └── default.latte +│ │ └── ... +│ ├── Front/ ← Front module +│ │ ├── @layout.latte +│ │ ├── Home/ +│ │ │ ├── HomePresenter.php +│ │ │ └── default.latte +│ │ └── ... \-- -This directory structure will be reflected by the class namespaces, so for example `DashboardPresenter` will be in the `App\Modules\Admin\Presenters` namespace: +This directory structure is reflected in the namespaces of the classes, so for example, `DashboardPresenter` is located in the namespace `App\Presentation\Admin\Dashboard`: ```php -namespace App\Modules\Admin\Presenters; +namespace App\Presentation\Admin\Dashboard; class DashboardPresenter extends Nette\Application\UI\Presenter { @@ -32,35 +34,49 @@ class DashboardPresenter extends Nette\Application\UI\Presenter } ``` -The `Dashboard` presenter inside the `Admin` module is referenced within the application using the colon notation as `Admin:Dashboard`, and its `default` action as `Admin:Dashboard:default`. -And how does Nette proper know that `Admin:Dashboard` represents the `App\Modules\Admin\Presenters\DashboardPresenter` class? This is determined by [#mapping] in the configuration. -Thus, the given structure is not hard set and you can modify it according to your needs. +In the application, we refer to the `Dashboard` presenter within the `Admin` module using colon notation as `Admin:Dashboard`. For its `default` action, we refer to it as `Admin:Dashboard:default`. -Modules can of course contain all other items besides presenters and templates, such as components, model classes, etc. +The structure presented is not rigid; you can [fully customize it to your needs|#mapping] in the configuration. .[tip] + +Modules can include all other files, such as components and auxiliary classes, in addition to presenters and templates. If you are considering where to place these, consider using an `Accessory` folder: + +/--pre +app/ +├── Presentation/ +│ ├── Admin/ +│ │ ├── Accessory/ +│ │ │ ├── FormFactory.php +│ │ │ └── AdminLayout.php +│ │ ├── Dashboard/ +│ │ └── ... +\-- Nested Modules -------------- -Modules don't have to form only a flat structure, you can also create submodules, for example: +Modules can have multiple levels of nesting, similar to a directory structure on a disk: /--pre -app/ -├── Modules/ ← directory with modules -│ ├── Blog/ ← module Blog -│ │ ├── Admin/ ← submodule Admin -│ │ │ ├── Presenters/ +app/ +├── Presentation/ +│ ├── Blog/ ← Blog module +│ │ ├── Admin/ ← Admin submodule +│ │ │ ├── Dashboard/ +│ │ │ └── ... +│ │ ├── Front/ ← Front submodule +│ │ │ ├── @layout.latte +│ │ │ ├── Home/ │ │ │ └── ... -│ │ └── Front/ ← submodule Front -│ │ ├── Presenters/ -│ │ └── ... -│ ├── Forum/ ← module Forum +│ ├── Forum/ ← Forum module │ │ └── ... \-- -Thus, the `Blog` module is divided into `Admin` and `Front` submodules. Again, this will be reflected in the namespaces, which will be `App\Modules\Blog\Admin\Presenters` etc. The presenter `Dashboard` inside the submodule is referred to as `Blog:Admin:Dashboard`. +The `Blog` module is divided into `Admin` and `Front` submodules. This is also reflected in the namespaces, which then appear as `App\Presentation\Blog\Admin` and similarly. To refer to the `Dashboard` presenter within the `Admin` submodule, we refer to it as `Blog:Admin:Dashboard`. -The nesting can go as deep as you like, so sub-submodules can be created. +Nesting can be as deep as needed, allowing the creation of sub-submodules. + +For example, if in administration you have many presenters related to order management, such as `OrderDetail`, `OrderEdit`, `OrderDispatch`, etc., you might create an `Order` module in which presenters like `Detail`, `Edit`, `Dispatch`, and others will be organized. Creating Links @@ -102,46 +118,66 @@ See [chapter on routing |routing#Modules]. Mapping ------- -Defines the rules by which the class name is derived from the presenter name. We write them in [configuration] under the `application › mapping` key. +Mapping defines the rules for deriving the class name from the presenter name. These rules are specified in the [configuration|configuration] under the key `application › mapping`. + +The directory structures mentioned earlier on this page are based on the following mapping: + +```neon +application: + mapping: App\Presentation\*\**Presenter +``` -Let's start with a sample that doesn't use modules. We'll just want the presenter classes to have the `App\Presenters` namespace. That means that a presenter such as `Home` should map to the `App\Presenters\HomePresenter` class. This can be achieved by the following configuration: +How does the mapping work? For a better understanding, let's first imagine an application without modules. We want the presenter classes to fall under the namespace `App\UI`, so that the `Home` presenter maps to the class `App\Presentation\HomePresenter`. This can be achieved with this configuration: ```neon application: - mapping: App\Presenters\*Presenter + mapping: App\Presentation\*Presenter ``` -The presenter name is replaced with the asterisk in the class mask and the result is the class name. Easy! +This mapping works by replacing the asterisk in the mask `App\Presentation\*Presenter` with the presenter name `Home`, resulting in the final class name `App\Presentation\HomePresenter`. Simple! + +However, as you can see in the examples in this and other chapters, we place presenter classes in eponymous subdirectories, e.g., the `Home` presenter is mapped to the class `App\Presentation\Home\HomePresenter`. This is achieved by doubling the asterisk (requires Nette Application 3.2): + +```neon +application: + mapping: App\Presentation\**Presenter +``` -If we divide presenters into modules, we can have our own mapping for each module: +Now, let's move on to mapping presenters into modules. We can define specific mappings for each module: ```neon application: mapping: - Front: App\Modules\Front\Presenters\*Presenter - Admin: App\Modules\Admin\Presenters\*Presenter + Front: App\Presentation\Front\**Presenter + Admin: App\Presentation\Admin\**Presenter Api: App\Api\*Presenter ``` -Now presenter `Front:Home` maps to class `App\Modules\Front\Presenters\HomePresenter` and presenter `Admin:Dashboard` to class `App\Modules\Admin\Presenters\DashboardPresenter`. +According to this configuration, the presenter `Front:Home` maps to the class `App\Presentation\Front\Home\HomePresenter`, while the presenter `Api:OAuth` maps to the class `App\Api\OAuthPresenter`. -It is more practical to create a general (star) rule to replace the first two. The extra asterisk will be added to the class mask just for the module: +Since the `Front` and `Admin` modules have a similar mapping approach and there are likely to be more such modules, it is possible to create a general rule that replaces them. A new asterisk for the module is added to the class mask: ```neon application: mapping: - *: App\Modules\*\Presenters\*Presenter + *: App\Presentation\*\**Presenter Api: App\Api\*Presenter ``` -But what if we use nested modules and have a presenter `Admin:User:Edit`? In this case, the segment with an asterisk representing the module for each level is simply repeated and the result is class `App\Modules\Admin\User\Presenters\EditPresenter`. +For multi-level nested modules, such as the presenter `Admin:User:Edit`, the asterisk segment repeats for each level, resulting in the class `App\Presentation\Admin\User\Edit\EditPresenter`. -An alternative notation is to use an array consisting of three segments instead of a string. This notation is equivalent to the previous one: +An alternative notation is to use an array composed of three segments instead of a string. This notation is equivalent to the previous one: ```neon application: mapping: - *: [App\Modules, *, Presenters\*Presenter] + *: [App\UI, *, **Presenter] + Api: [App\Api, '', *Presenter] ``` -The default value is `*Module\*Presenter`. +If we have only one rule in the configuration, the general one, we can write briefly: + +```neon +application: + mapping: App\Presentation\*\**Presenter +``` diff --git a/application/en/templates.texy b/application/en/templates.texy index 5107b4493a..d31240399f 100644 --- a/application/en/templates.texy +++ b/application/en/templates.texy @@ -34,35 +34,81 @@ And this might be the action template: It defines block `content`, which is inserted in place of `{include content}` in the layout, and also re-defines block `title`, which overwrites `{block title}` in the layout. Try to imagine the result. -Search for Templates --------------------- +Template Lookup +--------------- -The path to the templates is deduced according to simple logic. It tries to see if one of these template files exists relative to the directory where presenter class is located, where `` is the name of the current presenter and `` is the name of the current action: +In presenters, you don't need to specify which template should be rendered; the framework will automatically determine the path, making coding easier for you. -- `templates//.latte` -- `templates/..latte` +If you use a directory structure where each presenter has its own directory, simply place the template in this directory under the name of the action (i.e. view). For example, for the `default` action, use the `default.latte` template: -If the template is not found, it will try to search in the `templates` directory one level up, i.e., at the same level as the directory with the presenter class. +/--pre +app/ +└── Presentation/ + └── Home/ + ├── HomePresenter.php + └── default.latte +\-- -If the template is not found there either, the response is a [404 error|presenters#Error 404 etc.]. +If you use a structure where presenters are together in one directory and templates in a `templates` folder, save it either in a file `..latte` or `/.latte`: -You can also change the view using `$this->setView('otherView')`. Or, instead of searching, directly specify the name of the template file using `$this->template->setFile('/path/to/template.latte')`. +/--pre +app/ +└── Presenters/ + ├── HomePresenter.php + └── templates/ + ├── Home.default.latte ← 1st variant + └── Home/ + └── default.latte ← 2nd variant +\-- + +The `templates` directory can also be placed one level higher, at the same level as the directory with presenter classes. + +If the template is not found, the presenter responds with [404 - page not found error|presenters#Error 404 etc]. + +You can change the view using `$this->setView('anotherView')`. It is also possible to directly specify the template file with `$this->template->setFile('/path/to/template.latte')`. .[note] -You can change the paths where templates are searched by overriding the [formatTemplateFiles |api:Nette\Application\UI\Presenter::formatTemplateFiles()] method, which returns an array of possible file paths. +Files where templates are searched can be changed by overriding the method [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()], which returns an array of possible file names. + + +Layout Template Lookup +---------------------- + +Nette also automatically searches for the layout file. + +If you use a directory structure where each presenter has its own directory, place the layout either in the folder with the presenter, if it is specific only to them, or a level higher if it is common to multiple presenters: + +/--pre +app/ +└── Presentation/ + ├── @layout.latte ← common layout + └── Home/ + ├── @layout.latte ← only for Home presenter + ├── HomePresenter.php + └── default.latte +\-- + +If you use a structure where presenters are grouped together in one directory and templates are in a `templates` folder, the layout will be expected in the following places: -The layout is expected in the following files: +/--pre +app/ +└── Presenters/ + ├── HomePresenter.php + └── templates/ + ├── @layout.latte ← common layout + ├── Home.@layout.latte ← only for Home, 1st variant + └── Home/ + └── @layout.latte ← only for Home, 2nd variant +\-- -- `templates//@.latte` -- `templates/.@.latte` -- `templates/@.latte` layout common to multiple presenters +If the presenter is in a [module|modules], it will also search further up the directory tree according to the module's nesting. -`` is the name of the current presenter and `` is the name of the layout, which is by default `'layout'`. The name can be changed with `$this->setLayout('otherLayout')`, so that `@otherLayout.latte` files will be tried. +The name of the layout can be changed using `$this->setLayout('layoutAdmin')` and then it will be expected in the file `@layoutAdmin.latte`. You can also directly specify the layout template file using `$this->setLayout('/path/to/template.latte')`. -You can also directly specify the file name of the layout template using `$this->setLayout('/path/to/template.latte')`. Using `$this->setLayout(false)` will disable the layout searching. +Using `$this->setLayout(false)` or the `{layout none}` tag inside the template disables layout search. .[note] -You can change the paths where templates are searched by overriding the [formatLayoutTemplateFiles |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()] method, which returns an array of possible file paths. +Files where layout templates are searched can be changed by overriding the method [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], which returns an array of possible file names. Variables in the Template @@ -104,7 +150,7 @@ The `@property-read` annotation is for IDE and static analysis, it will make aut You can indulge in the luxury of whispering in templates too, just install the Latte plugin in PhpStorm and specify the class name at the beginning of the template, see the article "Latte: how to type system":https://blog.nette.org/en/latte-how-to-use-type-system: ```latte -{templateType App\Presenters\ArticleTemplate} +{templateType App\Presentation\Article\ArticleTemplate} ... ``` @@ -176,7 +222,7 @@ public function beforeRender(): void Latte version 3 offers a more advanced way by creating an [extension |latte:creating-extension] for each web project. Here is a rough example of such a class: ```php -namespace App\Templating; +namespace App\Presentation\Accessory; final class LatteExtension extends Latte\Extension { @@ -214,7 +260,7 @@ We register it using [configuration#Latte]: ```neon latte: extensions: - - App\Templating\LatteExtension + - App\Presentation\Accessory\LatteExtension ``` diff --git a/application/es/how-it-works.texy b/application/es/how-it-works.texy index 1706cb62a5..f8ab6cc8b6 100644 --- a/application/es/how-it-works.texy +++ b/application/es/how-it-works.texy @@ -22,13 +22,13 @@ La estructura de directorios se parece a esto /--pre web-project/ ├── app/ ← directorio con la aplicación -│ ├── Presenters/ ← clases para presentadores -│ │ ├── HomePresenter.php ← Home de inicio de la clase de presentador -│ │ └── templates/ ← directorio de plantillas -│ │ ├── @layout.latte ← plantilla de diseño compartida -│ │ └── Home/ ← plantillas para Home presentador de inicio -│ │ └── default.latte ← plantilla para la acción `default` -│ ├── Router/ ← configuración de direcciones URL +│ ├── Core/ ← clases básicas necesarias. +│ │ └── RouterFactory.php ← configuración de direcciones URL. +│ ├── Presentation/ ← presentadores, plantillas & co. +│ │ ├── @layout.latte ← plantilla de maquetación compartida +│ │ └── Home/ ← Home directorio del presentador +│ │ ├── HomePresenter.php ← Clase del presentador de inicio +│ │ └── default.latte ← plantilla para la acción default │ └── Bootstrap.php ← clase de arranque Bootstrap ├── bin/ ← scripts para la línea de comandos ├── config/ ← archivos de configuración @@ -91,7 +91,7 @@ Las aplicaciones escritas en Nette se dividen en muchos de los llamados presenta La aplicación comienza pidiendo al llamado enrutador que decida a cuál de los presentadores debe pasar la petición actual para su procesamiento. El enrutador decide de quién es la responsabilidad. Mira la URL de entrada `https://example.com/product/123`, que quiere `show` un producto con `id: 123` como acción. Es una buena costumbre escribir pares de presentador + acción separados por dos puntos como `Product:show`. -Así que el enrutador transforma la URL en un par `Presenter:action` + parámetros, en nuestro caso `Product:show` + `id: 123`. Puedes ver el aspecto de un enrutador en el archivo `app/Router/RouterFactory.php` y lo describiremos en detalle en el capítulo [Enrutamiento |Routing]. +Así que el enrutador transforma la URL en un par `Presenter:action` + parámetros, en nuestro caso `Product:show` + `id: 123`. Puedes ver el aspecto de un enrutador en el archivo `app/Core/RouterFactory.php` y lo describiremos en detalle en el capítulo [Enrutamiento |Routing]. Sigamos. La aplicación ya conoce el nombre del presentador y puede continuar. Creando un objeto `ProductPresenter`, que es el código del presentador `Product`. Más concretamente, le pide al contenedor DI que cree el presentador, porque producir objetos es su trabajo. @@ -121,12 +121,9 @@ Así, se llamó al método `renderShow(123)`, cuyo código es ficticio ejemplo, Posteriormente, el presentador devuelve la respuesta. Esta puede ser una página HTML, una imagen, un documento XML, el envío de un fichero desde disco, JSON o la redirección a otra página. Es importante destacar que, si no decimos explícitamente cómo responder (que es el caso de `ProductPresenter`), la respuesta será renderizar la plantilla con una página HTML. ¿Por qué? Pues porque en el 99% de los casos queremos dibujar una plantilla, así que el presentador toma este comportamiento por defecto y quiere facilitarnos el trabajo. Ese es el punto de Nette. -Ni siquiera tenemos que indicar qué plantilla dibujar, él deriva la ruta hacia ella según una lógica simple. En el caso del presentador `Product` y la acción `show`, intenta ver si uno de estos archivos de plantilla existe en relación al directorio donde se encuentra la clase `ProductPresenter`: +Ni siquiera necesitamos especificar qué plantilla renderizar; el framework deducirá la ruta por sí mismo. En el caso de la acción `show`, simplemente intenta cargar la plantilla `show.latte` en el directorio con la clase `ProductPresenter`. También intenta encontrar el diseño en el archivo `@layout.latte` (más información sobre la [búsqueda de plantillas |templates#Template Lookup]). -- `templates/Product/show.latte` -- `templates/Product.show.latte` - -También intentará encontrar el diseño en el archivo `@layout.latte` y luego renderizará la plantilla. Ahora se completa la tarea del presentador y de toda la aplicación. Si la plantilla no existe, se devolverá una página con el error 404. Puedes leer más sobre los presentadores en la página de [Presentadores |Presenters]. +Posteriormente, se renderizan las plantillas. Esto completa la tarea del presentador y de toda la aplicación, y el trabajo está hecho. Si la plantilla no existiera, se devolvería una página de error 404. Puede leer más sobre los presentadores en la página [Presentadores |presenters]. [* request-flow.svg *] @@ -137,7 +134,7 @@ Sólo para estar seguros, intentemos recapitular todo el proceso con una URL lig 3) el router decodifica la URL como un par `Home:default` 4) se crea un objeto `HomePresenter` 5) se llama al método `renderDefault()` (si existe) -6) se renderiza una plantilla `templates/Home/default.latte` con un diseño `templates/@layout.latte` +6) se renderiza una plantilla `default.latte` con un diseño `@layout.latte` Puede que ahora te hayas encontrado con un montón de conceptos nuevos, pero creemos que tienen sentido. Crear aplicaciones en Nette es pan comido. diff --git a/application/es/modules.texy b/application/es/modules.texy index 644cab5c1f..0e6d7cf4d5 100644 --- a/application/es/modules.texy +++ b/application/es/modules.texy @@ -2,29 +2,31 @@ Módulos ******* .[perex] -En Nette, los módulos representan las unidades lógicas que componen una aplicación. Incluyen presentadores, plantillas, posiblemente también componentes y clases modelo. +Los módulos aportan claridad a las aplicaciones Nette al facilitar su división en unidades lógicas. -Un directorio para los presentadores y otro para las plantillas no serían suficientes para los proyectos reales. Tener docenas de archivos en una carpeta es, como mínimo, desorganizado. ¿Cómo salir de ello? Simplemente los dividimos en subdirectorios en el disco y en espacios de nombres en el código. Y eso es exactamente lo que hacen los módulos de Nette. - -Así que olvidémonos de una única carpeta para presentadores y plantillas y en su lugar creemos módulos, por ejemplo `Admin` y `Front`. +De forma similar a la organización de archivos en carpetas en un disco duro, en Nette podemos dividir los presentadores, plantillas y otras clases auxiliares en módulos. ¿Cómo funciona esto en la práctica? Simplemente incorporando nuevos subdirectorios a la estructura. He aquí un ejemplo de estructura con dos módulos, Front y Admin: /--pre -app/ -├── Presenters/ -├── Modules/ ← directorio con módulos -│ ├── Admin/ ← módulo Admin -│ │ ├── Presenters/ ← sus presentadores -│ │ │ ├── DashboardPresenter.php -│ │ │ └── templates/ -│ └── Front/ ← módulo Front -│ └── Presenters/ ← sus presentadores -│ └── ... +app/ +├── Presentation/ +│ ├── Admin/ ← Admin module +│ │ ├── @layout.latte +│ │ ├── Dashboard/ +│ │ │ ├── DashboardPresenter.php +│ │ │ └── default.latte +│ │ └── ... +│ ├── Front/ ← Front module +│ │ ├── @layout.latte +│ │ ├── Home/ +│ │ │ ├── HomePresenter.php +│ │ │ └── default.latte +│ │ └── ... \-- -Esta estructura de directorios se reflejará en los espacios de nombres de las clases, así por ejemplo `DashboardPresenter` estará en el espacio de nombres `App\Modules\Admin\Presenters`: +Esta estructura de directorios se refleja en los espacios de nombres de las clases, así por ejemplo, `DashboardPresenter` se encuentra en el espacio de nombres `App\Presentation\Admin\Dashboard`: ```php -namespace App\Modules\Admin\Presenters; +namespace App\Presentation\Admin\Dashboard; class DashboardPresenter extends Nette\Application\UI\Presenter { @@ -32,35 +34,49 @@ class DashboardPresenter extends Nette\Application\UI\Presenter } ``` -El presentador `Dashboard` dentro del módulo `Admin` es referenciado dentro de la aplicación usando la notación de dos puntos como `Admin:Dashboard`, y su acción `default` como `Admin:Dashboard:default`. -¿Y cómo sabe Nette que `Admin:Dashboard` representa la clase `App\Modules\Admin\Presenters\DashboardPresenter`? Esto se determina mediante el [mapeo |#mapping] en la configuración. -Por lo tanto, la estructura dada no es rígida y puede modificarla según sus necesidades. +En la aplicación, nos referimos al presentador `Dashboard` dentro del módulo `Admin` utilizando la notación de dos puntos como `Admin:Dashboard`. Para su acción `default`, nos referimos a él como `Admin:Dashboard:default`. -Por supuesto, los módulos pueden contener todos los demás elementos además de presentadores y plantillas, como componentes, clases modelo, etc. +La estructura presentada no es rígida; puede [adaptarla totalmente a sus necesidades |#mapping] en la configuración. .[tip] + +Los módulos pueden incluir todos los demás archivos, como componentes y clases auxiliares, además de presentadores y plantillas. Si está pensando dónde colocarlos, considere la posibilidad de utilizar una carpeta `Accessory`: + +/--pre +app/ +├── Presentation/ +│ ├── Admin/ +│ │ ├── Accessory/ +│ │ │ ├── FormFactory.php +│ │ │ └── AdminLayout.php +│ │ ├── Dashboard/ +│ │ └── ... +\-- Módulos anidados .[#toc-nested-modules] --------------------------------------- -Los módulos no tienen por qué formar sólo una estructura plana, también puedes crear submódulos, por ejemplo: +Los módulos pueden tener múltiples niveles de anidamiento, similar a una estructura de directorios en un disco: /--pre -app/ -├── Modules/ ← directorio con módulos -│ ├── Blog/ ← módulo Blog -│ │ ├── Admin/ ← submódulo Admin -│ │ │ ├── Presenters/ +app/ +├── Presentation/ +│ ├── Blog/ ← Blog module +│ │ ├── Admin/ ← Admin submodule +│ │ │ ├── Dashboard/ +│ │ │ └── ... +│ │ ├── Front/ ← Front submodule +│ │ │ ├── @layout.latte +│ │ │ ├── Home/ │ │ │ └── ... -│ │ └── Front/ ← submódulo Front -│ │ ├── Presenters/ -│ │ └── ... -│ ├── Forum/ ← módulo Forum +│ ├── Forum/ ← Forum module │ │ └── ... \-- -Así, el módulo `Blog` se divide en los submódulos `Admin` y `Front`. De nuevo, esto se reflejará en los espacios de nombres, que serán `App\Modules\Blog\Admin\Presenters`, etc. El presentador `Dashboard` dentro del submódulo se denomina `Blog:Admin:Dashboard`. +El módulo `Blog` se divide en los submódulos `Admin` y `Front`. Esto también se refleja en los espacios de nombres, que aparecen como `App\Presentation\Blog\Admin` y similares. Para referirnos al presentador `Dashboard` dentro del submódulo `Admin`, lo denominamos `Blog:Admin:Dashboard`. -El anidamiento puede ser tan profundo como se desee, por lo que pueden crearse submódulos. +El anidamiento puede ser tan profundo como sea necesario, permitiendo la creación de sub-submódulos. + +Por ejemplo, si en administración tiene muchos presentadores relacionados con la gestión de pedidos, como `OrderDetail`, `OrderEdit`, `OrderDispatch`, etc., puede crear un módulo `Order` en el que se organizarán presentadores como `Detail`, `Edit`, `Dispatch`, y otros. Creación de enlaces .[#toc-creating-links] @@ -99,49 +115,69 @@ Enrutamiento .[#toc-routing] Véase el [capítulo sobre en rutamiento|routing#Modules]. -Mapeo .[#toc-mapping] ---------------------- +Cartografía .[#toc-mapping] +--------------------------- + +El mapeo define las reglas para derivar el nombre de la clase del nombre del presentador. Estas reglas se especifican en la [configuración |configuration] bajo la clave `application › mapping`. + +Las estructuras de directorios mencionadas anteriormente en esta página se basan en la siguiente asignación: -Define las reglas por las que el nombre de la clase se deriva del nombre del presentador. Las escribimos en [configuración |configuration] bajo la clave `application › mapping`. +```neon +application: + mapping: App\Presentation\*\**Presenter +``` -Empecemos con un ejemplo que no utiliza módulos. Sólo querremos que las clases del presentador tengan el espacio de nombres `App\Presenters`. Eso significa que un presentador como `Home` debe mapearse a la clase `App\Presenters\HomePresenter`. Esto se puede lograr con la siguiente configuración: +¿Cómo funciona el mapeo? Para entenderlo mejor, imaginemos primero una aplicación sin módulos. Queremos que las clases del presentador pertenezcan al espacio de nombres `App\UI`, de modo que el presentador `Home` se asigne a la clase `App\Presentation\HomePresenter`. Esto se puede lograr con esta configuración: ```neon application: - mapping: App\Presenters\*Presenter + mapping: App\Presentation\*Presenter ``` -El nombre del presentador se sustituye por el asterisco en la máscara de clase y el resultado es el nombre de la clase. Muy fácil. +Este mapeo funciona reemplazando el asterisco en la máscara `App\Presentation\*Presenter` con el nombre del presentador `Home`, resultando en el nombre final de la clase `App\Presentation\HomePresenter`. Es muy sencillo. + +Sin embargo, como puede ver en los ejemplos de este y otros capítulos, colocamos las clases de presentador en subdirectorios epónimos, por ejemplo, el presentador `Home` se asigna a la clase `App\Presentation\Home\HomePresenter`. Esto se consigue duplicando el asterisco (requiere Nette Application 3.2): + +```neon +application: + mapping: App\Presentation\**Presenter +``` -Si dividimos a los presentadores en módulos, podemos tener nuestra propia asignación para cada módulo: +Pasemos ahora a la asignación de presentadores a módulos. Podemos definir asignaciones específicas para cada módulo: ```neon application: mapping: - Front: App\Modules\Front\Presenters\*Presenter - Admin: App\Modules\Admin\Presenters\*Presenter + Front: App\Presentation\Front\**Presenter + Admin: App\Presentation\Admin\**Presenter Api: App\Api\*Presenter ``` -Ahora el presentador `Front:Home` se asigna a la clase `App\Modules\Front\Presenters\HomePresenter` y el presentador `Admin:Dashboard` a la clase `App\Modules\Admin\Presenters\DashboardPresenter`. +Según esta configuración, el presentador `Front:Home` se asigna a la clase `App\Presentation\Front\Home\HomePresenter`, mientras que el presentador `Api:OAuth` se asigna a la clase `App\Api\OAuthPresenter`. -Es más práctico crear una regla general (estrella) para sustituir a las dos primeras. El asterisco adicional se añadirá a la máscara de clase sólo para el módulo: +Puesto que los módulos `Front` y `Admin` tienen un enfoque de asignación similar y es probable que haya más módulos de este tipo, es posible crear una regla general que los sustituya. Se añade un nuevo asterisco para el módulo a la máscara de la clase: ```neon application: mapping: - *: App\Modules\*\Presenters\*Presenter + *: App\Presentation\*\**Presenter Api: App\Api\*Presenter ``` -Pero, ¿y si utilizamos módulos anidados y tenemos un presentador `Admin:User:Edit`? En este caso, el segmento con un asterisco que representa el módulo para cada nivel simplemente se repite y el resultado es la clase `App\Modules\Admin\User\Presenters\EditPresenter`. +Para los módulos anidados de varios niveles, como el presentador `Admin:User:Edit`, el segmento del asterisco se repite para cada nivel, lo que da como resultado la clase `App\Presentation\Admin\User\Edit\EditPresenter`. -Una notación alternativa es utilizar una matriz formada por tres segmentos en lugar de una cadena. Esta notación es equivalente a la anterior: +Una notación alternativa consiste en utilizar una matriz compuesta por tres segmentos en lugar de una cadena. Esta notación es equivalente a la anterior: ```neon application: mapping: - *: [App\Modules, *, Presenters\*Presenter] + *: [App\UI, *, **Presenter] + Api: [App\Api, '', *Presenter] ``` -El valor por defecto es `*Module\*Presenter`. +Si sólo tenemos una regla en la configuración, la general, podemos escribir brevemente: + +```neon +application: + mapping: App\Presentation\*\**Presenter +``` diff --git a/application/es/templates.texy b/application/es/templates.texy index 761f7a648e..64f9cf67c1 100644 --- a/application/es/templates.texy +++ b/application/es/templates.texy @@ -34,35 +34,81 @@ Y esta podría ser la plantilla de acción: Define el bloque `content`, que se inserta en lugar de `{include content}` en el diseño, y también redefine el bloque `title`, que sobrescribe `{block title}` en el diseño. Intenta imaginar el resultado. -Búsqueda de plantillas .[#toc-search-for-templates] ---------------------------------------------------- +Búsqueda de plantillas .[#toc-template-lookup] +---------------------------------------------- -La ruta a las plantillas se deduce según una lógica simple. Se intenta ver si uno de estos archivos de plantilla existe en relación con el directorio donde se encuentra la clase de presentador, donde `` es el nombre del presentador actual y `` es el nombre de la acción actual: +En los presentadores, no es necesario especificar qué plantilla debe renderizarse; el framework determinará automáticamente la ruta, facilitándole la codificación. -- `templates//.latte` -- `templates/..latte` +Si utiliza una estructura de directorios donde cada presentador tiene su propio directorio, simplemente coloque la plantilla en este directorio bajo el nombre de la acción (es decir, vista). Por ejemplo, para la acción `default`, utilice la plantilla `default.latte`: -Si no se encuentra la plantilla, se intentará buscar en el directorio `templates` un nivel más arriba, es decir, al mismo nivel que el directorio con la clase presentadora. +/--pre +app/ +└── Presentation/ + └── Home/ + ├── HomePresenter.php + └── default.latte +\-- -Si la plantilla tampoco se encuentra allí, la respuesta es un [error 404 |presenters#Error 404 etc.]. +Si utiliza una estructura en la que los presentadores están juntos en un directorio y las plantillas en una carpeta `templates`, guárdela en un archivo `..latte` o en `/.latte`: -También puede cambiar la vista utilizando `$this->setView('otherView')`. O, en lugar de buscar, especifique directamente el nombre del archivo de plantilla utilizando `$this->template->setFile('/path/to/template.latte')`. +/--pre +app/ +└── Presenters/ + ├── HomePresenter.php + └── templates/ + ├── Home.default.latte ← 1st variant + └── Home/ + └── default.latte ← 2nd variant +\-- + +El directorio `templates` también puede colocarse un nivel más arriba, al mismo nivel que el directorio con las clases de presentador. + +Si no se encuentra la plantilla, el presentador responde con el [error 404 - página no encontrada |presenters#Error 404 etc]. + +Puede cambiar la vista utilizando `$this->setView('anotherView')`. También es posible especificar directamente el archivo de plantilla con `$this->template->setFile('/path/to/template.latte')`. .[note] -Puede cambiar las rutas donde se buscan las plantillas anulando el método [formatTemplateFiles |api:Nette\Application\UI\Presenter::formatTemplateFiles()], que devuelve una matriz de posibles rutas de archivo. +Los archivos en los que se buscan las plantillas pueden cambiarse anulando el método [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()], que devuelve una matriz de posibles nombres de archivo. + + +Búsqueda de plantillas de diseño .[#toc-layout-template-lookup] +--------------------------------------------------------------- + +Nette también busca automáticamente el archivo de diseño. + +Si utiliza una estructura de directorios en la que cada presentador tiene su propio directorio, coloque la maqueta en la carpeta con el presentador, si es específica sólo para él, o en un nivel superior si es común a varios presentadores: + +/--pre +app/ +└── Presentation/ + ├── @layout.latte ← common layout + └── Home/ + ├── @layout.latte ← only for Home presenter + ├── HomePresenter.php + └── default.latte +\-- + +Si utiliza una estructura en la que los presentadores están agrupados en un directorio y las plantillas se encuentran en una carpeta `templates`, la maquetación se esperará en los siguientes lugares: -El diseño se espera en los siguientes archivos: +/--pre +app/ +└── Presenters/ + ├── HomePresenter.php + └── templates/ + ├── @layout.latte ← common layout + ├── Home.@layout.latte ← only for Home, 1st variant + └── Home/ + └── @layout.latte ← only for Home, 2nd variant +\-- -- `templates//@.latte` -- `templates/.@.latte` -- `templates/@.latte` diseño común a varios presentadores +Si el presentador está en un [módulo |modules], también buscará más arriba en el árbol de directorios según el anidamiento del módulo. -`` es el nombre del presentador actual y `` es el nombre de la maquetación, que por defecto es `'layout'`. El nombre puede cambiarse con `$this->setLayout('otherLayout')`, de modo que se intentarán los archivos `@otherLayout.latte`. +El nombre de la presentación puede cambiarse utilizando `$this->setLayout('layoutAdmin')` y entonces se esperará en el archivo `@layoutAdmin.latte`. También puede especificar directamente el archivo de plantilla de presentación utilizando `$this->setLayout('/path/to/template.latte')`. -También puede especificar directamente el nombre de archivo de la plantilla de maquetación con `$this->setLayout('/path/to/template.latte')`. El uso de `$this->setLayout(false)` desactivará la búsqueda de diseños. +El uso de `$this->setLayout(false)` o de la etiqueta `{layout none}` dentro de la plantilla desactiva la búsqueda de diseños. .[note] -Puede cambiar las rutas donde se buscan las plantillas anulando el método [formatLayoutTemplateFiles |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], que devuelve una matriz de posibles rutas de archivo. +Los archivos en los que se buscan las plantillas de diseño pueden modificarse modificando el método [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], que devuelve una matriz de posibles nombres de archivo. Variables en la plantilla .[#toc-variables-in-the-template] @@ -104,7 +150,7 @@ La anotación `@property-read` es para IDE y análisis estático, hará que func Puedes permitirte el lujo de susurrar en las plantillas también, simplemente instala el plugin Latte en PhpStorm y especifica el nombre de la clase al principio de la plantilla, ver el artículo "Latte: cómo escribir sistema:https://blog.nette.org/es/latte-como-utilizar-el-sistema-de-tipos": ```latte -{templateType App\Presenters\ArticleTemplate} +{templateType App\Presentation\Article\ArticleTemplate} ... ``` @@ -176,7 +222,7 @@ public function beforeRender(): void La versión 3 de Latte ofrece una forma más avanzada creando una [extensión |latte:creating-extension] para cada proyecto web. He aquí un ejemplo aproximado de una clase de este tipo: ```php -namespace App\Templating; +namespace App\Presentation\Accessory; final class LatteExtension extends Latte\Extension { @@ -214,7 +260,7 @@ La registramos usando [configuration|configuration#Latte]: ```neon latte: extensions: - - App\Templating\LatteExtension + - App\Presentation\Accessory\LatteExtension ``` diff --git a/application/fr/how-it-works.texy b/application/fr/how-it-works.texy index 9c4358110a..a0efee1aad 100644 --- a/application/fr/how-it-works.texy +++ b/application/fr/how-it-works.texy @@ -22,13 +22,13 @@ La structure des répertoires ressemble à ceci : /--pre web-project/ ├── app/ ← répertoire avec application -│ ├── Presenters/ ← classes d'presenter -│ │ ├── HomePresenter.php ← Home classe des présentateurs -│ │ └── templates/ ← répertoire des modèles -│ │ ├── @layout.latte ← modèle de disposition partagée -│ │ └── Home/ ← Modèles pour le présentateur de la page d'accueil -│ │ └── default.latte ← modèle pour l'action `default` -│ ├── Router/ ← configuration des adresses URL +│ ├── Core/ ← basic necessary classes +│ │ └── RouterFactory.php ← configuration des adresses URL +│ ├── Presentation/ ← presenters, templates & co. +│ │ ├─── @layout.latte ← template of shared layout +│ │ └── Home/ ← Home presenter directory +│ │ ├── HomePresenter.php ← Classe Home Presenter +│ │ └── default.latte ← template for action default │ └── Bootstrap.php ← classe de démarrage Bootstrap ├── bin/ ← scripts pour la ligne de commande ├── config/ ← configuration files @@ -91,7 +91,7 @@ Les applications écrites dans Nette sont divisées en plusieurs présentateurs L'application commence par demander à ce qu'on appelle le routeur de décider lequel des présentateurs doit transmettre la demande actuelle pour traitement. Le routeur décide de la responsabilité qui lui incombe. Il examine l'URL d'entrée `https://example.com/product/123`, qui veut `show` un produit avec `id: 123` comme action. C'est une bonne habitude d'écrire une paire présentateur + action séparée par un deux-points comme `Product:show`. -Le routeur transforme donc l'URL en une paire `Presenter:action` + paramètres, dans notre cas `Product:show` + `id: 123`. Vous pouvez voir à quoi ressemble un routeur dans le fichier `app/Router/RouterFactory.php` et nous le décrirons en détail dans le chapitre [Routage |Routing]. +Le routeur transforme donc l'URL en une paire `Presenter:action` + paramètres, dans notre cas `Product:show` + `id: 123`. Vous pouvez voir à quoi ressemble un routeur dans le fichier `app/Core/RouterFactory.php` et nous le décrirons en détail dans le chapitre [Routage |Routing]. Continuons. L'application connaît déjà le nom du présentateur et peut continuer. En créant un objet `ProductPresenter`, qui est le code du présentateur `Product`. Plus précisément, elle demande au conteneur DI de créer le présentateur, car la production d'objets est son travail. @@ -121,12 +121,9 @@ Ainsi, la méthode `renderShow(123)` a été appelée, dont le code est un exemp Ensuite, le présentateur renvoie la réponse. Cela peut être une page HTML, une image, un document XML, l'envoi d'un fichier depuis le disque, JSON ou la redirection vers une autre page. Il est important de noter que si nous ne disons pas explicitement comment répondre (ce qui est le cas de `ProductPresenter`), la réponse sera de rendre le modèle avec une page HTML. Pourquoi ? Eh bien, parce que dans 99% des cas, nous voulons dessiner un modèle, donc le présentateur prend ce comportement par défaut et veut nous faciliter le travail. C'est le point de vue de Nette. -Nous n'avons même pas besoin d'indiquer quel modèle dessiner, il dérive le chemin vers celui-ci selon une logique simple. Dans le cas du présentateur `Product` et de l'action `show`, il essaie de voir si l'un de ces fichiers modèles existe par rapport au répertoire où se trouve la classe `ProductPresenter`: +Il n'est même pas nécessaire de spécifier le modèle à rendre ; le framework déduira lui-même le chemin d'accès. Dans le cas de l'action `show`, il essaie simplement de charger le modèle `show.latte` dans le répertoire contenant la classe `ProductPresenter`. Il tente également de trouver la mise en page dans le fichier `@layout.latte` (plus d'informations sur la [recherche de modèles |templates#Template Lookup]). -- `templates/Product/show.latte` -- `templates/Product.show.latte` - -Il essaiera également de trouver la mise en page dans le fichier `@layout.latte`, puis il effectuera le rendu du modèle. La tâche du présentateur et de l'ensemble de l'application est maintenant terminée. Si le modèle n'existe pas, une page d'erreur 404 sera renvoyée. Vous pouvez en savoir plus sur les présentateurs sur la page [Présentateurs |Presenters]. +Ensuite, les modèles sont rendus. La tâche du présentateur et de l'ensemble de l'application est ainsi achevée et le travail est terminé. Si le modèle n'existait pas, une page d'erreur 404 serait renvoyée. Pour en savoir plus sur les présentateurs, consultez la page [Présentateurs |presenters]. [* request-flow.svg *] @@ -137,7 +134,7 @@ Juste pour être sûr, essayons de récapituler l'ensemble du processus avec une 3) le routeur décode l'URL comme une paire `Home:default` 4) un objet `HomePresenter` est créé 5) la méthode `renderDefault()` est appelée (si elle existe) -6) un modèle `templates/Home/default.latte` avec une mise en page `templates/@layout.latte` est rendu +6) un modèle `default.latte` avec une mise en page `@layout.latte` est rendu Vous avez peut-être rencontré beaucoup de nouveaux concepts maintenant, mais nous pensons qu'ils ont un sens. Créer des applications dans Nette est un jeu d'enfant. diff --git a/application/fr/modules.texy b/application/fr/modules.texy index 754e97b5ad..3f9594633a 100644 --- a/application/fr/modules.texy +++ b/application/fr/modules.texy @@ -2,29 +2,31 @@ Modules ******* .[perex] -Dans Nette, les modules représentent les unités logiques qui composent une application. Ils comprennent des présentateurs, des modèles, éventuellement aussi des composants et des classes de modèles. +Les modules apportent de la clarté aux applications Nette en facilitant la division en unités logiques. -Un répertoire pour les présentateurs et un autre pour les modèles ne seraient pas suffisants pour les projets réels. Avoir des dizaines de fichiers dans un seul dossier est pour le moins inorganisé. Comment s'en sortir ? Il suffit de les répartir en sous-répertoires sur le disque et en espaces de noms dans le code. Et c'est exactement ce que font les modules Nette. - -Oublions donc le dossier unique pour les présentateurs et les modèles et créons plutôt des modules, par exemple `Admin` et `Front`. +À l'instar de l'organisation des fichiers en dossiers sur un disque dur, Nette permet de diviser les présentateurs, les modèles et les autres classes auxiliaires en modules. Comment cela fonctionne-t-il en pratique ? Simplement en incorporant de nouveaux sous-répertoires dans la structure. Voici un exemple de structure avec deux modules, Front et Admin : /--pre -app/ -├── Presenters/ -├── Modules/ ← répertoire avec les modules -│ ├── Admin/ ← module Admin -│ │ ├── Presenters/ ← ses présentateurs -│ │ │ ├── DashboardPresenter.php -│ │ │ └── templates/ -│ └── Front/ ← module Front -│ └── Presenters/ ← ses présentateurs -│ └── ... +app/ +├── Presentation/ +│ ├── Admin/ ← Admin module +│ │ ├── @layout.latte +│ │ ├── Dashboard/ +│ │ │ ├── DashboardPresenter.php +│ │ │ └── default.latte +│ │ └── ... +│ ├── Front/ ← Front module +│ │ ├── @layout.latte +│ │ ├── Home/ +│ │ │ ├── HomePresenter.php +│ │ │ └── default.latte +│ │ └── ... \-- -Cette structure de répertoire sera reflétée par les espaces de noms des classes, ainsi par exemple `DashboardPresenter` sera dans l'espace de noms `App\Modules\Admin\Presenters`: +Cette structure de répertoires se reflète dans les espaces de noms des classes. Ainsi, par exemple, `DashboardPresenter` est situé dans l'espace de noms `App\Presentation\Admin\Dashboard`: ```php -namespace App\Modules\Admin\Presenters; +namespace App\Presentation\Admin\Dashboard; class DashboardPresenter extends Nette\Application\UI\Presenter { @@ -32,35 +34,49 @@ class DashboardPresenter extends Nette\Application\UI\Presenter } ``` -Le présentateur `Dashboard` dans le module `Admin` est référencé dans l'application en utilisant la notation deux points comme `Admin:Dashboard`, et son action `default` comme `Admin:Dashboard:default`. -Et comment Nette proper sait-elle que `Admin:Dashboard` représente la classe `App\Modules\Admin\Presenters\DashboardPresenter`? Cela est déterminé par le [mappage |#mapping] dans la configuration. -Ainsi, la structure donnée n'est pas figée et vous pouvez la modifier en fonction de vos besoins. +Dans l'application, nous faisons référence au présentateur `Dashboard` dans le module `Admin` en utilisant la notation des deux points comme `Admin:Dashboard`. Pour son action `default`, nous l'appelons `Admin:Dashboard:default`. -Les modules peuvent bien sûr contenir tous les éléments autres que les présentateurs et les modèles, tels que les composants, les classes de modèles, etc. +La structure présentée n'est pas rigide ; vous pouvez [l'adapter entièrement à vos besoins |#mapping] dans la configuration. .[tip] + +Les modules peuvent inclure tous les autres fichiers, tels que les composants et les classes auxiliaires, en plus des présentateurs et des modèles. Si vous vous demandez où placer ces derniers, envisagez d'utiliser un dossier `Accessory`: + +/--pre +app/ +├── Presentation/ +│ ├── Admin/ +│ │ ├── Accessory/ +│ │ │ ├── FormFactory.php +│ │ │ └── AdminLayout.php +│ │ ├── Dashboard/ +│ │ └── ... +\-- Modules imbriqués .[#toc-nested-modules] ---------------------------------------- -Les modules ne doivent pas uniquement former une structure plate, vous pouvez également créer des sous-modules, par exemple : +Les modules peuvent avoir plusieurs niveaux d'imbrication, comme la structure d'un répertoire sur un disque : /--pre -app/ -├── Modules/ ← répertoire avec les modules -│ ├── Blog/ ← module Blog -│ │ ├── Admin/ ← sous-module Admin -│ │ │ ├── Presenters/ +app/ +├── Presentation/ +│ ├── Blog/ ← Blog module +│ │ ├── Admin/ ← Admin submodule +│ │ │ ├── Dashboard/ +│ │ │ └── ... +│ │ ├── Front/ ← Front submodule +│ │ │ ├── @layout.latte +│ │ │ ├── Home/ │ │ │ └── ... -│ │ └── Front/ ← sous-module Front -│ │ ├── Presenters/ -│ │ └── ... -│ ├── Forum/ ← module Forum +│ ├── Forum/ ← Forum module │ │ └── ... \-- -Ainsi, le module `Blog` est divisé en sous-modules `Admin` et `Front`. Là encore, cela se reflétera dans les espaces de noms, qui seront `App\Modules\Blog\Admin\Presenters` etc. Le présentateur `Dashboard` à l'intérieur du sous-module est désigné par `Blog:Admin:Dashboard`. +Le module `Blog` est divisé en sous-modules `Admin` et `Front`. Cela se reflète également dans les espaces de noms, qui apparaissent alors comme `App\Presentation\Blog\Admin` et similaires. Pour désigner le présentateur `Dashboard` au sein du sous-module `Admin`, nous l'appelons `Blog:Admin:Dashboard`. -L'imbrication peut aller aussi loin que vous le souhaitez, de sorte que des sous-sous-modules peuvent être créés. +L'imbrication peut être aussi poussée que nécessaire, ce qui permet de créer des sous-sous-modules. + +Par exemple, si dans l'administration vous avez de nombreux présentateurs liés à la gestion des commandes, tels que `OrderDetail`, `OrderEdit`, `OrderDispatch`, etc., vous pouvez créer un module `Order` dans lequel les présentateurs tels que `Detail`, `Edit`, `Dispatch`, et d'autres seront organisés. Création de liens .[#toc-creating-links] @@ -102,46 +118,66 @@ Voir le [chapitre sur le routage |routing#Modules]. Cartographie .[#toc-mapping] ---------------------------- -Définit les règles par lesquelles le nom de la classe est dérivé du nom du présentateur. On les inscrit dans la [configuration] sous la clé `application › mapping`. +Le mappage définit les règles permettant de dériver le nom de la classe à partir du nom du présentateur. Ces règles sont spécifiées dans la [configuration |configuration] sous la clé `application › mapping`. + +Les structures de répertoire mentionnées plus haut sur cette page sont basées sur la correspondance suivante : + +```neon +application: + mapping: App\Presentation\*\**Presenter +``` -Commençons par un exemple qui n'utilise pas de modules. Nous voulons simplement que les classes du présentateur aient l'espace de nom `App\Presenters`. Cela signifie qu'un présentateur tel que `Home` doit correspondre à la classe `App\Presenters\HomePresenter`. Ceci peut être réalisé par la configuration suivante : +Comment fonctionne la cartographie ? Pour mieux comprendre, imaginons d'abord une application sans modules. Nous voulons que les classes de présentateurs relèvent de l'espace de noms `App\UI`, de sorte que le présentateur `Home` soit associé à la classe `App\Presentation\HomePresenter`. Cette configuration permet d'atteindre cet objectif : ```neon application: - mapping: App\Presenters\*Presenter + mapping: App\Presentation\*Presenter ``` -Le nom du présentateur est remplacé par l'astérisque dans le masque de classe et le résultat est le nom de la classe. Facile ! +Ce mappage fonctionne en remplaçant l'astérisque du masque `App\Presentation\*Presenter` par le nom du présentateur `Home`, ce qui donne le nom de classe final `App\Presentation\HomePresenter`. C'est simple ! + +Cependant, comme vous pouvez le voir dans les exemples de ce chapitre et d'autres chapitres, nous plaçons les classes de présentateurs dans des sous-répertoires éponymes, par exemple, le présentateur `Home` est associé à la classe `App\Presentation\Home\HomePresenter`. Pour ce faire, il suffit de doubler l'astérisque (Nette Application 3.2 requise) : + +```neon +application: + mapping: App\Presentation\**Presenter +``` -Si nous divisons les présentateurs en modules, nous pouvons avoir notre propre mappage pour chaque module : +Passons maintenant au mappage des présentateurs dans les modules. Nous pouvons définir des correspondances spécifiques pour chaque module : ```neon application: mapping: - Front: App\Modules\Front\Presenters\*Presenter - Admin: App\Modules\Admin\Presenters\*Presenter + Front: App\Presentation\Front\**Presenter + Admin: App\Presentation\Admin\**Presenter Api: App\Api\*Presenter ``` -Maintenant, le présentateur `Front:Home` correspond à la classe `App\Modules\Front\Presenters\HomePresenter` et le présentateur `Admin:Dashboard` à la classe `App\Modules\Admin\Presenters\DashboardPresenter`. +Selon cette configuration, le présentateur `Front:Home` correspond à la classe `App\Presentation\Front\Home\HomePresenter`, tandis que le présentateur `Api:OAuth` correspond à la classe `App\Api\OAuthPresenter`. -Il est plus pratique de créer une règle générale (étoile) pour remplacer les deux premières. L'astérisque supplémentaire sera ajouté au masque de classe uniquement pour le module : +Étant donné que les modules `Front` et `Admin` ont une approche de mappage similaire et qu'il est probable qu'il y ait d'autres modules de ce type, il est possible de créer une règle générale qui les remplace. Un nouvel astérisque pour le module est ajouté au masque de classe : ```neon application: mapping: - *: App\Modules\*\Presenters\*Presenter + *: App\Presentation\*\**Presenter Api: App\Api\*Presenter ``` -Mais qu'en est-il si nous utilisons des modules imbriqués et que nous avons un présentateur `Admin:User:Edit`? Dans ce cas, le segment avec un astérisque représentant le module pour chaque niveau est simplement répété et le résultat est la classe `App\Modules\Admin\User\Presenters\EditPresenter`. +Pour les modules imbriqués à plusieurs niveaux, tels que le présentateur `Admin:User:Edit`, le segment astérisque se répète pour chaque niveau, ce qui donne la classe `App\Presentation\Admin\User\Edit\EditPresenter`. -Une notation alternative consiste à utiliser un tableau composé de trois segments au lieu d'une chaîne de caractères. Cette notation est équivalente à la précédente : +Une autre notation consiste à utiliser un tableau composé de trois segments au lieu d'une chaîne. Cette notation est équivalente à la précédente : ```neon application: mapping: - *: [App\Modules, *, Presenters\*Presenter] + *: [App\UI, *, **Presenter] + Api: [App\Api, '', *Presenter] ``` -La valeur par défaut est `*Module\*Presenter`. +Si nous n'avons qu'une seule règle dans la configuration, la règle générale, nous pouvons l'écrire brièvement : + +```neon +application: + mapping: App\Presentation\*\**Presenter +``` diff --git a/application/fr/templates.texy b/application/fr/templates.texy index 8ecd733495..a4fe2de447 100644 --- a/application/fr/templates.texy +++ b/application/fr/templates.texy @@ -34,35 +34,81 @@ Et ceci pourrait être le modèle d'action : Il définit le bloc `content`, qui est inséré à la place de `{include content}` dans la mise en page, et redéfinit également le bloc `title`, qui écrase `{block title}` dans la mise en page. Essayez d'imaginer le résultat. -Recherche de modèles .[#toc-search-for-templates] -------------------------------------------------- +Recherche de modèles .[#toc-template-lookup] +-------------------------------------------- -Le chemin vers les modèles est déduit selon une logique simple. Il essaie de voir si l'un de ces fichiers modèles existe par rapport au répertoire où se trouve la classe du présentateur, où `` est le nom du présentateur actuel et `` est le nom de l'action en cours : +Dans les présentateurs, vous n'avez pas besoin de spécifier quel modèle doit être rendu ; le cadre détermine automatiquement le chemin, ce qui facilite le codage. -- `templates//.latte` -- `templates/..latte` +Si vous utilisez une structure de répertoires dans laquelle chaque présentateur a son propre répertoire, placez simplement le modèle dans ce répertoire sous le nom de l'action (c'est-à-dire de la vue). Par exemple, pour l'action `default`, utilisez le modèle `default.latte`: -Si le modèle n'est pas trouvé, il essaiera de chercher dans le répertoire `templates` au niveau supérieur, c'est-à-dire au même niveau que le répertoire contenant la classe du présentateur. +/--pre +app/ +└── Presentation/ + └── Home/ + ├── HomePresenter.php + └── default.latte +\-- -Si le modèle n'y est pas trouvé non plus, la réponse est une [erreur 404 |presenters#Error 404 etc.]. +Si vous utilisez une structure dans laquelle les présentateurs sont regroupés dans un répertoire et les modèles dans un dossier `templates`, enregistrez-les dans un fichier `..latte` soit dans un fichier `/.latte`: -Vous pouvez également changer la vue en utilisant `$this->setView('otherView')`. Ou, au lieu de chercher, spécifiez directement le nom du fichier de modèle en utilisant `$this->template->setFile('/path/to/template.latte')`. +/--pre +app/ +└── Presenters/ + ├── HomePresenter.php + └── templates/ + ├── Home.default.latte ← 1st variant + └── Home/ + └── default.latte ← 2nd variant +\-- + +Le répertoire `templates` peut également être placé un niveau plus haut, au même niveau que le répertoire des classes de présentateurs. + +Si le modèle n'est pas trouvé, le présentateur répond par l'[erreur 404 - page non trouvée |presenters#Error 404 etc]. + +Vous pouvez changer la vue en utilisant `$this->setView('anotherView')`. Il est également possible de spécifier directement le fichier de modèle avec `$this->template->setFile('/path/to/template.latte')`. .[note] -Vous pouvez modifier les chemins dans lesquels les modèles sont recherchés en remplaçant la méthode [formatTemplateFiles |api:Nette\Application\UI\Presenter::formatTemplateFiles()], qui renvoie un tableau de chemins de fichiers possibles. +Les fichiers dans lesquels les modèles sont recherchés peuvent être modifiés en remplaçant la méthode [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()], qui renvoie un tableau de noms de fichiers possibles. + + +Recherche de modèles de mise en page .[#toc-layout-template-lookup] +------------------------------------------------------------------- + +Nette recherche également automatiquement le fichier de mise en page. + +Si vous utilisez une structure de répertoires dans laquelle chaque présentateur a son propre répertoire, placez le modèle soit dans le dossier du présentateur, s'il lui est propre, soit à un niveau supérieur s'il est commun à plusieurs présentateurs : + +/--pre +app/ +└── Presentation/ + ├── @layout.latte ← common layout + └── Home/ + ├── @layout.latte ← only for Home presenter + ├── HomePresenter.php + └── default.latte +\-- + +Si vous utilisez une structure dans laquelle les présentateurs sont regroupés dans un répertoire et les modèles dans un dossier `templates`, la mise en page sera attendue aux endroits suivants : -Le modèle est attendu dans les fichiers suivants : +/--pre +app/ +└── Presenters/ + ├── HomePresenter.php + └── templates/ + ├── @layout.latte ← common layout + ├── Home.@layout.latte ← only for Home, 1st variant + └── Home/ + └── @layout.latte ← only for Home, 2nd variant +\-- -- `templates//@.latte` -- `templates/.@.latte` -- `templates/@.latte` mise en page commune à plusieurs présentateurs +Si le présentateur se trouve dans un [module |modules], il cherchera également plus haut dans l'arborescence du répertoire en fonction de l'imbrication du module. -`` est le nom du présentateur actuel et `` est le nom de la mise en page, qui est par défaut `'layout'`. Le nom peut être modifié avec `$this->setLayout('otherLayout')`, de sorte que les fichiers `@otherLayout.latte` seront essayés. +Le nom de la présentation peut être modifié à l'aide de `$this->setLayout('layoutAdmin')` et sera alors attendu dans le fichier `@layoutAdmin.latte`. Vous pouvez également spécifier directement le fichier de modèle de présentation en utilisant `$this->setLayout('/path/to/template.latte')`. -Vous pouvez également spécifier directement le nom du fichier du modèle de présentation en utilisant `$this->setLayout('/path/to/template.latte')`. L'utilisation de `$this->setLayout(false)` désactivera la recherche de la mise en page. +L'utilisation de `$this->setLayout(false)` ou de la balise `{layout none}` à l'intérieur du modèle désactive la recherche de modèle. .[note] -Vous pouvez modifier les chemins dans lesquels les modèles sont recherchés en remplaçant la méthode [formatLayoutTemplateFiles |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], qui renvoie un tableau de chemins de fichiers possibles. +Les fichiers dans lesquels les modèles de présentation sont recherchés peuvent être modifiés en remplaçant la méthode [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], qui renvoie un tableau de noms de fichiers possibles. Variables dans le modèle .[#toc-variables-in-the-template] @@ -104,7 +150,7 @@ L'annotation `@property-read` est pour les IDE et l'analyse statique, elle fera Vous pouvez aussi vous offrir le luxe de chuchoter dans les templates, il suffit d'installer le plugin Latte dans PhpStorm et de spécifier le nom de la classe au début du template, voir l'article "Latte : how to type system":https://blog.nette.org/fr/latte-comment-utiliser-le-systeme-de-type: ```latte -{templateType App\Presenters\ArticleTemplate} +{templateType App\Presentation\Article\ArticleTemplate} ... ``` @@ -176,7 +222,7 @@ public function beforeRender(): void Latte version 3 propose un moyen plus avancé en créant une [extension |latte:creating-extension] pour chaque projet web. Voici un exemple approximatif d'une telle classe : ```php -namespace App\Templating; +namespace App\Presentation\Accessory; final class LatteExtension extends Latte\Extension { @@ -214,7 +260,7 @@ Nous l'enregistrons en utilisant la [configuration |configuration#Latte]: ```neon latte: extensions: - - App\Templating\LatteExtension + - App\Presentation\Accessory\LatteExtension ``` diff --git a/application/hu/how-it-works.texy b/application/hu/how-it-works.texy index 5101363032..a5f6c1c2e9 100644 --- a/application/hu/how-it-works.texy +++ b/application/hu/how-it-works.texy @@ -22,13 +22,13 @@ A könyvtárszerkezet valahogy így néz ki: /--pre web-project/ ├── app/ ← directory with application -│ ├── Presenters/ ← presenter classes -│ │ ├── HomePresenter.php ← Home presenter class -│ │ └── templates/ ← templates directory -│ │ ├── @layout.latte ← template of shared layout -│ │ └── Home/ ← templates for Home presenter -│ │ └── default.latte ← template for action `default` -│ ├── Router/ ← configuration of URL addresses +│ ├── Core/ ← alapvető szükséges osztályok +│ │ └── RouterFactory.php ← URL címek konfigurálása +│ ├── Presentation/ ← prezenterek, sablonok és társai. +│ │ ├── @layout.latte ← a megosztott elrendezés sablonja +│ │ └── Home/ ← Főoldal bemutatókönyvtár +│ │ ├── HomePresenter.php ← Home prezenter osztály +│ │ └── default.latte ← cselekvési sablon default │ └── Bootstrap.php ← booting class Bootstrap ├── bin/ ← scripts for the command line ├── config/ ← configuration files @@ -91,7 +91,7 @@ A Nette-ben írt alkalmazások sok úgynevezett prezenterre oszlanak (más keret Az alkalmazás azzal indul, hogy az ún. routertől kéri, hogy döntse el, hogy az aktuális kérést melyik prezenternek adja át feldolgozásra. A router dönti el, hogy kinek a felelőssége. Megnézi a bemeneti URL-t `https://example.com/product/123`, aki a `show` egy terméket `id: 123` művelettel akarja ellátni. Jó szokás a prezenter + akció párokat kettősponttal elválasztva `Product:show`-ként írni. -Tehát a router az URL-t átalakította `Presenter:action` + paraméterek párrá, esetünkben `Product:show` + `id: 123`. A `app/Router/RouterFactory.php` fájlban láthatjuk, hogyan néz ki egy útválasztó, és ezt részletesen az [Útválasztás |Routing] fejezetben fogjuk leírni. +Tehát a router az URL-t átalakította `Presenter:action` + paraméterek párrá, esetünkben `Product:show` + `id: 123`. A `app/Core/RouterFactory.php` fájlban láthatjuk, hogyan néz ki egy útválasztó, és ezt részletesen az [Útválasztás |Routing] fejezetben fogjuk leírni. Lépjünk tovább. Az alkalmazás már ismeri a bemutató nevét, és folytathatja. Egy `ProductPresenter` objektum létrehozásával, amely a `Product` bemutató kódja. Pontosabban megkéri a DI konténert a prezenter létrehozására, mert az objektumok előállítása az ő feladata. @@ -121,12 +121,9 @@ Tehát a `renderShow(123)` metódust hívtuk meg, amelynek kódja fiktív példa Ezt követően a prezenter visszaadja a választ. Ez lehet egy HTML oldal, egy kép, egy XML dokumentum, egy fájl elküldése a lemezről, JSON vagy egy másik oldalra való átirányítás. Fontos, hogy ha nem mondjuk meg kifejezetten, hogyan kell válaszolni (ami a `ProductPresenter` esetében a helyzet), akkor a válasz az lesz, hogy a sablon egy HTML-oldallal jeleníti meg a sablont. Hogy miért? Nos, mert az esetek 99%-ában egy sablont szeretnénk kirajzolni, így a prezentáló ezt a viselkedést veszi alapértelmezettnek, és a mi munkánkat akarja megkönnyíteni. Ez a Nette lényege. -Még csak meg sem kell adnunk, hogy melyik sablont rajzoljuk ki, egyszerű logika szerint levezeti az oda vezető utat. A presenter `Product` és az action `show` esetében megnézi, hogy létezik-e valamelyik sablonfájl a `ProductPresenter` osztály könyvtárához képest, ahol a osztály található: +Még azt sem kell megadnunk, hogy melyik sablont kell megjelenítenünk; a keretrendszer magától levonja az útvonalat. A `show` akció esetében egyszerűen megpróbálja betölteni a `show.latte` sablont a `ProductPresenter` osztályt tartalmazó könyvtárban. Megpróbálja megtalálni az elrendezést is a `@layout.latte` fájlban (a [sablonkeresésről |templates#Template Lookup] bővebben). -- `templates/Product/show.latte` -- `templates/Product.show.latte` - -Megpróbálja megtalálni az elrendezést is a `@layout.latte` fájlban, majd rendereli a sablont. Ezzel a prezenter és az egész alkalmazás feladata befejeződött. Ha a sablon nem létezik, akkor egy 404-es hibaüzenetű oldal fog visszakerülni. A prezenterekről bővebben a [Prezenterek |Presenters] oldalon olvashat. +Ezt követően a sablonok megjelenítésre kerülnek. Ezzel a bemutató és az egész alkalmazás feladata befejeződik, és a munka elvégeztetett. Ha a sablon nem létezne, akkor egy 404-es hibaoldalt kapna vissza. A prezenterekről bővebben a [Prezenterek |presenters] oldalon olvashat. [* request-flow.svg *] @@ -137,7 +134,7 @@ A biztonság kedvéért próbáljuk meg az egész folyamatot egy kicsit más URL 3) a router dekódolja az URL-t, mint egy párat `Home:default` 4) létrejön egy `HomePresenter` objektum 5) a `renderDefault()` metódust meghívjuk (ha létezik) -6) egy `templates/Home/default.latte` sablon `templates/@layout.latte` elrendezéssel megjelenik. +6) egy `default.latte` sablon `@layout.latte` elrendezéssel megjelenik. Lehet, hogy most sok új fogalommal találkoztál, de úgy gondoljuk, hogy van értelme. Az alkalmazások létrehozása a Nette-ben gyerekjáték. diff --git a/application/hu/modules.texy b/application/hu/modules.texy index e4ec0d80aa..cb779a2b01 100644 --- a/application/hu/modules.texy +++ b/application/hu/modules.texy @@ -2,29 +2,31 @@ Modulok ******* .[perex] -A Nette-ben a modulok az alkalmazást alkotó logikai egységeket jelentik. Ide tartoznak a prezenterek, sablonok, esetleg komponensek és modellosztályok. +A modulok a Nette-alkalmazások áttekinthetőségét segítik elő azáltal, hogy megkönnyítik a logikai egységekre való egyszerű felosztást. -Egy könyvtár a bemutatóknak és egy a sablonoknak nem lenne elég a valódi projektekhez. Több tucat fájl egy mappában való elhelyezése legalábbis rendezetlen. Hogyan szabadulhatunk meg ettől? Egyszerűen felosztjuk őket alkönyvtárakra a lemezen és névterekre a kódban. És pontosan ezt teszik a Nette modulok. - -Felejtsük el tehát az egyetlen mappát az előadóknak és a sablonoknak, és helyette hozzunk létre modulokat, például a `Admin` és a `Front`. +Hasonlóan a fájlok mappákba rendezéséhez a merevlemezen, a Nette-ben modulokba oszthatjuk a prezentereket, sablonokat és más segédosztályokat. Hogyan működik ez a gyakorlatban? Egyszerűen úgy, hogy új alkönyvtárakat építünk be a struktúrába. Íme egy példa egy struktúrára két modullal, a Front és az Admin modulokkal: /--pre -app/ -├── Presenters/ -├── Modules/ ← directory with modules -│ ├── Admin/ ← module Admin -│ │ ├── Presenters/ ← its presenters -│ │ │ ├── DashboardPresenter.php -│ │ │ └── templates/ -│ └── Front/ ← module Front -│ └── Presenters/ ← its presenters -│ └── ... +app/ +├── Presentation/ +│ ├── Admin/ ← Admin module +│ │ ├── @layout.latte +│ │ ├── Dashboard/ +│ │ │ ├── DashboardPresenter.php +│ │ │ └── default.latte +│ │ └── ... +│ ├── Front/ ← Front module +│ │ ├── @layout.latte +│ │ ├── Home/ +│ │ │ ├── HomePresenter.php +│ │ │ └── default.latte +│ │ └── ... \-- -Ezt a könyvtárszerkezetet az osztályok névterei is tükrözni fogják, így például a `DashboardPresenter` a `App\Modules\Admin\Presenters` névtérben lesz: +Ez a könyvtárszerkezet tükröződik az osztályok névterében, így például a `DashboardPresenter` a `App\Presentation\Admin\Dashboard` névtérben található: ```php -namespace App\Modules\Admin\Presenters; +namespace App\Presentation\Admin\Dashboard; class DashboardPresenter extends Nette\Application\UI\Presenter { @@ -32,35 +34,49 @@ class DashboardPresenter extends Nette\Application\UI\Presenter } ``` -A `Dashboard` prezenterre a `Admin` modulon belül az alkalmazáson belül a kettőspont jelöléssel `Admin:Dashboard`, a `default` műveletre pedig `Admin:Dashboard:default` néven hivatkozunk. -És honnan tudja a Nette proper, hogy a `Admin:Dashboard` a `App\Modules\Admin\Presenters\DashboardPresenter` osztályt képviseli? Ezt a konfigurációban történő [leképezéssel |#mapping] határozzuk meg. -A megadott struktúra tehát nem keményen meghatározott, és Ön az igényeinek megfelelően módosíthatja. +Az alkalmazásban a `Dashboard` bemutatóra a `Admin` modulon belül a `Admin:Dashboard` kettőspont jelöléssel hivatkozunk a . A `default` műveletére `Admin:Dashboard:default` néven hivatkozunk. -A modulok természetesen a prezentereken és sablonokon kívül minden más elemet is tartalmazhatnak, például komponenseket, modellosztályokat stb. +A bemutatott struktúra nem merev; a konfigurációban [teljes mértékben az igényeihez igazíthatja |#mapping]. .[tip] + +A modulok a prezentereken és sablonokon kívül minden más fájlt, például komponenseket és segédosztályokat is tartalmazhatnak. Ha mérlegeli, hogy hol helyezze el ezeket, fontolja meg a `Accessory` mappa használatát: + +/--pre +app/ +├── Presentation/ +│ ├── Admin/ +│ │ ├── Accessory/ +│ │ │ ├── FormFactory.php +│ │ │ └── AdminLayout.php +│ │ ├── Dashboard/ +│ │ └── ... +\-- Beágyazott modulok .[#toc-nested-modules] ----------------------------------------- -A moduloknak nem kell csak sima struktúrát alkotniuk, létrehozhatunk például almodulokat is: +A modulok több szinten is egymásba ágyazhatók, hasonlóan a lemezen lévő könyvtárstruktúrához: /--pre -app/ -├── Modules/ ← directory with modules -│ ├── Blog/ ← module Blog -│ │ ├── Admin/ ← submodule Admin -│ │ │ ├── Presenters/ +app/ +├── Presentation/ +│ ├── Blog/ ← Blog module +│ │ ├── Admin/ ← Admin submodule +│ │ │ ├── Dashboard/ +│ │ │ └── ... +│ │ ├── Front/ ← Front submodule +│ │ │ ├── @layout.latte +│ │ │ ├── Home/ │ │ │ └── ... -│ │ └── Front/ ← submodule Front -│ │ ├── Presenters/ -│ │ └── ... -│ ├── Forum/ ← module Forum +│ ├── Forum/ ← Forum module │ │ └── ... \-- -Így a `Blog` modul `Admin` és `Front` almodulokra oszlik. Ez ismét tükröződik a névterekben, amelyek a `App\Modules\Blog\Admin\Presenters` stb. lesznek. Az almodulon belüli `Dashboard` bemutatót `Blog:Admin:Dashboard` néven említjük. +A `Blog` modul `Admin` és `Front` almodulokra oszlik. Ez tükröződik a névterekben is, amelyek aztán `App\Presentation\Blog\Admin` és hasonló módon jelennek meg. A `Dashboard` bemutatóra a `Admin` almodulon belül `Blog:Admin:Dashboard` néven hivatkozunk. -A beágyazás tetszőlegesen mélyre mehet, így al-almodulok hozhatók létre. +A beágyazás olyan mély lehet, amilyen mélyre csak szükséges, lehetővé téve al-almodulok létrehozását. + +Például, ha az adminisztrációban sok, a rendeléskezeléshez kapcsolódó prezenter van, mint például `OrderDetail`, `OrderEdit`, `OrderDispatch`, stb., létrehozhat egy `Order` modult, amelyben a `Detail`, `Edit`, `Dispatch`, stb. típusú prezentereket szervezi. Linkek létrehozása .[#toc-creating-links] @@ -99,49 +115,69 @@ Hogy megtudjuk, hogy egy adott modulban vagy annak almoduljában vagyunk-e, hasz Lásd [az útválasztásról szóló fejezetet |routing#Modules]. -Feltérképezés .[#toc-mapping] ------------------------------ +A feltérképezése .[#toc-mapping] +--------------------------------- + +A leképezés határozza meg az osztálynévnek a bemutató nevéből való származtatásának szabályait. Ezek a szabályok a [konfigurációban |configuration] a `application › mapping` kulcs alatt vannak megadva. + +Az ezen az oldalon korábban említett könyvtárszerkezetek a következő leképezésen alapulnak: -Meghatározza azokat a szabályokat, amelyek alapján az osztály neve az előadó nevéből származik. Ezeket a [konfigurációban |configuration] a `application › mapping` kulcs alatt írjuk le. +```neon +application: + mapping: App\Presentation\*\**Presenter +``` -Kezdjük egy olyan példával, amely nem használ modulokat. Csak azt akarjuk, hogy a prezenter osztályok a `App\Presenters` névtérrel rendelkezzenek. Ez azt jelenti, hogy egy olyan prezenternek, mint a `Home`, a `App\Presenters\HomePresenter` osztályhoz kell kapcsolódnia. Ezt a következő konfigurációval érhetjük el: +Hogyan működik a térképezés? A jobb megértés érdekében először képzeljünk el egy modulok nélküli alkalmazást. Szeretnénk, ha a prezenter osztályok a `App\UI` névtérbe tartoznának, így a `Home` prezenter a `App\Presentation\HomePresenter` osztályhoz tartozik. Ezt a következő konfigurációval érhetjük el: ```neon application: - mapping: App\Presenters\*Presenter + mapping: App\Presentation\*Presenter ``` -Az osztálymaszkban a prezenter nevét csillaggal helyettesítjük, és az eredmény az osztály neve lesz. Easy! +Ez a leképezés úgy működik, hogy a `App\Presentation\*Presenter` maszkban a csillagot a `Home` prezenter névvel helyettesítjük, így kapjuk a `App\Presentation\HomePresenter` végső osztálynevet. Egyszerű! + +Azonban, ahogyan azt az ebben és más fejezetekben található példákban láthatjuk, a prezenter osztályokat névadó alkönyvtárakba helyezzük, például a `Home` prezenter a `App\Presentation\Home\HomePresenter` osztályra van leképezve. Ezt a csillag megduplázásával érjük el (Nette Application 3.2 szükséges): + +```neon +application: + mapping: App\Presentation\**Presenter +``` -Ha az előadókat modulokra osztjuk, akkor minden modulhoz saját leképezésünk lehet: +Most pedig térjünk rá az előadók modulokba való leképezésére. Minden egyes modulhoz sajátos hozzárendeléseket határozhatunk meg: ```neon application: mapping: - Front: App\Modules\Front\Presenters\*Presenter - Admin: App\Modules\Admin\Presenters\*Presenter + Front: App\Presentation\Front\**Presenter + Admin: App\Presentation\Admin\**Presenter Api: App\Api\*Presenter ``` -Most a `Front:Home` bemutatót a `App\Modules\Front\Presenters\HomePresenter` osztályra, a `Admin:Dashboard` bemutatót pedig a `App\Modules\Admin\Presenters\DashboardPresenter` osztályra képezzük le. +E konfiguráció szerint a `Front:Home` bemutató a `App\Presentation\Front\Home\HomePresenter` osztályhoz, míg a `Api:OAuth` bemutató a `App\Api\OAuthPresenter` osztályhoz tartozik. -Praktikusabb egy általános (csillag) szabályt létrehozni az első kettő helyett. Az extra csillagot csak a modul számára adjuk hozzá az osztálymaszkhoz: +Mivel a `Front` és a `Admin` modulok hasonló leképezési megközelítéssel rendelkeznek, és valószínűleg több ilyen modul is létezik, létrehozható egy általános szabály, amely ezeket helyettesíti. Az osztálymaszkhoz egy új csillagot adunk a modulhoz: ```neon application: mapping: - *: App\Modules\*\Presenters\*Presenter + *: App\Presentation\*\**Presenter Api: App\Api\*Presenter ``` -De mi van akkor, ha egymásba ágyazott modulokat használunk, és van egy bemutató `Admin:User:Edit`? Ebben az esetben a modult jelképező csillaggal ellátott szegmens minden szinten egyszerűen megismétlődik, és az eredmény a `App\Modules\Admin\User\Presenters\EditPresenter` osztály lesz. +A többszintű, egymásba ágyazott modulok esetében, mint például a `Admin:User:Edit` bemutató, a csillagszegmens minden szinten megismétlődik, így a `App\Presentation\Admin\User\Edit\EditPresenter` osztály lesz az eredmény. -Egy alternatív jelölés az, hogy a karakterlánc helyett egy három szegmensből álló tömböt használunk. Ez a jelölés egyenértékű az előzővel: +Egy alternatív jelölés a karakterlánc helyett egy három szegmensből álló tömb használata. Ez a jelölés egyenértékű az előzővel: ```neon application: mapping: - *: [App\Modules, *, Presenters\*Presenter] + *: [App\UI, *, **Presenter] + Api: [App\Api, '', *Presenter] ``` -Az alapértelmezett érték a `*Module\*Presenter`. +Ha csak egy szabály van a konfigurációban, az általános szabály, akkor röviden leírhatjuk: + +```neon +application: + mapping: App\Presentation\*\**Presenter +``` diff --git a/application/hu/templates.texy b/application/hu/templates.texy index 71b205b7d1..0607b632a4 100644 --- a/application/hu/templates.texy +++ b/application/hu/templates.texy @@ -34,35 +34,81 @@ Az a szokásos, hogy az oldal az elrendezési sablonból + az akció sablonból Meghatározza a `content` blokkot, amely az elrendezésben a `{include content}` helyére kerül, és újra definiálja a `title` blokkot is, amely felülírja az elrendezésben a `{block title}` blokkot. Próbálja meg elképzelni az eredményt. -Sablonok keresése .[#toc-search-for-templates] ----------------------------------------------- +Sablon keresés .[#toc-template-lookup] +-------------------------------------- -A sablonok elérési útvonalát egyszerű logika szerint vezetjük le. Megpróbálja megnézni, hogy létezik-e valamelyik sablonfájl ahhoz a könyvtárhoz képest, ahol a prezenter osztály található, ahol a `` az aktuális prezenter neve és `` az aktuális művelet neve: +A prezenterekben nem kell megadnia, hogy melyik sablont kell megjeleníteni; a keretrendszer automatikusan meghatározza az útvonalat, megkönnyítve ezzel a kódolást. -- `templates//.latte` -- `templates/..latte` +Ha olyan könyvtárstruktúrát használ, ahol minden prezenternek saját könyvtára van, egyszerűen helyezze el a sablont ebben a könyvtárban az akció (pl. nézet) neve alatt. Például a `default` művelethez használja a `default.latte` sablont: -Ha a sablon nem található, a program megpróbál a `templates` könyvtárban keresni egy szinttel feljebb, azaz ugyanazon a szinten, mint a bemutató osztályt tartalmazó könyvtár. +/--pre +app/ +└── Presentation/ + └── Home/ + ├── HomePresenter.php + └── default.latte +\-- -Ha a sablon ott sem található, a válasz [404-es hiba |presenters#Error 404 etc.]. +Ha olyan struktúrát használ, ahol az előadók együttesen egy könyvtárban vannak, a sablonok pedig a `templates` mappában, mentse el vagy egy fájlban `..latte` vagy a `/.latte`: -A nézetet a `$this->setView('otherView')` segítségével is megváltoztathatja. Vagy a keresés helyett közvetlenül megadhatja a sablonfájl nevét a `$this->template->setFile('/path/to/template.latte')` segítségével. +/--pre +app/ +└── Presenters/ + ├── HomePresenter.php + └── templates/ + ├── Home.default.latte ← 1st variant + └── Home/ + └── default.latte ← 2nd variant +\-- + +A `templates` könyvtár egy szinttel feljebb is elhelyezhető, ugyanazon a szinten, mint az előadói osztályokat tartalmazó könyvtár. + +Ha a sablon nem található, a prezenter [404 - page not found hibával |presenters#Error 404 etc] válaszol. + +A nézetet a `$this->setView('anotherView')` segítségével lehet megváltoztatni. Lehetőség van a sablonfájl közvetlen megadására is a `$this->template->setFile('/path/to/template.latte')` segítségével. .[note] -A [formatTemplateFiles |api:Nette\Application\UI\Presenter::formatTemplateFiles()] metódus felülbírálásával módosíthatja azokat az elérési utakat, ahol a sablonok keresése történik, amely a lehetséges fájl elérési utak tömbjét adja vissza. +A fájlokat, amelyekben a sablonok keresése történik, a [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()] metódus felülbírálásával lehet megváltoztatni, amely a lehetséges fájlnevek tömbjét adja vissza. + + +Layout sablon keresés .[#toc-layout-template-lookup] +---------------------------------------------------- + +A Nette automatikusan megkeresi az elrendezési fájlt is. + +Ha olyan könyvtárstruktúrát használ, ahol minden előadónak saját könyvtára van, akkor az elrendezést vagy az előadóval közös mappába helyezze el, ha csak rá jellemző, vagy egy szinttel feljebb, ha több előadó számára közös: + +/--pre +app/ +└── Presentation/ + ├── @layout.latte ← common layout + └── Home/ + ├── @layout.latte ← only for Home presenter + ├── HomePresenter.php + └── default.latte +\-- + +Ha olyan struktúrát használ, ahol az előadók egy könyvtárban vannak csoportosítva, a sablonok pedig a `templates` mappában találhatók, az elrendezés a következő helyeken várható: -Az elrendezés a következő fájlokban várható: +/--pre +app/ +└── Presenters/ + ├── HomePresenter.php + └── templates/ + ├── @layout.latte ← common layout + ├── Home.@layout.latte ← only for Home, 1st variant + └── Home/ + └── @layout.latte ← only for Home, 2nd variant +\-- -- `templates//@.latte` -- `templates/.@.latte` -- `templates/@.latte` több előadónál közös elrendezés +Ha a bemutató egy [modulban |modules] van, akkor a modul beágyazottságának megfelelően a könyvtárfában feljebb is keresni fog. -`` az aktuális előadó neve és `` az elrendezés neve, amely alapértelmezés szerint `'layout'`. A név megváltoztatható a `$this->setLayout('otherLayout')` segítségével, így a `@otherLayout.latte` fájlokat próbálja meg. +Az elrendezés nevét a `$this->setLayout('layoutAdmin')` segítségével lehet megváltoztatni, majd a `@layoutAdmin.latte` fájlban várjuk el. Az elrendezés sablonfájlt közvetlenül is megadhatja a `$this->setLayout('/path/to/template.latte')` segítségével. -Az elrendezéssablon fájlnevét közvetlenül is megadhatja a `$this->setLayout('/path/to/template.latte')` segítségével. A `$this->setLayout(false)` használata letiltja az elrendezés keresését. +A `$this->setLayout(false)` vagy a `{layout none}` címke használata a sablonon belül kikapcsolja az elrendezéskeresést. .[note] -A [formatLayoutTemplateFiles |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()] metódus felülbírálásával módosíthatja a sablonok keresési útvonalait, amely a lehetséges fájlútvonalak tömbjét adja vissza. +A fájlok, amelyekben az elrendezési sablonok keresése történik, megváltoztathatók a [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()] metódus felülbírálásával, amely a lehetséges fájlnevek tömbjét adja vissza. Változók a sablonban .[#toc-variables-in-the-template] @@ -104,7 +150,7 @@ A `@property-read` annotáció az IDE és a statikus elemzés számára készül A sablonokban is megengedheted magadnak a suttogás luxusát, csak telepítsd a Latte plugint a PhpStormban, és add meg az osztály nevét a sablon elején, lásd a "Latte: hogyan kell tipizálni a rendszert":https://blog.nette.org/hu/latte-hogyan-kell-hasznalni-a-tipusrendszert című cikket: ```latte -{templateType App\Presenters\ArticleTemplate} +{templateType App\Presentation\Article\ArticleTemplate} ... ``` @@ -176,7 +222,7 @@ public function beforeRender(): void A Latte 3. verziója egy fejlettebb módszert kínál, amely minden egyes webes projekthez egy [bővítményt |latte:creating-extension] hoz létre. Íme egy durva példa egy ilyen osztályra: ```php -namespace App\Templating; +namespace App\Presentation\Accessory; final class LatteExtension extends Latte\Extension { @@ -214,7 +260,7 @@ A [configuration |configuration#Latte] segítségével regisztráljuk: ```neon latte: extensions: - - App\Templating\LatteExtension + - App\Presentation\Accessory\LatteExtension ``` diff --git a/application/it/how-it-works.texy b/application/it/how-it-works.texy index 91e4f4e5ef..f75a9bbce6 100644 --- a/application/it/how-it-works.texy +++ b/application/it/how-it-works.texy @@ -22,13 +22,13 @@ La struttura delle directory è simile a questa: /--pre web-project/ ├── app/ ← directory with application -│ ├── Presenters/ ← presenter classes -│ │ ├── HomePresenter.php ← Home presenter class -│ │ └── templates/ ← templates directory -│ │ ├── @layout.latte ← template of shared layout -│ │ └── Home/ ← templates for Home presenter -│ │ └── default.latte ← template for action `default` -│ ├── Router/ ← configuration of URL addresses +│ ├── Core/ ← classi di base necessarie +│ │ └── RouterFactory.php ← configurazione degli indirizzi URL +│ ├── Presentation/ ← presenter, template & co. +│ │ ├── @layout.latte ← modello di layout condiviso +│ │ └── Home/ ← cartella del presentatore Home +│ │ ├── HomePresenter.php ← Classe del presentatore della casa +│ │ └── default.latte ← template per l'azione default │ └── Bootstrap.php ← booting class Bootstrap ├── bin/ ← scripts for the command line ├── config/ ← configuration files @@ -91,7 +91,7 @@ Le applicazioni scritte in Nette sono suddivise in molti cosiddetti presenter (i L'applicazione inizia chiedendo al cosiddetto router di decidere a quale dei presenter passare la richiesta corrente per l'elaborazione. Il router decide di chi è la responsabilità. Osserva l'URL di ingresso `https://example.com/product/123`, che vuole `show` un prodotto con `id: 123` come azione. È buona abitudine scrivere le coppie presentatore + azione separate da due punti come `Product:show`. -Quindi il router ha trasformato l'URL in una coppia `Presenter:action` + parametri, nel nostro caso `Product:show` + `id: 123`. Si può vedere l'aspetto di un router nel file `app/Router/RouterFactory.php` e lo descriveremo in dettaglio nel capitolo [Routing |Routing]. +Quindi il router ha trasformato l'URL in una coppia `Presenter:action` + parametri, nel nostro caso `Product:show` + `id: 123`. Si può vedere l'aspetto di un router nel file `app/Core/RouterFactory.php` e lo descriveremo in dettaglio nel capitolo [Routing |Routing]. Andiamo avanti. L'applicazione conosce già il nome del presentatore e può continuare. Creando un oggetto `ProductPresenter`, che è il codice del presentatore `Product`. Più precisamente, chiede al contenitore DI di creare il presentatore, perché produrre oggetti è il suo lavoro. @@ -121,12 +121,9 @@ Quindi, è stato chiamato il metodo `renderShow(123)`, il cui codice è un esemp Successivamente, il presentatore restituisce la risposta. Questa può essere una pagina HTML, un'immagine, un documento XML, l'invio di un file dal disco, JSON o il reindirizzamento a un'altra pagina. È importante notare che, se non si dice esplicitamente come rispondere (come nel caso di `ProductPresenter`), la risposta sarà il rendering del modello con una pagina HTML. Perché? Perché nel 99% dei casi vogliamo disegnare un modello, quindi il presentatore prende questo comportamento come predefinito e vuole semplificarci il lavoro. Questo è il punto di Nette. -Non dobbiamo nemmeno dichiarare quale modello disegnare, lui ricava il percorso per raggiungerlo secondo una semplice logica. Nel caso del presenter `Product` e dell'azione `show`, cerca di vedere se esiste uno di questi file di template relativi alla directory in cui si trova la classe `ProductPresenter`: +Non è nemmeno necessario specificare quale template rendere; il framework dedurrà da solo il percorso. Nel caso dell'azione `show`, cerca semplicemente di caricare il template `show.latte` nella cartella con la classe `ProductPresenter`. Cerca anche di trovare il layout nel file `@layout.latte` (maggiori informazioni sulla [ricerca dei template |templates#Template Lookup]). -- `templates/Product/show.latte` -- `templates/Product.show.latte` - -Cercherà anche di trovare il layout nel file `@layout.latte` e quindi eseguirà il rendering del modello. Ora il compito del presentatore e dell'intera applicazione è completato. Se il modello non esiste, verrà restituita una pagina con errore 404. Per saperne di più sui presentatori, consultare la pagina [Presentatori |Presenters]. +Successivamente, i modelli vengono renderizzati. Questo completa il compito del presentatore e dell'intera applicazione e il lavoro è terminato. Se il modello non esistesse, verrebbe restituita una pagina di errore 404. Per saperne di più sui presentatori, consultare la pagina [Presentatori |presenters]. [* request-flow.svg *] @@ -137,7 +134,7 @@ Per sicurezza, proviamo a riepilogare l'intero processo con un URL leggermente d 3) il router decodifica l'URL come una coppia di oggetti `Home:default` 4) viene creato un oggetto `HomePresenter` 5) viene richiamato il metodo `renderDefault()` (se esiste) -6) viene reso un modello `templates/Home/default.latte` con un layout `templates/@layout.latte` +6) viene reso un modello `default.latte` con un layout `@layout.latte` Potreste esservi imbattuti in molti concetti nuovi, ma crediamo che abbiano un senso. Creare applicazioni in Nette è un gioco da ragazzi. diff --git a/application/it/modules.texy b/application/it/modules.texy index 76b8af4e23..7c9596e854 100644 --- a/application/it/modules.texy +++ b/application/it/modules.texy @@ -2,29 +2,31 @@ Moduli ****** .[perex] -In Nette, i moduli rappresentano le unità logiche che compongono un'applicazione. Comprendono presentatori, modelli, eventualmente anche componenti e classi di modelli. +I moduli conferiscono chiarezza alle applicazioni Nette, facilitando la suddivisione in unità logiche. -Una cartella per i presentatori e una per i modelli non sarebbe sufficiente per i progetti reali. Avere decine di file in una cartella è quantomeno disorganizzato. Come uscirne? Semplicemente dividendoli in sottodirectory su disco e in spazi dei nomi nel codice. E questo è esattamente ciò che fanno i moduli Nette. - -Dimentichiamo quindi un'unica cartella per i presentatori e i modelli e creiamo invece dei moduli, ad esempio `Admin` e `Front`. +Analogamente all'organizzazione dei file in cartelle su un disco rigido, in Nette possiamo dividere presentatori, modelli e altre classi ausiliarie in moduli. Come funziona in pratica? Semplicemente incorporando nuove sottodirectory nella struttura. Ecco un esempio di struttura con due moduli, Front e Admin: /--pre -app/ -├── Presenters/ -├── Modules/ ← directory with modules -│ ├── Admin/ ← module Admin -│ │ ├── Presenters/ ← its presenters -│ │ │ ├── DashboardPresenter.php -│ │ │ └── templates/ -│ └── Front/ ← module Front -│ └── Presenters/ ← its presenters -│ └── ... +app/ +├── Presentation/ +│ ├── Admin/ ← Admin module +│ │ ├── @layout.latte +│ │ ├── Dashboard/ +│ │ │ ├── DashboardPresenter.php +│ │ │ └── default.latte +│ │ └── ... +│ ├── Front/ ← Front module +│ │ ├── @layout.latte +│ │ ├── Home/ +│ │ │ ├── HomePresenter.php +│ │ │ └── default.latte +│ │ └── ... \-- -Questa struttura di cartelle si rifletterà negli spazi dei nomi delle classi, quindi ad esempio `DashboardPresenter` sarà nello spazio dei nomi `App\Modules\Admin\Presenters`: +Questa struttura di directory si riflette negli spazi dei nomi delle classi, per cui, ad esempio, `DashboardPresenter` si trova nello spazio dei nomi `App\Presentation\Admin\Dashboard`: ```php -namespace App\Modules\Admin\Presenters; +namespace App\Presentation\Admin\Dashboard; class DashboardPresenter extends Nette\Application\UI\Presenter { @@ -32,35 +34,49 @@ class DashboardPresenter extends Nette\Application\UI\Presenter } ``` -Il presentatore `Dashboard` all'interno del modulo `Admin` è referenziato all'interno dell'applicazione usando la notazione dei due punti come `Admin:Dashboard`, e la sua azione `default` come `Admin:Dashboard:default`. -E come fa Nette a sapere che `Admin:Dashboard` rappresenta la classe `App\Modules\Admin\Presenters\DashboardPresenter`? Questo è determinato dalla [mappatura |#mapping] nella configurazione. -Pertanto, la struttura data non è rigida e può essere modificata in base alle proprie esigenze. +Nell'applicazione, ci si riferisce al presentatore `Dashboard` all'interno del modulo `Admin` usando la notazione dei due punti come `Admin:Dashboard`. Per l'azione `default`, ci si riferisce ad essa come `Admin:Dashboard:default`. -I moduli possono naturalmente contenere tutti gli altri elementi oltre ai presentatori e ai modelli, come componenti, classi di modelli, ecc. +La struttura presentata non è rigida; è possibile [personalizzarla completamente in base alle proprie esigenze |#mapping] nella configurazione. .[tip] + +I moduli possono includere tutti gli altri file, come i componenti e le classi ausiliarie, oltre ai presentatori e ai modelli. Se si sta valutando dove collocare questi ultimi, si può prendere in considerazione l'uso di una cartella `Accessory`: + +/--pre +app/ +├── Presentation/ +│ ├── Admin/ +│ │ ├── Accessory/ +│ │ │ ├── FormFactory.php +│ │ │ └── AdminLayout.php +│ │ ├── Dashboard/ +│ │ └── ... +\-- Moduli annidati .[#toc-nested-modules] -------------------------------------- -I moduli non devono formare solo una struttura piatta, ma si possono anche creare sottomoduli, ad esempio: +I moduli possono avere più livelli di annidamento, simili a una struttura di directory su disco: /--pre -app/ -├── Modules/ ← directory with modules -│ ├── Blog/ ← module Blog -│ │ ├── Admin/ ← submodule Admin -│ │ │ ├── Presenters/ +app/ +├── Presentation/ +│ ├── Blog/ ← Blog module +│ │ ├── Admin/ ← Admin submodule +│ │ │ ├── Dashboard/ +│ │ │ └── ... +│ │ ├── Front/ ← Front submodule +│ │ │ ├── @layout.latte +│ │ │ ├── Home/ │ │ │ └── ... -│ │ └── Front/ ← submodule Front -│ │ ├── Presenters/ -│ │ └── ... -│ ├── Forum/ ← module Forum +│ ├── Forum/ ← Forum module │ │ └── ... \-- -Così, il modulo `Blog` è suddiviso nei sottomoduli `Admin` e `Front`. Anche in questo caso, ciò si rifletterà negli spazi dei nomi, che saranno `App\Modules\Blog\Admin\Presenters` e così via. Il presentatore `Dashboard` all'interno del sottomodulo viene chiamato `Blog:Admin:Dashboard`. +Il modulo `Blog` è diviso nei sottomoduli `Admin` e `Front`. Questo si riflette anche negli spazi dei nomi, che appaiono come `App\Presentation\Blog\Admin` e simili. Per riferirsi al presentatore `Dashboard` all'interno del sottomodulo `Admin`, ci si riferisce ad esso come `Blog:Admin:Dashboard`. -L'annidamento può andare in profondità quanto si vuole, quindi si possono creare dei sottomoduli. +L'annidamento può essere profondo quanto necessario, consentendo la creazione di sottomoduli. + +Ad esempio, se nell'amministrazione sono presenti molti presentatori relativi alla gestione degli ordini, come `OrderDetail`, `OrderEdit`, `OrderDispatch`, ecc. si può creare un modulo `Order` in cui saranno organizzati presentatori come `Detail`, `Edit`, `Dispatch`, e altri. Creazione di collegamenti .[#toc-creating-links] @@ -102,46 +118,66 @@ Vedere il [capitolo sull'instradamento |routing#Modules]. Mappatura .[#toc-mapping] ------------------------- -Definisce le regole con cui il nome della classe viene derivato dal nome del presentatore. Vengono scritte nella [configurazione |configuration] sotto la chiave `application › mapping`. +La mappatura definisce le regole per derivare il nome della classe dal nome del presentatore. Queste regole sono specificate nella [configurazione |configuration] sotto la chiave `application › mapping`. + +Le strutture di directory menzionate in precedenza in questa pagina si basano sulla seguente mappatura: + +```neon +application: + mapping: App\Presentation\*\**Presenter +``` -Cominciamo con un esempio che non usa moduli. Vogliamo solo che le classi del presentatore abbiano lo spazio dei nomi `App\Presenters`. Ciò significa che un presentatore come `Home` deve mappare alla classe `App\Presenters\HomePresenter`. Questo si può ottenere con la seguente configurazione: +Come funziona la mappatura? Per capire meglio, immaginiamo prima un'applicazione senza moduli. Vogliamo che le classi del presentatore rientrino nello spazio dei nomi `App\UI`, in modo che il presentatore `Home` sia mappato nella classe `App\Presentation\HomePresenter`. Ciò può essere ottenuto con questa configurazione: ```neon application: - mapping: App\Presenters\*Presenter + mapping: App\Presentation\*Presenter ``` -Il nome del presentatore viene sostituito con l'asterisco nella maschera della classe e il risultato è il nome della classe. Facile! +Questa mappatura funziona sostituendo l'asterisco nella maschera `App\Presentation\*Presenter` con il nome del presenter `Home`, ottenendo il nome finale della classe `App\Presentation\HomePresenter`. Semplice! + +Tuttavia, come si può vedere negli esempi di questo e di altri capitoli, le classi dei presentatori sono collocate in sottodirectory eponime, ad esempio il presentatore `Home` è mappato nella classe `App\Presentation\Home\HomePresenter`. Questo si ottiene raddoppiando l'asterisco (richiede Nette Application 3.2): + +```neon +application: + mapping: App\Presentation\**Presenter +``` -Se dividiamo i presentatori in moduli, possiamo avere la nostra mappatura per ogni modulo: +Passiamo ora alla mappatura dei presentatori nei moduli. Possiamo definire mappature specifiche per ogni modulo: ```neon application: mapping: - Front: App\Modules\Front\Presenters\*Presenter - Admin: App\Modules\Admin\Presenters\*Presenter + Front: App\Presentation\Front\**Presenter + Admin: App\Presentation\Admin\**Presenter Api: App\Api\*Presenter ``` -Ora il presentatore `Front:Home` mappa alla classe `App\Modules\Front\Presenters\HomePresenter` e il presentatore `Admin:Dashboard` alla classe `App\Modules\Admin\Presenters\DashboardPresenter`. +In base a questa configurazione, il presentatore `Front:Home` si riferisce alla classe `App\Presentation\Front\Home\HomePresenter`, mentre il presentatore `Api:OAuth` si riferisce alla classe `App\Api\OAuthPresenter`. -È più pratico creare una regola generale (asterisco) per sostituire le prime due. L'asterisco in più sarà aggiunto alla maschera di classe solo per il modulo: +Poiché i moduli `Front` e `Admin` hanno un approccio di mappatura simile e probabilmente ci saranno altri moduli di questo tipo, è possibile creare una regola generale che li sostituisca. Un nuovo asterisco per il modulo viene aggiunto alla maschera della classe: ```neon application: mapping: - *: App\Modules\*\Presenters\*Presenter + *: App\Presentation\*\**Presenter Api: App\Api\*Presenter ``` -Ma cosa succede se utilizziamo moduli annidati e abbiamo un presentatore `Admin:User:Edit`? In questo caso, il segmento con l'asterisco che rappresenta il modulo per ogni livello viene semplicemente ripetuto e il risultato è la classe `App\Modules\Admin\User\Presenters\EditPresenter`. +Per i moduli annidati a più livelli, come il presentatore `Admin:User:Edit`, il segmento dell'asterisco si ripete per ogni livello, dando luogo alla classe `App\Presentation\Admin\User\Edit\EditPresenter`. Una notazione alternativa consiste nell'utilizzare un array composto da tre segmenti invece di una stringa. Questa notazione è equivalente alla precedente: ```neon application: mapping: - *: [App\Modules, *, Presenters\*Presenter] + *: [App\UI, *, **Presenter] + Api: [App\Api, '', *Presenter] ``` -Il valore predefinito è `*Module\*Presenter`. +Se abbiamo una sola regola nella configurazione, quella generale, possiamo scrivere brevemente: + +```neon +application: + mapping: App\Presentation\*\**Presenter +``` diff --git a/application/it/templates.texy b/application/it/templates.texy index bb704a88f2..a5a78e3f70 100644 --- a/application/it/templates.texy +++ b/application/it/templates.texy @@ -34,35 +34,81 @@ E questo potrebbe essere il modello di azione: Definisce il blocco `content`, che viene inserito al posto di `{include content}` nel layout, e ridefinisce anche il blocco `title`, che sovrascrive `{block title}` nel layout. Provate a immaginare il risultato. -Ricerca dei modelli .[#toc-search-for-templates] ------------------------------------------------- +Ricerca di modelli .[#toc-template-lookup] +------------------------------------------ + +Nei presentatori, non è necessario specificare quale template debba essere reso; il framework determinerà automaticamente il percorso, semplificando la codifica. + +Se si utilizza una struttura di cartelle in cui ogni presentatore ha una propria cartella, è sufficiente posizionare il template in questa cartella sotto il nome dell'azione (cioè della vista). Ad esempio, per l'azione `default`, utilizzare il modello `default.latte`: -Il percorso dei modelli viene dedotto secondo una semplice logica. Si cerca di vedere se uno di questi file di template esiste relativamente alla directory in cui si trova la classe del presentatore, dove `` è il nome del presentatore corrente e `` è il nome dell'azione corrente: +/--pre +app/ +└── Presentation/ + └── Home/ + ├── HomePresenter.php + └── default.latte +\-- -- `templates//.latte` -- `templates/..latte` +Se si utilizza una struttura in cui i presentatori sono riuniti in una directory e i modelli in una cartella `templates`, salvare il tutto in un file `..latte` oppure `/.latte`: -Se il modello non viene trovato, si cercherà nella cartella `templates` a un livello superiore, cioè allo stesso livello della cartella con la classe del presentatore. +/--pre +app/ +└── Presenters/ + ├── HomePresenter.php + └── templates/ + ├── Home.default.latte ← 1st variant + └── Home/ + └── default.latte ← 2nd variant +\-- -Se il modello non viene trovato nemmeno lì, la risposta è un [errore 404 |presenters#Error 404 etc.]. +La directory `templates` può anche essere collocata un livello più in alto, allo stesso livello della directory con le classi dei presentatori. -Si può anche cambiare la vista usando `$this->setView('otherView')`. Oppure, invece di cercare, specificare direttamente il nome del file del template usando `$this->template->setFile('/path/to/template.latte')`. +Se il modello non viene trovato, il presentatore risponde con un [errore 404 - pagina non trovata |presenters#Error 404 etc]. + +È possibile modificare la vista utilizzando `$this->setView('anotherView')`. È anche possibile specificare direttamente il file del modello con `$this->template->setFile('/path/to/template.latte')`. .[note] -È possibile modificare i percorsi in cui vengono cercati i modelli sovrascrivendo il metodo [formatTemplateFiles |api:Nette\Application\UI\Presenter::formatTemplateFiles()], che restituisce un array di possibili percorsi di file. +I file in cui vengono cercati i modelli possono essere modificati sovrascrivendo il metodo [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()], che restituisce un array di possibili nomi di file. + + +Ricerca dei modelli di layout .[#toc-layout-template-lookup] +------------------------------------------------------------ + +Nette cerca automaticamente anche il file di layout. + +Se si utilizza una struttura di directory in cui ogni presentatore ha una propria directory, collocare il layout nella cartella del presentatore, se è specifico solo per lui, oppure a un livello superiore se è comune a più presentatori: + +/--pre +app/ +└── Presentation/ + ├── @layout.latte ← common layout + └── Home/ + ├── @layout.latte ← only for Home presenter + ├── HomePresenter.php + └── default.latte +\-- + +Se si utilizza una struttura in cui i presentatori sono raggruppati in una directory e i modelli si trovano in una cartella `templates`, il layout sarà previsto nei seguenti punti: -Il layout è previsto nei seguenti file: +/--pre +app/ +└── Presenters/ + ├── HomePresenter.php + └── templates/ + ├── @layout.latte ← common layout + ├── Home.@layout.latte ← only for Home, 1st variant + └── Home/ + └── @layout.latte ← only for Home, 2nd variant +\-- -- `templates//@.latte` -- `templates/.@.latte` -- `templates/@.latte` layout comune a più presentatori +Se il presentatore si trova in un [modulo |modules], cercherà anche più in alto nell'albero della directory, in base alla nidificazione del modulo. -`` è il nome del presentatore corrente e `` è il nome del layout, che per impostazione predefinita è `'layout'`. Il nome può essere modificato con `$this->setLayout('otherLayout')`, in modo da provare i file `@otherLayout.latte`. +Il nome del layout può essere modificato con `$this->setLayout('layoutAdmin')` e sarà previsto nel file `@layoutAdmin.latte`. È anche possibile specificare direttamente il file del modello di layout usando `$this->setLayout('/path/to/template.latte')`. -È anche possibile specificare direttamente il nome del file del modello di layout con `$this->setLayout('/path/to/template.latte')`. L'uso di `$this->setLayout(false)` disabilita la ricerca dei layout. +L'uso di `$this->setLayout(false)` o del tag `{layout none}` all'interno del template disabilita la ricerca del layout. .[note] -È possibile modificare i percorsi in cui vengono cercati i modelli sovrascrivendo il metodo [formatLayoutTemplateFiles |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], che restituisce un array di possibili percorsi di file. +I file in cui vengono cercati i modelli di layout possono essere modificati sovrascrivendo il metodo [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], che restituisce un array di possibili nomi di file. Variabili nel modello .[#toc-variables-in-the-template] @@ -104,7 +150,7 @@ L'annotazione `@property-read` è per l'IDE e l'analisi statica, farà funzionar Ci si può concedere il lusso di sussurrare anche nei template, basta installare il plugin Latte in PhpStorm e specificare il nome della classe all'inizio del template, si veda l'articolo "Latte: come digitare il sistema":https://blog.nette.org/it/latte-come-usare-il-sistema-di-tipi: ```latte -{templateType App\Presenters\ArticleTemplate} +{templateType App\Presentation\Article\ArticleTemplate} ... ``` @@ -176,7 +222,7 @@ public function beforeRender(): void La versione 3 di Latte offre un metodo più avanzato, creando un'[estensione |latte:creating-extension] per ogni progetto web. Ecco un esempio approssimativo di una classe di questo tipo: ```php -namespace App\Templating; +namespace App\Presentation\Accessory; final class LatteExtension extends Latte\Extension { @@ -214,7 +260,7 @@ La registriamo usando [configuration |configuration#Latte]: ```neon latte: extensions: - - App\Templating\LatteExtension + - App\Presentation\Accessory\LatteExtension ``` diff --git a/application/pl/how-it-works.texy b/application/pl/how-it-works.texy index 9cbbb61f69..8b856748a9 100644 --- a/application/pl/how-it-works.texy +++ b/application/pl/how-it-works.texy @@ -22,13 +22,13 @@ Struktura katalogów wygląda mniej więcej tak: /--pre web-project/ ├── app/ ← adresář s aplikací -│ ├── Presenters/ ← presentery a šablony -│ │ ├── HomePresenter.php ← třída presenteru Home -│ │ └── templates/ ← adresář se šablonami -│ │ ├── @layout.latte ← šablona layoutu -│ │ └── Home/ ← šablony presenteru Home -│ │ └── default.latte ← šablona akce 'default' -│ ├── Router/ ← konfigurace URL adres +│ ├── Core/ ← podstawowe niezbędne klasy +│ │ └── RouterFactory.php ← konfiguracja adresów URL +│ ├── Presentation/ ← prezentery, szablony & co. +│ │ ├── @layout.latte ← szablon udostępnionego layoutu +│ │ └── Home/ ← Katalog główny prezentera +│ │ ├── HomePresenter.php ← Klasa prezentera strony głównej +│ │ └── default.latte ← szablon dla akcji default │ └── Bootstrap.php ← zaváděcí třída Bootstrap ├── bin/ ← skripty spouštěné z příkazové řádky ├── config/ ← konfigurační soubory @@ -91,7 +91,7 @@ Aplikacje napisane w Nette są podzielone na wiele prezenterów (w innych framew Aplikacja rozpoczyna się od zapytania tzw. routera o decyzję, do którego prezentera przekazać bieżące żądanie do przetworzenia. Router decyduje o tym, czyja to odpowiedzialność. Patrzy na wejściowy URL `https://example.com/product/123`, którego poprosi o wyświetlenie (`show`) produktu z `id: 123` jako **akcji** . Dobrą praktyką jest zapisanie pary prezenter + akcja oddzielonej dwukropkiem jako `Product:show`. -W ten sposób router przekształca adres URL w parę `Presenter:action` + parametry, w naszym przypadku `Product:show` + `id: 123`. Jak wygląda taki router, można zobaczyć w pliku `app/Router/RouterFactory.php`, a szczegółowo opisujemy go w rozdziale [Routing |Routing]. +W ten sposób router przekształca adres URL w parę `Presenter:action` + parametry, w naszym przypadku `Product:show` + `id: 123`. Jak wygląda taki router, można zobaczyć w pliku `app/Core/RouterFactory.php`, a szczegółowo opisujemy go w rozdziale [Routing |Routing]. Ruszajmy dalej. Aplikacja zna teraz nazwę prezentera i może przejść dalej. Produkując obiekt klasy `ProductPresenter`, który jest kodem prezentera `Product`. Dokładniej, prosi kontener DI o wyprodukowanie prezentera, ponieważ jest tam, aby go wyprodukować. @@ -121,12 +121,9 @@ Wywołana jest więc metoda `renderShow(123)`, której kod jest fikcyjnym przyk Następnie prezenter zwraca odpowiedź. Może to być strona HTML, obraz, dokument XML, wysłanie pliku z dysku, JSON, a nawet przekierowanie na inną stronę. Co ważne, o ile nie powiemy wprost prezenterowi, jak ma odpowiedzieć (co ma miejsce w przypadku `ProductPresenter`), odpowiedzią będzie renderowanie szablonu ze stroną HTML. Dlaczego? Ponieważ w 99% przypadków chcemy renderować szablon, więc prezenter przyjmuje to zachowanie jako domyślne i chce ułatwić nam pracę. O to właśnie chodzi w Nette. -Nie musimy nawet określać, jaki szablon ma być renderowany, sam wywnioskuje ścieżkę do niego za pomocą prostej logiki. W przypadku prezentera `Product` i akcji `show`, spróbuje sprawdzić, czy istnieje jeden z tych plików szablonów przechowywanych względnie z katalogu klasy `ProductPresenter`: +Nie musimy nawet określać, który szablon ma być renderowany; framework sam wydedukuje ścieżkę. W przypadku akcji `show`, po prostu próbuje załadować szablon `show.latte` w katalogu z klasą `ProductPresenter`. Próbuje również znaleźć układ w pliku `@layout.latte` (więcej o [wyszukiwaniu szablonów |templates#Template Lookup]). -- `templates/Product/show.latte` -- `templates/Product.show.latte` - -Spróbuje również prześledzić układ w pliku `@layout.latte`, a następnie wyrenderować szablon. W ten sposób kończy się zadanie prezentera i aplikacji, a praca zostaje zakończona. Jeśli szablon nie istnieje, zwrócona zostanie strona błędu 404. Więcej o prezenterach można przeczytać na stronie [Prezenterzy |presenters]. +Następnie szablony są renderowane. To kończy zadanie prezentera i całej aplikacji, a praca jest wykonywana. Jeśli szablon nie istnieje, zostanie zwrócona strona błędu 404. Więcej informacji na temat prezenterów można znaleźć na stronie [Prezenterzy |presenters]. [* request-flow.svg *] @@ -137,7 +134,7 @@ Aby być bezpiecznym, spróbujmy podsumować cały proces z nieco innym adresem 3) router dekoduje adres URL jako parę `Home:default` 4) tworzony jest obiekt klasy `HomePresenter` 5) wywoływana jest metoda `renderDefault()` (jeśli istnieje) -6) wyrenderować szablon np. `templates/Home/default.latte` z układem np. `templates/@layout.latte` +6) wyrenderować szablon np. `default.latte` z układem np. `@layout.latte` Teraz być może spotkałeś się z wieloma nowymi pojęciami, ale wierzymy, że mają one sens. Tworzenie aplikacji w Nette to ogromna bułka z masłem. diff --git a/application/pl/modules.texy b/application/pl/modules.texy index 488d8f50a3..7210b29629 100644 --- a/application/pl/modules.texy +++ b/application/pl/modules.texy @@ -2,29 +2,31 @@ Moduły ****** .[perex] -W Nette moduły reprezentują logiczne jednostki, które tworzą aplikację. Należą do nich prezentery, szablony, ewentualnie komponenty i klasy modeli. +Moduły zapewniają przejrzystość aplikacji Nette, ułatwiając podział na logiczne jednostki. -Jeden komponent dla prezenterów i jeden dla szablonów nie wystarczyłby dla prawdziwych projektów. Posiadanie kilkudziesięciu plików w jednym folderze jest co najmniej niezorganizowane. Jak się z niego wydostać? Po prostu dzielimy je na podkatalogi na dysku i na przestrzenie nazw w kodzie. I właśnie to robią moduły Nette. - -Zapomnijmy więc o jednym folderze dla prezenterów i szablonów, a zamiast tego stwórzmy moduły, na przykład `Admin` i `Front`. +Podobnie jak w przypadku organizowania plików w foldery na dysku twardym, w Nette możemy podzielić prezenterów, szablony i inne klasy pomocnicze na moduły. Jak to działa w praktyce? Po prostu poprzez włączenie nowych podkatalogów do struktury. Oto przykład struktury z dwoma modułami, Front i Admin: /--pre -app/ -├── Presenters/ -├── Modules/ ← adresář s moduly -│ ├── Admin/ ← modul Admin -│ │ ├── Presenters/ ← jeho presentery -│ │ │ ├── DashboardPresenter.php -│ │ │ └── templates/ -│ └── Front/ ← modul Front -│ └── Presenters/ ← jeho presentery -│ └── ... +app/ +├── Presentation/ +│ ├── Admin/ ← Admin module +│ │ ├── @layout.latte +│ │ ├── Dashboard/ +│ │ │ ├── DashboardPresenter.php +│ │ │ └── default.latte +│ │ └── ... +│ ├── Front/ ← Front module +│ │ ├── @layout.latte +│ │ ├── Home/ +│ │ │ ├── HomePresenter.php +│ │ │ └── default.latte +│ │ └── ... \-- -Ta struktura katalogów będzie odzwierciedlona w przestrzeni nazw klas, więc na przykład `DashboardPresenter` będzie w przestrzeni `App\Modules\Admin\Presenters`: +Ta struktura katalogów jest odzwierciedlona w przestrzeniach nazw klas, więc na przykład `DashboardPresenter` znajduje się w przestrzeni nazw `App\Presentation\Admin\Dashboard`: ```php -namespace App\Modules\Admin\Presenters; +namespace App\Presentation\Admin\Dashboard; class DashboardPresenter extends Nette\Application\UI\Presenter { @@ -32,35 +34,49 @@ class DashboardPresenter extends Nette\Application\UI\Presenter } ``` -Prezenter `Dashboard` wewnątrz modułu `Admin` jest określany w aplikacji za pomocą notacji z podwójną kropką jako `Admin:Dashboard`, a jego działanie `default` jest określane jako `Admin:Dashboard:default`. -A skąd Nette own wie, że `Admin:Dashboard` reprezentuje klasę `App\Modules\Admin\Presenters\DashboardPresenter`? Mówimy to za pomocą [mapowania |#Mappings] w konfiguracji. -Tak więc podana struktura nie jest stała i można ją modyfikować według potrzeb. +W aplikacji odnosimy się do prezentera `Dashboard` w module `Admin` używając notacji dwukropka jako `Admin:Dashboard`. W przypadku akcji `default` odnosimy się do niej jako `Admin:Dashboard:default`. -Moduły mogą oczywiście zawierać wszystkie inne części oprócz prezenterów i szablonów, jak komponenty, klasy modeli itp. +Przedstawiona struktura nie jest sztywna; można [ją w pełni dostosować do własnych potrzeb |#mapping] w konfiguracji. .[tip] + +Moduły mogą zawierać wszystkie inne pliki, takie jak komponenty i klasy pomocnicze, oprócz prezenterów i szablonów. Jeśli zastanawiasz się, gdzie je umieścić, rozważ użycie folderu `Accessory`: + +/--pre +app/ +├── Presentation/ +│ ├── Admin/ +│ │ ├── Accessory/ +│ │ │ ├── FormFactory.php +│ │ │ └── AdminLayout.php +│ │ ├── Dashboard/ +│ │ └── ... +\-- Moduły zagnieżdżone .[#toc-nested-modules] ------------------------------------------ -Moduły nie muszą tworzyć tylko płaskiej struktury, można też tworzyć np. submoduły: +Moduły mogą mieć wiele poziomów zagnieżdżenia, podobnie jak struktura katalogów na dysku: /--pre -app/ -├── Modules/ ← adresář s moduly -│ ├── Blog/ ← modul Blog -│ │ ├── Admin/ ← submodul Admin -│ │ │ ├── Presenters/ +app/ +├── Presentation/ +│ ├── Blog/ ← Blog module +│ │ ├── Admin/ ← Admin submodule +│ │ │ ├── Dashboard/ +│ │ │ └── ... +│ │ ├── Front/ ← Front submodule +│ │ │ ├── @layout.latte +│ │ │ ├── Home/ │ │ │ └── ... -│ │ └── Front/ ← submodul Front -│ │ ├── Presenters/ -│ │ └── ... -│ ├── Forum/ ← modul Forum +│ ├── Forum/ ← Forum module │ │ └── ... \-- -Tak więc moduł `Blog` jest podzielony na podmoduły `Admin` i `Front`. I znowu będzie to odzwierciedlone w przestrzeni nazw, która będzie `App\Modules\Blog\Admin\Presenters` itd. Prezenter `Dashboard` wewnątrz submodułu jest określany jako `Blog:Admin:Dashboard`. +Moduł `Blog` jest podzielony na podmoduły `Admin` i `Front`. Jest to również odzwierciedlone w przestrzeniach nazw, które następnie pojawiają się jako `App\Presentation\Blog\Admin` i podobnie. Aby odnieść się do prezentera `Dashboard` w podmodule `Admin`, odnosimy się do niego jako `Blog:Admin:Dashboard`. -Rozgałęzienie może iść tak głęboko, jak chcesz, więc możesz tworzyć podmoduły. +Zagnieżdżanie może być tak głębokie, jak potrzeba, umożliwiając tworzenie podmodułów. + +Na przykład, jeśli w administracji masz wiele prezenterów związanych z zarządzaniem zamówieniami, takich jak `OrderDetail`, `OrderEdit`, `OrderDispatch`, itp., możesz utworzyć moduł `Order`, w którym będą zorganizowane prezentery takie jak `Detail`, `Edit`, `Dispatch`, i inne. Tworzenie linków .[#toc-creating-links] @@ -102,46 +118,66 @@ Patrz [rozdział dotyczący routingu |routing#Modules]. Mapowanie .[#toc-mapping] ------------------------- -Określa zasady, według których nazwa klasy jest wyprowadzana z nazwy prezentera. Zapisujemy je w [konfiguracji |configuration] pod kluczem `application › mapping`. +Mapowanie definiuje zasady wyprowadzania nazwy klasy z nazwy prezentera. Reguły te są określone w [konfiguracji |configuration] pod kluczem `application › mapping`. + +Struktury katalogów wspomniane wcześniej na tej stronie są oparte na następującym mapowaniu: + +```neon +application: + mapping: App\Presentation\*\**Presenter +``` -Zacznijmy od próbki, która nie korzysta z modułów. Będziemy chcieli, aby klasy prezentera miały przestrzeń nazw `App\Presenters`. To znaczy, będziemy chcieli, aby prezenter, na przykład, `Home` mapował do klasy `App\Presenters\HomePresenter`. Można to osiągnąć dzięki następującej konfiguracji: +Jak działa mapowanie? Dla lepszego zrozumienia, wyobraźmy sobie najpierw aplikację bez modułów. Chcemy, aby klasy prezenterów należały do przestrzeni nazw `App\UI`, tak aby prezenter `Home` był mapowany na klasę `App\Presentation\HomePresenter`. Można to osiągnąć za pomocą tej konfiguracji: ```neon application: - mapping: App\Presenters\*Presenter + mapping: App\Presentation\*Presenter ``` -Zastąp nazwę prezentera gwiazdką w masce klasy, a wynikiem będzie nazwa klasy. Spokojnie! +Mapowanie to polega na zastąpieniu gwiazdki w masce `App\Presentation\*Presenter` nazwą prezentera `Home`, co daje końcową nazwę klasy `App\Presentation\HomePresenter`. Proste! + +Jednakże, jak widać w przykładach w tym i innych rozdziałach, umieszczamy klasy prezenterów w podkatalogach o tej samej nazwie, np. prezenter `Home` jest mapowany na klasę `App\Presentation\Home\HomePresenter`. Osiąga się to poprzez podwojenie gwiazdki (wymaga Nette Application 3.2): + +```neon +application: + mapping: App\Presentation\**Presenter +``` -Jeśli złamiemy prezenterów na moduły, możemy mieć niestandardowe mapowanie dla każdego modułu: +Przejdźmy teraz do mapowania prezenterów na moduły. Możemy zdefiniować konkretne mapowania dla każdego modułu: ```neon application: mapping: - Front: App\Modules\Front\Presenters\*Presenter - Admin: App\Modules\Admin\Presenters\*Presenter + Front: App\Presentation\Front\**Presenter + Admin: App\Presentation\Admin\**Presenter Api: App\Api\*Presenter ``` -Teraz prezenter `Front:Home` mapuje do klasy `App\Modules\Front\Presenters\HomePresenter`, a prezenter `Admin:Dashboard` mapuje do klasy `App\Modules\Admin\Presenters\DashboardPresenter`. +Zgodnie z tą konfiguracją, prezenter `Front:Home` mapuje się do klasy `App\Presentation\Front\Home\HomePresenter`, podczas gdy prezenter `Api:OAuth` mapuje się do klasy `App\Api\OAuthPresenter`. -Bardziej praktyczne będzie stworzenie ogólnej (gwiazdkowej) reguły, która zastąpi pierwsze dwie. W masce klasy zostanie dodana dodatkowa gwiazdka tylko dla tego modułu: +Ponieważ moduły `Front` i `Admin` mają podobne podejście do mapowania i prawdopodobnie będzie więcej takich modułów, możliwe jest utworzenie ogólnej reguły, która je zastąpi. Nowa gwiazdka dla modułu jest dodawana do maski klasy: ```neon application: mapping: - *: App\Modules\*\Presenters\*Presenter + *: App\Presentation\*\**Presenter Api: App\Api\*Presenter ``` -Ale co w przypadku, gdy korzystamy z wielu zagnieżdżonych modułów i mamy np. prezentera `Admin:User:Edit`? W takim przypadku segment z gwiazdką reprezentujący moduł dla każdego poziomu zostanie po prostu powtórzony, a wynikiem będzie klasa `App\Modules\Admin\User\Presenters\EditPresenter`. +W przypadku wielopoziomowych zagnieżdżonych modułów, takich jak prezenter `Admin:User:Edit`, segment gwiazdki powtarza się dla każdego poziomu, dając w rezultacie klasę `App\Presentation\Admin\User\Edit\EditPresenter`. -Alternatywną notacją jest użycie tablicy składającej się z trzech segmentów zamiast ciągu. Ta notacja jest równoważna z poprzednią: +Alternatywnym zapisem jest użycie tablicy złożonej z trzech segmentów zamiast łańcucha. Ta notacja jest równoważna poprzedniej: ```neon application: mapping: - *: [App\Modules, *, Presenters\*Presenter] + *: [App\UI, *, **Presenter] + Api: [App\Api, '', *Presenter] ``` -Wartość domyślna to `*Module\*Presenter`. +Jeśli mamy tylko jedną regułę w konfiguracji, tę ogólną, możemy napisać krótko: + +```neon +application: + mapping: App\Presentation\*\**Presenter +``` diff --git a/application/pl/templates.texy b/application/pl/templates.texy index a7dd044914..e50b3c662e 100644 --- a/application/pl/templates.texy +++ b/application/pl/templates.texy @@ -34,35 +34,81 @@ I to będzie szablon akcji: Definiuje blok `content`, który zostanie wstawiony w miejsce `{include content}` w układzie, a także redefiniuje blok `title`, który zastąpi `{block title}` w układzie. Spróbujcie sobie wyobrazić ten rezultat. -Wyszukiwanie szablonów .[#toc-search-for-templates] ---------------------------------------------------- +Wyszukiwanie szablonów .[#toc-template-lookup] +---------------------------------------------- -Ścieżka do szablonów jest wyprowadzana przez prezentera za pomocą prostej logiki. Spróbuje sprawdzić, czy jeden z tych plików znajduje się relatywnie od katalogu klasy prezentera, gdzie `` to nazwa aktualnego prezentera, a `` jest nazwą bieżącego zdarzenia: +W prezenterach nie trzeba określać, który szablon ma być renderowany; framework automatycznie określi ścieżkę, ułatwiając kodowanie. -- `templates//.latte` -- `templates/..latte` +Jeśli używasz struktury katalogów, w której każdy prezenter ma swój własny katalog, po prostu umieść szablon w tym katalogu pod nazwą akcji (tj. widoku). Na przykład dla akcji `default` należy użyć szablonu `default.latte`: -Jeśli szablon nie zostanie znaleziony, spróbuje poszukać w katalogu `templates` o jeden poziom wyżej, czyli na tym samym poziomie co katalog z klasą prezentera. +/--pre +app/ +└── Presentation/ + └── Home/ + ├── HomePresenter.php + └── default.latte +\-- -Jeśli tam również nie zostanie znaleziony szablon, odpowiedzią będzie [błąd 404 |presenters#Error 404 etc.]. +Jeśli używasz struktury, w której prezenterzy znajdują się w jednym katalogu, a szablony w folderze `templates`, zapisz je w pliku `..latte` lub `/.latte`: -Widok można również zmienić za pomocą strony `$this->setView('jineView')`. Lub, zamiast szukać bezpośrednio, określ nazwę pliku szablonu za pomocą `$this->template->setFile('/path/to/template.latte')`. +/--pre +app/ +└── Presenters/ + ├── HomePresenter.php + └── templates/ + ├── Home.default.latte ← 1st variant + └── Home/ + └── default.latte ← 2nd variant +\-- + +Katalog `templates` może być również umieszczony o jeden poziom wyżej, na tym samym poziomie co katalog z klasami prezenterów. + +Jeśli szablon nie zostanie znaleziony, prezenter odpowie [błędem 404 - nie znaleziono strony |presenters#Error 404 etc]. + +Widok można zmienić za pomocą `$this->setView('anotherView')`. Możliwe jest również bezpośrednie określenie pliku szablonu za pomocą `$this->template->setFile('/path/to/template.latte')`. .[note] -Pliki, w których wyszukiwane są szablony można zmienić nakładając na metodę [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()], która zwraca tablicę możliwych nazw plików. +Pliki, w których wyszukiwane są szablony, można zmienić, nadpisując metodę [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()], która zwraca tablicę możliwych nazw plików. + + +Wyszukiwanie szablonu układu .[#toc-layout-template-lookup] +----------------------------------------------------------- + +Nette automatycznie wyszukuje również plik układu. + +Jeśli używasz struktury katalogów, w której każdy prezenter ma swój własny katalog, umieść układ w folderze z prezenterem, jeśli jest on specyficzny tylko dla niego, lub poziom wyżej, jeśli jest wspólny dla wielu prezenterów: + +/--pre +app/ +└── Presentation/ + ├── @layout.latte ← common layout + └── Home/ + ├── @layout.latte ← only for Home presenter + ├── HomePresenter.php + └── default.latte +\-- + +Jeśli używasz struktury, w której prezenterzy są zgrupowani w jednym katalogu, a szablony znajdują się w folderze `templates`, layout będzie oczekiwany w następujących miejscach: -W tych plikach spodziewany jest układ: +/--pre +app/ +└── Presenters/ + ├── HomePresenter.php + └── templates/ + ├── @layout.latte ← common layout + ├── Home.@layout.latte ← only for Home, 1st variant + └── Home/ + └── @layout.latte ← only for Home, 2nd variant +\-- -- `templates//@.latte` -- `templates/.@.latte` -- `templates/@.latte` układ wspólny dla wielu prezenterów +Jeśli prezenter znajduje się w [module |modules], będzie on również wyszukiwany dalej w drzewie katalogów zgodnie z zagnieżdżeniem modułu. -Gdzie `` to nazwa aktualnego prezentera, a `` jest nazwą układu, którą domyślnie jest `'layout'`. Nazwę można zmienić za pomocą `$this->setLayout('jinyLayout')`, więc wypróbowane zostaną pliki `@jinyLayout.latte`. +Nazwę layoutu można zmienić za pomocą `$this->setLayout('layoutAdmin')`, a następnie będzie ona oczekiwana w pliku `@layoutAdmin.latte`. Można również bezpośrednio określić plik szablonu układu za pomocą `$this->setLayout('/path/to/template.latte')`. -Możesz również bezpośrednio określić nazwę pliku szablonu układu, używając `$this->setLayout('/path/to/template.latte')`. Użycie `$this->setLayout(false)` wyłączy śledzenie układu. +Użycie `$this->setLayout(false)` lub znacznika `{layout none}` wewnątrz szablonu wyłącza wyszukiwanie układu. .[note] -Pliki, w których wyszukiwane są szablony układów można zmienić nakładając na metodę [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], która zwraca tablicę możliwych nazw plików. +Pliki, w których przeszukiwane są szablony układu, można zmienić, nadpisując metodę [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], która zwraca tablicę możliwych nazw plików. Zmienne w szablonie .[#toc-variables-in-the-template] @@ -104,7 +150,7 @@ Adnotacja `@property-read` jest dla IDE i analizy statycznej, sprawi, że szepta Możesz również mieć luksus szeptania w szablonach, wystarczy zainstalować wtyczkę Latte w PhpStorm i umieścić nazwę klasy na początku szablonu, zobacz artykuł "Latte: jak wpisać system":https://blog.nette.org/pl/latte-jak-korzystac-z-systemu-typow, aby uzyskać więcej informacji: ```latte -{templateType App\Presenters\ArticleTemplate} +{templateType App\Presentation\Article\ArticleTemplate} ... ``` @@ -176,7 +222,7 @@ public function beforeRender(): void Latte w wersji 3 oferuje bardziej zaawansowany sposób tworzenia [rozszerzenia |latte:creating-extension] dla każdego projektu internetowego. Oto krótki przykład takiej klasy: ```php -namespace App\Templating; +namespace App\Presentation\Accessory; final class LatteExtension extends Latte\Extension { @@ -214,7 +260,7 @@ Rejestrujemy go za pomocą [konfiguracji |configuration#Latte]: ```neon latte: extensions: - - App\Templating\LatteExtension + - App\Presentation\Accessory\LatteExtension ``` diff --git a/application/pt/how-it-works.texy b/application/pt/how-it-works.texy index a73637f71e..b051ca4a5f 100644 --- a/application/pt/how-it-works.texy +++ b/application/pt/how-it-works.texy @@ -22,13 +22,13 @@ A estrutura do diretório é algo parecido com isto: /--pre web-project/ ├── app/ ← directory with application -│ ├── Presenters/ ← presenter classes -│ │ ├── HomePresenter.php ← Home presenter class -│ │ └── templates/ ← templates directory -│ │ ├── @layout.latte ← template of shared layout -│ │ └── Home/ ← templates for Home presenter -│ │ └── default.latte ← template for action `default` -│ ├── Router/ ← configuration of URL addresses +│ ├── Core/ ← classes básicas necessárias +│ │ └── RouterFactory.php ← configuração de endereços URL +│ ├── Presentation/ ← apresentadores, modelos e outros +│ │ ├── @layout.latte ← modelo de layout compartilhado +│ │ └── Home/ ← Diretório do apresentador Home +│ │ ├── HomePresenter.php ← Classe do apresentador da página inicial +│ │ └── default.latte ← template for action default │ └── Bootstrap.php ← booting class Bootstrap ├── bin/ ← scripts for the command line ├── config/ ← configuration files @@ -91,7 +91,7 @@ As aplicações escritas em Nette são divididas em muitos dos chamados apresent A aplicação começa pedindo ao chamado roteador que decida qual dos apresentadores deve passar o atual pedido de processamento. O roteador decide de quem é a responsabilidade. Ele analisa a URL de entrada `https://example.com/product/123`, que quer `show` um produto com `id: 123` como uma ação. É um bom hábito escrever um par de apresentador + ação separado por dois pontos como `Product:show`. -Assim, o roteador transformou a URL em um par `Presenter:action` + parâmetros, em nosso caso `Product:show` + `id: 123`. Você pode ver como é um roteador no arquivo `app/Router/RouterFactory.php` e nós o descreveremos em detalhes no capítulo [Roteamento |Routing]. +Assim, o roteador transformou a URL em um par `Presenter:action` + parâmetros, em nosso caso `Product:show` + `id: 123`. Você pode ver como é um roteador no arquivo `app/Core/RouterFactory.php` e nós o descreveremos em detalhes no capítulo [Roteamento |Routing]. Vamos em frente. O pedido já conhece o nome do apresentador e pode continuar. Ao criar um objeto `ProductPresenter`, que é o código do apresentador `Product`. Mais precisamente, pede ao contêiner DI para criar o apresentador, pois a produção de objetos é sua função. @@ -121,12 +121,9 @@ Então, o método `renderShow(123)` foi chamado, cujo código é um exemplo fict Posteriormente, o apresentador retorna a resposta. Pode ser uma página HTML, uma imagem, um documento XML, o envio de um arquivo do disco, JSON ou o redirecionamento para outra página. É importante ressaltar que se não dissermos explicitamente como responder (que é o caso de `ProductPresenter`), a resposta será renderizar o template com uma página HTML. Por quê? Bem, porque em 99% dos casos queremos desenhar um template, então o apresentador toma este comportamento como padrão e quer tornar nosso trabalho mais fácil. Esse é o ponto de vista da Nette. -Não temos nem mesmo que declarar qual modelo desenhar, ele deriva o caminho para ele de acordo com uma lógica simples. No caso do apresentador `Product` e da ação `show`, ele tenta ver se um destes arquivos de modelo existe em relação ao diretório onde se encontra a classe `ProductPresenter`: +Não precisamos nem mesmo especificar o modelo a ser renderizado; a estrutura deduzirá o caminho por si só. No caso da ação `show`, ele simplesmente tenta carregar o modelo `show.latte` no diretório com a classe `ProductPresenter`. Ele também tenta encontrar o layout no arquivo `@layout.latte` (mais informações sobre a [pesquisa de modelos |templates#Template Lookup]). -- `templates/Product/show.latte` -- `templates/Product.show.latte` - -Ele também tentará encontrar o layout no arquivo `@layout.latte` e depois renderiza o modelo. Agora a tarefa do apresentador e de todo o pedido está concluída. Se o modelo não existir, uma página com erro 404 será devolvida. Você pode ler mais sobre os apresentadores na página [Apresentadores |Presenters]. +Em seguida, os modelos são renderizados. Isso conclui a tarefa do apresentador e de todo o aplicativo, e o trabalho está concluído. Se o modelo não existir, será retornada uma página de erro 404. Você pode ler mais sobre apresentadores na página [Apresentadores |presenters]. [* request-flow.svg *] @@ -137,7 +134,7 @@ Só para ter certeza, vamos tentar recapitular todo o processo com uma URL ligei 3) o roteador decodifica a URL como um par `Home:default` 4) um objeto `HomePresenter` é criado 5) método `renderDefault()` é chamado (se existir) -6) um modelo `templates/Home/default.latte` com um layout `templates/@layout.latte` é apresentado +6) um modelo `default.latte` com um layout `@layout.latte` é apresentado Você pode ter se deparado com muitos conceitos novos agora, mas acreditamos que eles fazem sentido. Criar aplicações em Nette é uma brisa. diff --git a/application/pt/modules.texy b/application/pt/modules.texy index 372dd0e467..fffae4ceae 100644 --- a/application/pt/modules.texy +++ b/application/pt/modules.texy @@ -2,29 +2,31 @@ Módulos ******* .[perex] -Em Nette, os módulos representam as unidades lógicas que compõem uma aplicação. Eles incluem apresentadores, gabaritos, possivelmente também componentes e classes de modelos. +Os módulos dão clareza aos aplicativos Nette, facilitando a divisão em unidades lógicas. -Um diretório para apresentadores e um para modelos não seria suficiente para projetos reais. Ter dezenas de arquivos em uma pasta é pelo menos desorganizado. Como sair dela? Nós simplesmente os dividimos em subdiretórios em disco e em namespaces no código. E é exatamente isso que os módulos Nette fazem. - -Portanto, vamos esquecer uma única pasta para apresentadores e modelos e, em vez disso, criar módulos, por exemplo `Admin` e `Front`. +Da mesma forma que organizamos os arquivos em pastas em um disco rígido, na Nette podemos dividir apresentadores, modelos e outras classes auxiliares em módulos. Como isso funciona na prática? Simplesmente incorporando novos subdiretórios à estrutura. Aqui está um exemplo de uma estrutura com dois módulos, Front e Admin: /--pre -app/ -├── Presenters/ -├── Modules/ ← directory with modules -│ ├── Admin/ ← module Admin -│ │ ├── Presenters/ ← its presenters -│ │ │ ├── DashboardPresenter.php -│ │ │ └── templates/ -│ └── Front/ ← module Front -│ └── Presenters/ ← its presenters -│ └── ... +app/ +├── Presentation/ +│ ├── Admin/ ← Admin module +│ │ ├── @layout.latte +│ │ ├── Dashboard/ +│ │ │ ├── DashboardPresenter.php +│ │ │ └── default.latte +│ │ └── ... +│ ├── Front/ ← Front module +│ │ ├── @layout.latte +│ │ ├── Home/ +│ │ │ ├── HomePresenter.php +│ │ │ └── default.latte +│ │ └── ... \-- -Esta estrutura de diretório será refletida pelos namespaces de classe, portanto, por exemplo `DashboardPresenter` estará no namespace `App\Modules\Admin\Presenters`: +Essa estrutura de diretórios é refletida nos namespaces das classes, portanto, por exemplo, `DashboardPresenter` está localizado no namespace `App\Presentation\Admin\Dashboard`: ```php -namespace App\Modules\Admin\Presenters; +namespace App\Presentation\Admin\Dashboard; class DashboardPresenter extends Nette\Application\UI\Presenter { @@ -32,35 +34,49 @@ class DashboardPresenter extends Nette\Application\UI\Presenter } ``` -O `Dashboard` apresentador dentro do módulo `Admin` é referenciado dentro da aplicação usando a notação de cólon como `Admin:Dashboard`, e sua ação `default` como `Admin:Dashboard:default`. -E como a Nette propriamente dita sabe que `Admin:Dashboard` representa a classe `App\Modules\Admin\Presenters\DashboardPresenter`? Isto é determinado pelo [mapeamento |#mapping] na configuração. -Assim, a estrutura dada não é difícil de definir e você pode modificá-la de acordo com suas necessidades. +No aplicativo, nos referimos ao apresentador `Dashboard` dentro do módulo `Admin` usando a notação de dois pontos como `Admin:Dashboard`. Para sua ação `default`, nos referimos a ela como `Admin:Dashboard:default`. -Os módulos podem naturalmente conter todos os outros itens além de apresentadores e modelos, tais como componentes, classes de modelos, etc. +A estrutura apresentada não é rígida; você pode [personalizá-la totalmente de acordo com suas necessidades |#mapping] na configuração. .[tip] + +Os módulos podem incluir todos os outros arquivos, como componentes e classes auxiliares, além de apresentadores e modelos. Se estiver pensando em onde colocá-los, considere o uso de uma pasta `Accessory`: + +/--pre +app/ +├── Presentation/ +│ ├── Admin/ +│ │ ├── Accessory/ +│ │ │ ├── FormFactory.php +│ │ │ └── AdminLayout.php +│ │ ├── Dashboard/ +│ │ └── ... +\-- Módulos aninhados .[#toc-nested-modules] ---------------------------------------- -Os módulos não precisam formar apenas uma estrutura plana, você também pode criar submódulos, por exemplo: +Os módulos podem ter vários níveis de aninhamento, semelhante a uma estrutura de diretórios em um disco: /--pre -app/ -├── Modules/ ← directory with modules -│ ├── Blog/ ← module Blog -│ │ ├── Admin/ ← submodule Admin -│ │ │ ├── Presenters/ +app/ +├── Presentation/ +│ ├── Blog/ ← Blog module +│ │ ├── Admin/ ← Admin submodule +│ │ │ ├── Dashboard/ +│ │ │ └── ... +│ │ ├── Front/ ← Front submodule +│ │ │ ├── @layout.latte +│ │ │ ├── Home/ │ │ │ └── ... -│ │ └── Front/ ← submodule Front -│ │ ├── Presenters/ -│ │ └── ... -│ ├── Forum/ ← module Forum +│ ├── Forum/ ← Forum module │ │ └── ... \-- -Assim, o módulo `Blog` está dividido em `Admin` e `Front` submódulos. Mais uma vez, isto se refletirá nos namespaces, que serão `App\Modules\Blog\Admin\Presenters` etc. O apresentador `Dashboard` dentro do submódulo é referido como `Blog:Admin:Dashboard`. +O módulo `Blog` é dividido em submódulos `Admin` e `Front`. Isso também se reflete nos namespaces, que aparecem como `App\Presentation\Blog\Admin` e similares. Para nos referirmos ao apresentador `Dashboard` dentro do submódulo `Admin`, nos referimos a ele como `Blog:Admin:Dashboard`. -O ninho pode ir tão fundo quanto você desejar, de modo que sub-submódulos podem ser criados. +O aninhamento pode ser tão profundo quanto necessário, permitindo a criação de sub-submódulos. + +Por exemplo, se na administração você tem muitos apresentadores relacionados ao gerenciamento de pedidos, como `OrderDetail`, `OrderEdit`, `OrderDispatch`, etc., você pode criar um módulo `Order` no qual apresentadores como `Detail`, `Edit`, `Dispatch` e outros serão organizados. Criação de links .[#toc-creating-links] @@ -102,46 +118,66 @@ Ver [capítulo sobre roteamento |routing#Modules]. Mapeamento .[#toc-mapping] -------------------------- -Define as regras pelas quais o nome da classe é derivado do nome do apresentador. Nós as escrevemos na [configuração |configuration] sob a chave `application › mapping`. +O mapeamento define as regras para derivar o nome da classe do nome do apresentador. Essas regras são especificadas na [configuração |configuration] sob a chave `application › mapping`. + +As estruturas de diretório mencionadas anteriormente nesta página são baseadas no seguinte mapeamento: + +```neon +application: + mapping: App\Presentation\*\**Presenter +``` -Vamos começar com uma amostra que não utiliza módulos. Queremos apenas que as classes de apresentadores tenham o namespace `App\Presenters`. Isso significa que um apresentador como o `Home` deve mapear para a classe `App\Presenters\HomePresenter`. Isto pode ser conseguido através da seguinte configuração: +Como funciona o mapeamento? Para entender melhor, vamos primeiro imaginar um aplicativo sem módulos. Queremos que as classes do apresentador se enquadrem no namespace `App\UI`, de modo que o apresentador `Home` mapeie para a classe `App\Presentation\HomePresenter`. Isso pode ser obtido com esta configuração: ```neon application: - mapping: App\Presenters\*Presenter + mapping: App\Presentation\*Presenter ``` -O nome do apresentador é substituído pelo asterisco na máscara da classe e o resultado é o nome da classe. Fácil! +Esse mapeamento funciona substituindo o asterisco na máscara `App\Presentation\*Presenter` pelo nome do apresentador `Home`, resultando no nome final da classe `App\Presentation\HomePresenter`. Simples! + +Entretanto, como você pode ver nos exemplos deste e de outros capítulos, colocamos as classes de apresentador em subdiretórios homônimos, por exemplo, o apresentador `Home` é mapeado para a classe `App\Presentation\Home\HomePresenter`. Isso é feito duplicando-se o asterisco (requer o Nette Application 3.2): + +```neon +application: + mapping: App\Presentation\**Presenter +``` -Se dividirmos os apresentadores em módulos, podemos ter nosso próprio mapeamento para cada módulo: +Agora, vamos passar a mapear os apresentadores em módulos. Podemos definir mapeamentos específicos para cada módulo: ```neon application: mapping: - Front: App\Modules\Front\Presenters\*Presenter - Admin: App\Modules\Admin\Presenters\*Presenter + Front: App\Presentation\Front\**Presenter + Admin: App\Presentation\Admin\**Presenter Api: App\Api\*Presenter ``` -Agora o apresentador `Front:Home` mapeia para a classe `App\Modules\Front\Presenters\HomePresenter` e o apresentador `Admin:Dashboard` para a classe `App\Modules\Admin\Presenters\DashboardPresenter`. +De acordo com essa configuração, o apresentador `Front:Home` mapeia para a classe `App\Presentation\Front\Home\HomePresenter`, enquanto o apresentador `Api:OAuth` mapeia para a classe `App\Api\OAuthPresenter`. -É mais prático criar uma regra geral (estrela) para substituir as duas primeiras. O asterisco extra será adicionado à máscara de classe apenas para o módulo: +Como os módulos `Front` e `Admin` têm uma abordagem de mapeamento semelhante e é provável que haja mais módulos desse tipo, é possível criar uma regra geral que os substitua. Um novo asterisco para o módulo é adicionado à máscara de classe: ```neon application: mapping: - *: App\Modules\*\Presenters\*Presenter + *: App\Presentation\*\**Presenter Api: App\Api\*Presenter ``` -Mas e se usarmos módulos aninhados e tivermos um apresentador `Admin:User:Edit`? Neste caso, o segmento com um asterisco representando o módulo para cada nível é simplesmente repetido e o resultado é a classe `App\Modules\Admin\User\Presenters\EditPresenter`. +Para módulos aninhados em vários níveis, como o apresentador `Admin:User:Edit`, o segmento de asterisco se repete para cada nível, resultando na classe `App\Presentation\Admin\User\Edit\EditPresenter`. -Uma notação alternativa é utilizar um conjunto composto de três segmentos em vez de um fio. Esta notação é equivalente à anterior: +Uma notação alternativa é usar uma matriz composta de três segmentos em vez de uma cadeia de caracteres. Essa notação é equivalente à anterior: ```neon application: mapping: - *: [App\Modules, *, Presenters\*Presenter] + *: [App\UI, *, **Presenter] + Api: [App\Api, '', *Presenter] ``` -O valor padrão é `*Module\*Presenter`. +Se tivermos apenas uma regra na configuração, a geral, podemos escrever de forma resumida: + +```neon +application: + mapping: App\Presentation\*\**Presenter +``` diff --git a/application/pt/templates.texy b/application/pt/templates.texy index 059e35178e..76f93dd8ba 100644 --- a/application/pt/templates.texy +++ b/application/pt/templates.texy @@ -34,35 +34,81 @@ E este poderia ser o modelo de ação: Ele define o bloco `content`, que é inserido no lugar de `{include content}` no layout, e também redefine o bloco `title`, que sobrescreve `{block title}` no layout. Tente imaginar o resultado. -Busca de modelos .[#toc-search-for-templates] ---------------------------------------------- +Pesquisa de modelos .[#toc-template-lookup] +------------------------------------------- -O caminho para os modelos é deduzido de acordo com uma lógica simples. Ele tenta ver se um destes arquivos de gabaritos existe em relação ao diretório onde se encontra a classe apresentadora, onde `` é o nome do atual apresentador e `` é o nome da ação atual: +Nos apresentadores, você não precisa especificar qual modelo deve ser renderizado; a estrutura determinará automaticamente o caminho, facilitando a codificação para você. -- `templates//.latte` -- `templates/..latte` +Se você usar uma estrutura de diretórios em que cada apresentador tenha seu próprio diretório, basta colocar o modelo nesse diretório com o nome da ação (ou seja, visualização). Por exemplo, para a ação `default`, use o modelo `default.latte`: -Se o modelo não for encontrado, ele tentará procurar no diretório `templates` um nível acima, ou seja, no mesmo nível que o diretório com a classe apresentadora. +/--pre +app/ +└── Presentation/ + └── Home/ + ├── HomePresenter.php + └── default.latte +\-- -Se o modelo também não for encontrado lá, a resposta é um [erro 404 |presenters#Error 404 etc.]. +Se você usar uma estrutura em que os apresentadores estejam juntos em um diretório e os modelos em uma pasta `templates`, salve-os em um arquivo `..latte` ou `/.latte`: -Você também pode mudar a visão usando `$this->setView('otherView')`. Ou, em vez de procurar, especifique diretamente o nome do arquivo modelo usando `$this->template->setFile('/path/to/template.latte')`. +/--pre +app/ +└── Presenters/ + ├── HomePresenter.php + └── templates/ + ├── Home.default.latte ← 1st variant + └── Home/ + └── default.latte ← 2nd variant +\-- + +O diretório `templates` também pode ser colocado um nível acima, no mesmo nível do diretório com as classes de apresentador. + +Se o modelo não for encontrado, o apresentador responderá com o [erro 404 - página não encontrada |presenters#Error 404 etc]. + +Você pode alterar a visualização usando `$this->setView('anotherView')`. Também é possível especificar diretamente o arquivo de modelo com `$this->template->setFile('/path/to/template.latte')`. .[note] -Você pode alterar os caminhos onde os modelos são pesquisados substituindo o método de [formataçãoTemplateFiles |api:Nette\Application\UI\Presenter::formatTemplateFiles()], que retorna um conjunto de possíveis caminhos de arquivos. +Os arquivos onde os modelos são pesquisados podem ser alterados substituindo o método [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()], que retorna uma matriz de possíveis nomes de arquivos. + + +Pesquisa de modelos de layout .[#toc-layout-template-lookup] +------------------------------------------------------------ + +O Nette também procura automaticamente o arquivo de layout. + +Se você usar uma estrutura de diretórios em que cada apresentador tenha seu próprio diretório, coloque o layout na pasta com o apresentador, se for específico apenas para ele, ou em um nível superior, se for comum a vários apresentadores: + +/--pre +app/ +└── Presentation/ + ├── @layout.latte ← common layout + └── Home/ + ├── @layout.latte ← only for Home presenter + ├── HomePresenter.php + └── default.latte +\-- + +Se você usar uma estrutura em que os apresentadores estejam agrupados em um diretório e os modelos estejam em uma pasta `templates`, o layout será esperado nos seguintes locais: -O layout é esperado nos seguintes arquivos: +/--pre +app/ +└── Presenters/ + ├── HomePresenter.php + └── templates/ + ├── @layout.latte ← common layout + ├── Home.@layout.latte ← only for Home, 1st variant + └── Home/ + └── @layout.latte ← only for Home, 2nd variant +\-- -- `templates//@.latte` -- `templates/.@.latte` -- `templates/@.latte` layout comum a vários apresentadores +Se o apresentador estiver em um [módulo |modules], ele também pesquisará mais acima na árvore de diretórios, de acordo com o aninhamento do módulo. -`` é o nome do atual apresentador e `` é o nome do layout, que é, por padrão, `'layout'`. O nome pode ser alterado com `$this->setLayout('otherLayout')`, para que os arquivos `@otherLayout.latte` sejam experimentados. +O nome do layout pode ser alterado usando `$this->setLayout('layoutAdmin')` e, em seguida, ele será esperado no arquivo `@layoutAdmin.latte`. Você também pode especificar diretamente o arquivo de modelo de layout usando `$this->setLayout('/path/to/template.latte')`. -Você também pode especificar diretamente o nome do arquivo do modelo de layout usando `$this->setLayout('/path/to/template.latte')`. O uso do `$this->setLayout(false)` desabilitará a busca do layout. +O uso de `$this->setLayout(false)` ou da tag `{layout none}` dentro do modelo desativa a pesquisa de layout. .[note] -Você pode alterar os caminhos onde os modelos são pesquisados, substituindo o método [formatLayoutTemplateFiles |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], que retorna uma série de possíveis caminhos de arquivos. +Os arquivos em que os modelos de layout são pesquisados podem ser alterados substituindo o método [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], que retorna uma matriz de possíveis nomes de arquivos. Variáveis no modelo .[#toc-variables-in-the-template] @@ -104,7 +150,7 @@ A anotação `@property-read` é para IDE e análise estática, fará com que o Você também pode se dar ao luxo de sussurrar nos modelos, basta instalar o plugin Latte no PhpStorm e especificar o nome da classe no início do modelo, veja o artigo "Latte: como digitar sistema":https://blog.nette.org/pt/latte-como-usar-o-sistema-de-tipo: ```latte -{templateType App\Presenters\ArticleTemplate} +{templateType App\Presentation\Article\ArticleTemplate} ... ``` @@ -176,7 +222,7 @@ public function beforeRender(): void A versão 3 do Latte oferece uma maneira mais avançada, criando uma [extensão |latte:creating-extension] para cada projeto web. Aqui está um exemplo rudimentar de tal classe: ```php -namespace App\Templating; +namespace App\Presentation\Accessory; final class LatteExtension extends Latte\Extension { @@ -214,7 +260,7 @@ Registramos usando [a configuração#Latte |configuration#Latte]: ```neon latte: extensions: - - App\Templating\LatteExtension + - App\Presentation\Accessory\LatteExtension ``` diff --git a/application/ro/how-it-works.texy b/application/ro/how-it-works.texy index 75291693ee..fda3fa0a75 100644 --- a/application/ro/how-it-works.texy +++ b/application/ro/how-it-works.texy @@ -22,13 +22,13 @@ Structura directoarelor arată cam așa: /--pre web-project/ ├── app/ ← directory with application -│ ├── Presenters/ ← presenter classes -│ │ ├── HomePresenter.php ← Home presenter class -│ │ └── templates/ ← templates directory -│ │ ├── @layout.latte ← template of shared layout -│ │ └── Home/ ← templates for Home presenter -│ │ └── default.latte ← template for action `default` -│ ├── Router/ ← configuration of URL addresses +│ ├── Core/ ← cursuri de bază necesare +│ │ └── RouterFactory.php ← configurare adrese URL +│ ├── Presentation/ ← prezentări, șabloane & co. +│ │ ├── @layout.latte ← șablon de prezentare partajată +│ │ └── Home/ ← Directorul de prezentatori de acasă +│ │ ├── HomePresenter.php ← Clasa de prezentator de acasă +│ │ └── default.latte ← șablon pentru acțiune default │ └── Bootstrap.php ← booting class Bootstrap ├── bin/ ← scripts for the command line ├── config/ ← configuration files @@ -91,7 +91,7 @@ Aplicațiile scrise în Nette sunt împărțite în mai multe așa-numite prezen Aplicația începe prin a cere așa-numitului router să decidă care dintre prezentatori să transmită cererea curentă pentru procesare. Routerul decide a cui este responsabilitatea. Acesta se uită la URL-ul de intrare `https://example.com/product/123`, care dorește să `show` un produs cu `id: 123` ca acțiune. Este un bun obicei să se scrie perechile prezentator + acțiune separate de două puncte ca `Product:show`. -Astfel, routerul a transformat URL-ul într-o pereche `Presenter:action` + parametri, în cazul nostru `Product:show` + `id: 123`. Puteți vedea cum arată un router în fișierul `app/Router/RouterFactory.php` și îl vom descrie în detaliu în capitolul [Routing |Routing]. +Astfel, routerul a transformat URL-ul într-o pereche `Presenter:action` + parametri, în cazul nostru `Product:show` + `id: 123`. Puteți vedea cum arată un router în fișierul `app/Core/RouterFactory.php` și îl vom descrie în detaliu în capitolul [Routing |Routing]. Să mergem mai departe. Aplicația cunoaște deja numele prezentatorului și poate continua. Prin crearea unui obiect `ProductPresenter`, care este codul prezentatorului `Product`. Mai exact, solicită containerului DI crearea prezentatorului, deoarece producerea de obiecte este sarcina acestuia. @@ -121,12 +121,9 @@ Așadar, a fost apelată metoda `renderShow(123)`, al cărei cod este un exemplu Ulterior, prezentatorul returnează răspunsul. Acesta poate fi o pagină HTML, o imagine, un document XML, trimiterea unui fișier de pe disc, JSON sau redirecționarea către o altă pagină. Este important de reținut că, dacă nu spunem în mod explicit cum să răspundem (ceea ce este cazul `ProductPresenter`), răspunsul va fi redarea șablonului cu o pagină HTML. De ce? Ei bine, pentru că în 99% din cazuri dorim să desenăm un șablon, așa că prezentatorul ia acest comportament ca fiind implicit și dorește să ne ușureze munca. Acesta este punctul de vedere al lui Nette. -Nici măcar nu trebuie să precizăm ce șablon să desenăm, el derivă calea către acesta conform unei logici simple. În cazul prezentatorului `Product` și al acțiunii `show`, el încearcă să vadă dacă unul dintre aceste fișiere șablon există în raport cu directorul în care se află clasa `ProductPresenter`: +Nici măcar nu trebuie să specificăm ce șablon să redăm; cadrul va deduce singur calea. În cazul acțiunii `show`, acesta încearcă pur și simplu să încarce șablonul `show.latte` din directorul cu clasa `ProductPresenter`. De asemenea, încearcă să găsească aspectul în fișierul `@layout.latte` (mai multe informații despre [căutarea șabloanelor |templates#Template Lookup]). -- `templates/Product/show.latte` -- `templates/Product.show.latte` - -De asemenea, va încerca să găsească aspectul în fișierul `@layout.latte` și apoi va reda șablonul. Acum sarcina prezentatorului și a întregii aplicații este finalizată. În cazul în care șablonul nu există, va fi returnată o pagină cu eroarea 404. Puteți citi mai multe despre prezentatori pe pagina [Prezentatori |Presenters]. +Ulterior, șabloanele sunt redate. Acest lucru încheie sarcina prezentatorului și a întregii aplicații, iar activitatea este finalizată. În cazul în care șablonul nu există, ar fi returnată o pagină de eroare 404. Puteți citi mai multe despre prezentatori pe pagina [Prezentatori |presenters]. [* request-flow.svg *] @@ -137,7 +134,7 @@ Doar pentru a fi siguri, să încercăm să recapitulăm întregul proces cu un 3) routerul decodifică URL-ul ca o pereche `Home:default` 4) este creat un obiect `HomePresenter` 5) se apelează metoda `renderDefault()` (dacă există) -6) este redat un șablon `templates/Home/default.latte` cu un layout `templates/@layout.latte` +6) este redat un șablon `default.latte` cu un layout `@layout.latte` Este posibil să fi întâlnit acum o mulțime de concepte noi, dar noi credem că acestea au sens. Crearea de aplicații în Nette este o joacă de copii. diff --git a/application/ro/modules.texy b/application/ro/modules.texy index 1e7cd0fee4..439e85e426 100644 --- a/application/ro/modules.texy +++ b/application/ro/modules.texy @@ -2,29 +2,31 @@ Module ****** .[perex] -În Nette, modulele reprezintă unitățile logice care alcătuiesc o aplicație. Acestea includ prezentatori, șabloane, eventual și componente și clase de model. +Modulele aduc claritate aplicațiilor Nette, facilitând divizarea ușoară în unități logice. -Un singur director pentru prezentatori și unul pentru șabloane nu ar fi suficient pentru proiectele reale. A avea zeci de fișiere într-un singur dosar este cel puțin neorganizat. Cum se poate ieși din asta? Pur și simplu le împărțim în subdirectoare pe disc și în spații de nume în cod. Și asta este exact ceea ce fac modulele Nette. - -Așadar, să uităm de un singur dosar pentru prezentatori și șabloane și să creăm în schimb module, de exemplu `Admin` și `Front`. +Similar cu organizarea fișierelor în foldere pe un hard disk, în Nette putem împărți în module prezentatorii, șabloanele și alte clase auxiliare. Cum funcționează acest lucru în practică? Pur și simplu prin încorporarea de noi subdirectoare în structură. Iată un exemplu de structură cu două module, Front și Admin: /--pre -app/ -├── Presenters/ -├── Modules/ ← directory with modules -│ ├── Admin/ ← module Admin -│ │ ├── Presenters/ ← its presenters -│ │ │ ├── DashboardPresenter.php -│ │ │ └── templates/ -│ └── Front/ ← module Front -│ └── Presenters/ ← its presenters -│ └── ... +app/ +├── Presentation/ +│ ├── Admin/ ← Admin module +│ │ ├── @layout.latte +│ │ ├── Dashboard/ +│ │ │ ├── DashboardPresenter.php +│ │ │ └── default.latte +│ │ └── ... +│ ├── Front/ ← Front module +│ │ ├── @layout.latte +│ │ ├── Home/ +│ │ │ ├── HomePresenter.php +│ │ │ └── default.latte +│ │ └── ... \-- -Această structură de directoare va fi reflectată de spațiile de nume ale claselor, astfel încât, de exemplu, `DashboardPresenter` va fi în spațiul de nume `App\Modules\Admin\Presenters`: +Această structură de directoare se reflectă în spațiile de nume ale claselor, astfel încât, de exemplu, `DashboardPresenter` se află în spațiul de nume `App\Presentation\Admin\Dashboard`: ```php -namespace App\Modules\Admin\Presenters; +namespace App\Presentation\Admin\Dashboard; class DashboardPresenter extends Nette\Application\UI\Presenter { @@ -32,35 +34,49 @@ class DashboardPresenter extends Nette\Application\UI\Presenter } ``` -Prezentatorul `Dashboard` din cadrul modulului `Admin` este referit în cadrul aplicației folosind notația de două puncte ca `Admin:Dashboard`, iar acțiunea `default` ca `Admin:Dashboard:default`. -Și de unde știe Nette proper că `Admin:Dashboard` reprezintă clasa `App\Modules\Admin\Presenters\DashboardPresenter`? Acest lucru este determinat de [cartografierea |#mapping] din configurație. -Așadar, structura dată nu este prestabilită și o puteți modifica în funcție de nevoile dumneavoastră. +În aplicație, ne referim la prezentatorul `Dashboard` din cadrul modulului `Admin` folosind notația două puncte ca `Admin:Dashboard`. Pentru acțiunea `default`, ne referim la acesta ca `Admin:Dashboard:default`. -Modulele pot conține, bineînțeles, toate celelalte elemente în afară de prezentatori și șabloane, cum ar fi componente, clase de modele etc. +Structura prezentată nu este rigidă; [o |#mapping] puteți [personaliza complet |#mapping] în funcție [de nevoile dumneavoastră |#mapping] în cadrul configurației. .[tip] + +Modulele pot include toate celelalte fișiere, cum ar fi componentele și clasele auxiliare, pe lângă prezentatori și șabloane. Dacă vă gândiți unde să le plasați pe acestea, luați în considerare utilizarea unui dosar `Accessory`: + +/--pre +app/ +├── Presentation/ +│ ├── Admin/ +│ │ ├── Accessory/ +│ │ │ ├── FormFactory.php +│ │ │ └── AdminLayout.php +│ │ ├── Dashboard/ +│ │ └── ... +\-- Module imbricate .[#toc-nested-modules] --------------------------------------- -Modulele nu trebuie să formeze doar o structură plată, ci puteți crea și submodule, de exemplu: +Modulele pot avea mai multe niveluri de anvelopare, similar cu o structură de directoare pe un disc: /--pre -app/ -├── Modules/ ← directory with modules -│ ├── Blog/ ← module Blog -│ │ ├── Admin/ ← submodule Admin -│ │ │ ├── Presenters/ +app/ +├── Presentation/ +│ ├── Blog/ ← Blog module +│ │ ├── Admin/ ← Admin submodule +│ │ │ ├── Dashboard/ +│ │ │ └── ... +│ │ ├── Front/ ← Front submodule +│ │ │ ├── @layout.latte +│ │ │ ├── Home/ │ │ │ └── ... -│ │ └── Front/ ← submodule Front -│ │ ├── Presenters/ -│ │ └── ... -│ ├── Forum/ ← module Forum +│ ├── Forum/ ← Forum module │ │ └── ... \-- -Astfel, modulul `Blog` este împărțit în submodulele `Admin` și `Front`. Din nou, acest lucru se va reflecta în spațiile de nume, care vor fi `App\Modules\Blog\Admin\Presenters` etc. Prezentatorul `Dashboard` din interiorul submodulului este denumit `Blog:Admin:Dashboard`. +Modulul `Blog` este împărțit în submodulele `Admin` și `Front`. Acest lucru se reflectă și în spațiile de nume, care apar apoi ca `App\Presentation\Blog\Admin` și similar. Pentru a ne referi la prezentatorul `Dashboard` din cadrul submodulului `Admin`, ne referim la acesta ca `Blog:Admin:Dashboard`. -Anveloparea poate merge cât de adânc doriți, astfel încât pot fi create sub-submodule. +Nesting-ul poate fi atât de adânc cât este necesar, permițând crearea de sub-submodule. + +De exemplu, dacă în administrație aveți mulți prezentatori legați de gestionarea comenzilor, cum ar fi `OrderDetail`, `OrderEdit`, , `OrderDispatch`, etc., puteți crea un modul `Order` în care vor fi organizați prezentatori precum `Detail`, `Edit`, `Dispatch`, și alții. Crearea de legături .[#toc-creating-links] @@ -102,46 +118,66 @@ A se vedea [capitolul privind rutarea |routing#Modules]. Cartografiere .[#toc-mapping] ----------------------------- -Definește regulile prin care numele clasei este derivat din numele prezentatorului. Le scriem în [configurație |configuration] sub cheia `application › mapping`. +Cartografierea definește regulile de derivare a numelui clasei din numele prezentatorului. Aceste reguli sunt specificate în [configurație |configuration] la cheia `application › mapping`. + +Structurile de directoare menționate anterior pe această pagină se bazează pe următoarea cartografiere: + +```neon +application: + mapping: App\Presentation\*\**Presenter +``` -Să începem cu un exemplu care nu folosește module. Vom dori doar ca clasele de prezentator să aibă spațiul de nume `App\Presenters`. Aceasta înseamnă că un prezentator precum `Home` ar trebui să se mapeze la clasa `App\Presenters\HomePresenter`. Acest lucru poate fi realizat prin următoarea configurație: +Cum funcționează cartografierea? Pentru o mai bună înțelegere, să ne imaginăm mai întâi o aplicație fără module. Dorim ca clasele de prezentatori să se încadreze în spațiul de nume `App\UI`, astfel încât prezentatorul `Home` să fie asociat cu clasa `App\Presentation\HomePresenter`. Acest lucru poate fi realizat cu această configurație: ```neon application: - mapping: App\Presenters\*Presenter + mapping: App\Presentation\*Presenter ``` -Numele prezentatorului este înlocuit cu un asterisc în masca clasei, iar rezultatul este numele clasei. Ușor! +Această cartografiere funcționează prin înlocuirea asteriscului din masca `App\Presentation\*Presenter` cu numele prezentatorului `Home`, rezultând numele final al clasei `App\Presentation\HomePresenter`. Simplu! + +Cu toate acestea, după cum puteți vedea în exemplele din acest capitol și din alte capitole, plasăm clasele de prezentatori în subdirectoare eponime, de exemplu, prezentatorul `Home` este mapat în clasa `App\Presentation\Home\HomePresenter`. Acest lucru se realizează prin dublarea asteriscului (necesită Nette Application 3.2): + +```neon +application: + mapping: App\Presentation\**Presenter +``` -Dacă împărțim prezentatorii în module, putem avea propria mapare pentru fiecare modul: +Acum, să trecem la maparea prezentatorilor în module. Putem defini mape specifice pentru fiecare modul: ```neon application: mapping: - Front: App\Modules\Front\Presenters\*Presenter - Admin: App\Modules\Admin\Presenters\*Presenter + Front: App\Presentation\Front\**Presenter + Admin: App\Presentation\Admin\**Presenter Api: App\Api\*Presenter ``` -Acum, prezentatorul `Front:Home` se referă la clasa `App\Modules\Front\Presenters\HomePresenter` și prezentatorul `Admin:Dashboard` la clasa `App\Modules\Admin\Presenters\DashboardPresenter`. +În conformitate cu această configurație, prezentatorul `Front:Home` se mapează la clasa `App\Presentation\Front\Home\HomePresenter`, în timp ce prezentatorul `Api:OAuth` se mapează la clasa `App\Api\OAuthPresenter`. -Este mai practic să creăm o regulă generală (stea) care să le înlocuiască pe primele două. Asteriscul suplimentar va fi adăugat la masca clasei doar pentru modul: +Deoarece modulele `Front` și `Admin` au o abordare similară de cartografiere și este posibil să existe mai multe astfel de module, este posibil să se creeze o regulă generală care să le înlocuiască. Un nou asterisc pentru modul este adăugat la masca clasei: ```neon application: mapping: - *: App\Modules\*\Presenters\*Presenter + *: App\Presentation\*\**Presenter Api: App\Api\*Presenter ``` -Dar ce se întâmplă dacă folosim module imbricate și avem un prezentator `Admin:User:Edit`? În acest caz, segmentul cu un asterisc care reprezintă modulul pentru fiecare nivel se repetă pur și simplu, iar rezultatul este clasa `App\Modules\Admin\User\Presenters\EditPresenter`. +Pentru modulele imbricate pe mai multe niveluri, cum ar fi prezentatorul `Admin:User:Edit`, segmentul de asterisc se repetă pentru fiecare nivel, rezultând clasa `App\Presentation\Admin\User\Edit\EditPresenter`. -O notație alternativă este utilizarea unui array format din trei segmente în loc de un șir de caractere. Această notație este echivalentă cu cea anterioară: +O notație alternativă constă în utilizarea unei matrice compuse din trei segmente în locul unui șir de caractere. Această notație este echivalentă cu cea anterioară: ```neon application: mapping: - *: [App\Modules, *, Presenters\*Presenter] + *: [App\UI, *, **Presenter] + Api: [App\Api, '', *Presenter] ``` -Valoarea implicită este `*Module\*Presenter`. +Dacă avem doar o singură regulă în configurație, cea generală, putem scrie pe scurt: + +```neon +application: + mapping: App\Presentation\*\**Presenter +``` diff --git a/application/ro/templates.texy b/application/ro/templates.texy index abcead647e..d9756d6418 100644 --- a/application/ro/templates.texy +++ b/application/ro/templates.texy @@ -34,35 +34,81 @@ Iar acesta ar putea fi șablonul de acțiune: Acesta definește blocul `content`, care este inserat în locul lui `{include content}` în machetă și, de asemenea, redefinește blocul `title`, care suprascrie `{block title}` în machetă. Încercați să vă imaginați rezultatul. -Căutați șabloane .[#toc-search-for-templates] ---------------------------------------------- +Căutarea șablonului .[#toc-template-lookup] +------------------------------------------- + +În prezentări, nu trebuie să specificați ce șablon trebuie redat; cadrul va determina automat calea, ceea ce vă ușurează codificarea. + +Dacă utilizați o structură de directoare în care fiecare prezentator are propriul director, plasați pur și simplu șablonul în acest director sub numele acțiunii (de exemplu, view). De exemplu, pentru acțiunea `default`, utilizați șablonul `default.latte`: -Calea către șabloane este dedusă conform unei logici simple. Se încearcă să se vadă dacă unul dintre aceste fișiere șablon există în raport cu directorul în care se află clasa presenter, unde `` este numele prezentatorului curent și `` este numele acțiunii curente: +/--pre +app/ +└── Presentation/ + └── Home/ + ├── HomePresenter.php + └── default.latte +\-- -- `templates//.latte` -- `templates/..latte` +Dacă utilizați o structură în care prezentatorii sunt împreună într-un singur director, iar șabloanele într-un dosar `templates`, salvați-l fie într-un fișier `..latte` sau `/.latte`: -Dacă șablonul nu este găsit, se va încerca căutarea în directorul `templates` cu un nivel mai sus, adică la același nivel cu directorul cu clasa de prezentator. +/--pre +app/ +└── Presenters/ + ├── HomePresenter.php + └── templates/ + ├── Home.default.latte ← 1st variant + └── Home/ + └── default.latte ← 2nd variant +\-- -Dacă șablonul nu este găsit nici acolo, răspunsul este o [eroare 404 |presenters#Error 404 etc.]. +Directorul `templates` poate fi, de asemenea, plasat un nivel mai sus, la același nivel cu directorul cu clasele de prezentatori. -De asemenea, puteți schimba vizualizarea folosind `$this->setView('otherView')`. Sau, în loc să căutați, specificați direct numele fișierului șablon folosind `$this->template->setFile('/path/to/template.latte')`. +În cazul în care șablonul nu este găsit, prezentatorul răspunde cu [eroarea 404 - page not found |presenters#Error 404 etc]. + +Puteți schimba vizualizarea folosind `$this->setView('anotherView')`. De asemenea, este posibilă specificarea directă a fișierului șablon cu `$this->template->setFile('/path/to/template.latte')`. .[note] -Puteți modifica căile în care sunt căutate șabloanele prin suprascrierea metodei [formatTemplateFiles |api:Nette\Application\UI\Presenter::formatTemplateFiles()], care returnează o matrice de posibile căi de acces la fișiere. +Fișierele în care sunt căutate șabloanele pot fi modificate prin suprascrierea metodei [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()], care returnează o matrice de nume de fișiere posibile. + + +Căutarea șabloanelor de prezentare .[#toc-layout-template-lookup] +----------------------------------------------------------------- + +De asemenea, Nette caută automat fișierul de machetare. + +Dacă folosiți o structură de directoare în care fiecare prezentator are propriul director, plasați macheta fie în folderul cu prezentatorul, dacă este specifică doar acestuia, fie la un nivel superior, dacă este comună mai multor prezentatori: + +/--pre +app/ +└── Presentation/ + ├── @layout.latte ← common layout + └── Home/ + ├── @layout.latte ← only for Home presenter + ├── HomePresenter.php + └── default.latte +\-- + +Dacă utilizați o structură în care prezentatorii sunt grupați într-un singur director, iar șabloanele se află într-un dosar `templates`, macheta va fi așteptată în următoarele locuri: -Prezentarea este așteptată în următoarele fișiere: +/--pre +app/ +└── Presenters/ + ├── HomePresenter.php + └── templates/ + ├── @layout.latte ← common layout + ├── Home.@layout.latte ← only for Home, 1st variant + └── Home/ + └── @layout.latte ← only for Home, 2nd variant +\-- -- `templates//@.latte` -- `templates/.@.latte` -- `templates/@.latte` aspect comun pentru mai mulți prezentatori +Dacă prezentatorul se află într-un [modul |modules], se va căuta și mai sus în arborele de directoare, în funcție de structura de anvelopare a modulului. -`` este numele prezentatorului curent și `` este numele structurii, care este în mod implicit `'layout'`. Numele poate fi schimbat cu `$this->setLayout('otherLayout')`, astfel încât să se încerce să se utilizeze fișierele `@otherLayout.latte`. +Numele prezentării poate fi schimbat folosind `$this->setLayout('layoutAdmin')` și apoi va fi așteptat în fișierul `@layoutAdmin.latte`. De asemenea, puteți specifica direct fișierul șablon de prezentare folosind `$this->setLayout('/path/to/template.latte')`. -De asemenea, puteți specifica direct numele de fișier al șablonului de machetă cu `$this->setLayout('/path/to/template.latte')`. Utilizarea `$this->setLayout(false)` va dezactiva căutarea de machete. +Utilizarea `$this->setLayout(false)` sau a etichetei `{layout none}` în interiorul șablonului dezactivează căutarea de layout. .[note] -Puteți modifica căile de căutare a șabloanelor prin suprascrierea metodei [formatLayoutTemplateFiles |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], care returnează o matrice de posibile căi de acces la fișiere. +Fișierele în care sunt căutate șabloanele de prezentare pot fi modificate prin suprascrierea metodei [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], care returnează o matrice de nume de fișiere posibile. Variabilele din șablon .[#toc-variables-in-the-template] @@ -104,7 +150,7 @@ Adnotarea `@property-read` este pentru IDE și analiza statică, va face ca auto Vă puteți permite și luxul de a șopti în șabloane, trebuie doar să instalați pluginul în PhpStorm și să specificați numele clasei la începutul șablonului, consultați articolul "Latte: cum se tastează sistemul":https://blog.nette.org/ro/latte-cum-se-utilizeaza-sistemul-de-tipuri: ```latte -{templateType App\Presenters\ArticleTemplate} +{templateType App\Presentation\Article\ArticleTemplate} ... ``` @@ -176,7 +222,7 @@ public function beforeRender(): void Latte versiunea 3 oferă o metodă mai avansată prin crearea unei [extensii |latte:creating-extension] pentru fiecare proiect web. Iată un exemplu aproximativ al unei astfel de clase: ```php -namespace App\Templating; +namespace App\Presentation\Accessory; final class LatteExtension extends Latte\Extension { @@ -214,7 +260,7 @@ O înregistrăm folosind [configuration#Latte]: ```neon latte: extensions: - - App\Templating\LatteExtension + - App\Presentation\Accessory\LatteExtension ``` diff --git a/application/ru/how-it-works.texy b/application/ru/how-it-works.texy index 39b20c686c..1d6d49ab9d 100644 --- a/application/ru/how-it-works.texy +++ b/application/ru/how-it-works.texy @@ -22,13 +22,13 @@ /--pre web-project/ ├── app/ ← каталог с приложением -│ ├── Presenters/ ← классы презентеров -│ │ ├── HomePresenter.php ← Класс презентера главной страницы -│ │ └── templates/ ← директория шаблонов -│ │ ├── @layout.latte ← шаблон общего макета -│ │ └── Home/ ← шаблоны презентера главной страницы -│ │ └── default.latte ← шаблон действия `default` -│ ├── Router/ ← конфигурация URL-адресов +│ ├── Core/ ← основные необходимые классы +│ │ └── RouterFactory.php ← настройка URL-адресов +│ ├── Presentation/ ← презентаторы, шаблоны и др. +│ │ ├── @layout.latte ← шаблон общего макета +│ │ └── Home/ ← Главная директория ведущих +│ │ ├── HomePresenter.php ← Класс презентера дома +│ │ └── default.latte ← шаблон для действий default │ └── Bootstrap.php ← загрузочный класс Bootstrap ├── bin/ ← скрипты командной строки ├── config/ ← файлы конфигурации @@ -91,7 +91,7 @@ Nette — это наставник, который направляет вас Приложение начинает работу с того, что просит так называемый маршрутизатор решить, какому из презентеров передать текущий запрос на обработку. Маршрутизатор решает, чья это ответственность. Он просматривает входной URL `https://example.com/product/123` и, основываясь на том, как он настроен, решает, что это задание, например, для **презентера** `Product`, который хочет `показать` продукт с `id: 123` как действие. Хорошей привычкой является написание пар презентер + действие, разделенных двоеточием: `Продукт:показать`. -Поэтому маршрутизатор преобразовал URL в пару `Presenter:action` + параметры, в нашем случае `Product:show` + `id`: 123`. Вы можете увидеть, как выглядит маршрутизатор в файле `app/Router/RouterFactory.php`, и мы подробно опишем его в главе [Маршрутизация |routing]. +Поэтому маршрутизатор преобразовал URL в пару `Presenter:action` + параметры, в нашем случае `Product:show` + `id`: 123`. Вы можете увидеть, как выглядит маршрутизатор в файле `app/Core/RouterFactory.php`, и мы подробно опишем его в главе [Маршрутизация |routing]. Давайте двигаться дальше. Приложение уже знает имя презентера и может продолжить работу. Путем создания объекта `ProductPresenter`, который является кодом презентера `Product`. Точнее, он просит контейнер DI создать презентера, потому что создание объектов — это его работа. @@ -121,12 +121,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter После этого презентер возвращает ответ. Это может быть HTML-страница, изображение, XML-документ, отправка файла с диска, JSON или перенаправление на другую страницу. Важно отметить, что если мы явно не указываем, как реагировать (что имеет место в случае с `ProductPresenter`), ответом будет отображение шаблона с HTML-страницей. Почему? Ну, потому что в 99% случаев мы хотим отобразить шаблон, поэтому презентер принимает такое поведение по умолчанию и хочет облегчить нашу работу. Это точка зрения Nette. -Нам даже не нужно указывать, какой шаблон нужно вывести, он сам выводит путь к нему в соответствии с простой логикой. В случае с презентером `Product` и действием `show`, он пытается проверить, существует ли один из этих файлов шаблонов относительно каталога, в котором находится класс `ProductPresenter`: +Нам даже не нужно указывать, какой шаблон рендерить, фреймворк сам определит путь. В случае с действием `show` он просто попытается загрузить шаблон `show.latte` в директории с классом `ProductPresenter`. Он также попытается найти макет в файле `@layout.latte` (подробнее о [поиске шаблонов |templates#Template Lookup]). -- `templates/Product/show.latte` -- `templates/Product.show.latte` - -И затем он отображает шаблон. Теперь задача презентера и всего приложения выполнена. Если шаблон не существует, будет возвращена страница с ошибкой 404. Подробнее о презентерах вы можете прочитать на странице [Презентеры |presenters]. +Затем происходит рендеринг шаблонов. На этом задача ведущего и всего приложения завершена, и работа закончена. Если шаблон не существует, будет возвращена страница с ошибкой 404. Подробнее о презентерах можно прочитать на странице [Презентеры |presenters]. [* request-flow.svg *] @@ -137,7 +134,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter 3) маршрутизатор декодирует URL как пару `Home:default` 4) создается объект `HomePresenter` 5) вызывается метод `renderDefault()` (если существует) -6) шаблон `templates/Home/default.latte` с макетом `templates/@layout.latte` отрисован +6) шаблон `default.latte` с макетом `@layout.latte` отрисован Возможно, сейчас вы столкнулись с множеством новых понятий, но мы считаем, что они имеют смысл. Создавать приложения в Nette — проще простого. diff --git a/application/ru/modules.texy b/application/ru/modules.texy index e7a6b8b277..66c313243f 100644 --- a/application/ru/modules.texy +++ b/application/ru/modules.texy @@ -2,29 +2,31 @@ ****** .[perex] -В Nette модули представляют собой логические единицы, из которых состоит приложение. Они включают ведущие, шаблоны, возможно, компоненты и классы моделей. +Модули вносят ясность в приложения Nette, облегчая разделение на логические блоки. -Одного компонента для презентаторов и одного для шаблонов будет недостаточно для реальных проектов. Наличие десятков файлов в одной папке по меньшей мере неорганизованно. Как выйти из этого положения? Мы просто разделяем их на подкаталоги на диске и на пространства имен в коде. И это именно то, что делают модули Nette. - -Поэтому давайте забудем о единой папке для ведущих и шаблонов и вместо этого создадим модули, например, `Admin` и `Front`. +Подобно организации файлов в папки на жестком диске, в Nette мы можем разделить презентаторы, шаблоны и другие вспомогательные классы на модули. Как это работает на практике? Просто путем включения в структуру новых подкаталогов. Вот пример структуры с двумя модулями - Front и Admin: /--pre -app/ -├── Presenters/ -├── Modules/ ← директория с модулями -│ ├── Admin/ ← модуль Admin -│ │ ├── Presenters/ ← его презентеры -│ │ │ ├── DashboardPresenter.php -│ │ │ └── templates/ -│ └── Front/ ← модуль Front -│ └── Presenters/ ← его презентеры -│ └── ... +app/ +├── Presentation/ +│ ├── Admin/ ← Admin module +│ │ ├── @layout.latte +│ │ ├── Dashboard/ +│ │ │ ├── DashboardPresenter.php +│ │ │ └── default.latte +│ │ └── ... +│ ├── Front/ ← Front module +│ │ ├── @layout.latte +│ │ ├── Home/ +│ │ │ ├── HomePresenter.php +│ │ │ └── default.latte +│ │ └── ... \-- -Эта структура каталогов будет отражена в пространствах имен классов, так, например, `DashboardPresenter` будет находиться в пространстве `App\Modules\Admin\Presenters`: +Эта структура каталогов отражается в пространствах имен классов, так, например, `DashboardPresenter` находится в пространстве имен `App\Presentation\Admin\Dashboard`: ```php -namespace App\Modules\Admin\Presenters; +namespace App\Presentation\Admin\Dashboard; class DashboardPresenter extends Nette\Application\UI\Presenter { @@ -32,35 +34,49 @@ class DashboardPresenter extends Nette\Application\UI\Presenter } ``` -Ведущий `Dashboard` внутри модуля `Admin` обозначается в приложении с помощью двойной точечной нотации как `Admin:Dashboard`, а его действие `default` обозначается как `Admin:Dashboard:default`. -А откуда Nette знает, что `Admin:Dashboard` представляет класс `App\Modules\Admin\Presenters\DashboardPresenter`? Мы говорим об этом, используя [отображение |#Mapping] в конфигурации. -Таким образом, приведенная структура не является фиксированной, и вы можете изменять ее по своему усмотрению. +В приложении мы ссылаемся на ведущего `Dashboard` в модуле `Admin` через двоеточие как `Admin:Dashboard`. Для его действия `default` мы ссылаемся на него как на `Admin:Dashboard:default`. -Модули, конечно, могут содержать все другие части, помимо презентаторов и шаблонов, такие как компоненты, классы моделей и т.д. +Представленная структура не является жесткой; вы можете [полностью настроить ее под свои нужды |#mapping] в конфигурации. .[tip] + +Модули могут включать в себя все остальные файлы, такие как компоненты и вспомогательные классы, в дополнение к ведущим и шаблонам. Если вы раздумываете над тем, где их разместить, рассмотрите возможность использования папки `Accessory`: + +/--pre +app/ +├── Presentation/ +│ ├── Admin/ +│ │ ├── Accessory/ +│ │ │ ├── FormFactory.php +│ │ │ └── AdminLayout.php +│ │ ├── Dashboard/ +│ │ └── ... +\-- Вложенные модули .[#toc-nested-modules] --------------------------------------- -Модули не обязательно должны формировать только плоскую структуру, вы также можете создавать, например, подмодули: +Модули могут иметь несколько уровней вложенности, подобно структуре каталогов на диске: /--pre -app/ -├── Modules/ ← директория с модулями -│ ├── Blog/ ← модуль Blog -│ │ ├── Admin/ ← подмодуль Admin -│ │ │ ├── Presenters/ +app/ +├── Presentation/ +│ ├── Blog/ ← Blog module +│ │ ├── Admin/ ← Admin submodule +│ │ │ ├── Dashboard/ +│ │ │ └── ... +│ │ ├── Front/ ← Front submodule +│ │ │ ├── @layout.latte +│ │ │ ├── Home/ │ │ │ └── ... -│ │ └── Front/ ← подмодуль Front -│ │ ├── Presenters/ -│ │ └── ... -│ ├── Forum/ ← модуль Forum +│ ├── Forum/ ← Forum module │ │ └── ... \-- -Таким образом, модуль `Blog` разбивается на подмодули `Admin` и `Front`. И опять же это будет отражено в пространствах имен, которые будут `App\Modules\Blog\Admin\Presenters` и т.д. Ведущий `Dashboard` внутри подмодуля называется `Blog:Admin:Dashboard`. +Модуль `Blog` делится на подмодули `Admin` и `Front`. Это также отражено в пространствах имен, которые отображаются как `App\Presentation\Blog\Admin` и аналогично. Для обозначения ведущего `Dashboard` в подмодуле `Admin` мы обозначаем его как `Blog:Admin:Dashboard`. -Ветвление может быть настолько глубоким, насколько вы захотите, поэтому вы можете создавать подмодули. +Вложенность может быть настолько глубокой, насколько это необходимо, что позволяет создавать подмодули. + +Например, если в администрировании есть много ведущих, связанных с управлением заказами, таких как `OrderDetail`, `OrderEdit`, `OrderDispatch`, и т. д., можно создать модуль `Order`, в котором будут организованы ведущие `Detail`, `Edit`, `Dispatch`, и другие. Создание ссылок .[#toc-creating-links] @@ -102,46 +118,66 @@ class DashboardPresenter extends Nette\Application\UI\Presenter Составление карты .[#toc-mapping] --------------------------------- -Определяет правила, по которым имя класса выводится из имени ведущего. Мы записываем их в [конфигурацию |configuration] под ключом `application › mapping`. +Mapping определяет правила получения имени класса из имени ведущего. Эти правила задаются в [конфигурации |configuration] под ключом `application › mapping`. + +Структуры каталогов, упомянутые ранее на этой странице, основаны на следующем отображении: + +```neon +application: + mapping: App\Presentation\*\**Presenter +``` -Начнем с примера, в котором не используются модули. Мы просто хотим, чтобы классы ведущего имели пространство имен `App\Presenters`. То есть мы хотим, чтобы ведущий, например, `Home` отображался на класс `App\Presenters\HomePresenter`. Этого можно достичь с помощью следующей конфигурации: +Как работает отображение? Для лучшего понимания давайте сначала представим себе приложение без модулей. Мы хотим, чтобы классы ведущих относились к пространству имен `App\UI`, так что ведущий `Home` отображается на класс `App\Presentation\HomePresenter`. Этого можно добиться с помощью следующей конфигурации: ```neon application: - mapping: App\Presenters\*Presenter + mapping: App\Presentation\*Presenter ``` -Имя презентера заменяется звездочкой, и в результате получается название класса. Легко! +Это сопоставление работает путем замены звездочки в маске `App\Presentation\*Presenter` на имя ведущего `Home`, в результате чего мы получаем конечное имя класса `App\Presentation\HomePresenter`. Просто! + +Однако, как вы можете видеть в примерах этой и других глав, мы размещаем классы ведущих в одноименных подкаталогах, например, ведущий `Home` отображается на класс `App\Presentation\Home\HomePresenter`. Это достигается удвоением звездочки (требуется Nette Application 3.2): + +```neon +application: + mapping: App\Presentation\**Presenter +``` -Если мы разделим докладчиков на модули, то для каждого модуля у нас может быть свой маппинг: +Теперь перейдем к сопоставлению ведущих с модулями. Для каждого модуля мы можем определить конкретное сопоставление: ```neon application: mapping: - Front: App\Modules\Front\Presenters\*Presenter - Admin: App\Modules\Admin\Presenters\*Presenter + Front: App\Presentation\Front\**Presenter + Admin: App\Presentation\Admin\**Presenter Api: App\Api\*Presenter ``` -Теперь презентер `Front:Home` определяется классом `App\Modules\Front\HomePresenter`, а презентер `Admin:Dashboard` — `App\AdminModule\DashboardPresenter`. +Согласно этой конфигурации, ведущий `Front:Home` соотносится с классом `App\Presentation\Front\Home\HomePresenter`, а ведущий `Api:OAuth` - с классом `App\Api\OAuthPresenter`. -Удобнее будет создать общее правило (звездочка), которое заменит первые два правила и добавит дополнительную звездочку только для модуля: +Поскольку модули `Front` и `Admin` имеют схожий подход к отображению и, скорее всего, таких модулей будет больше, можно создать общее правило, которое заменит их. В маску класса добавляется новая звездочка для модуля: ```neon application: mapping: - *: App\Modules\*\Presenters\*Presenter + *: App\Presentation\*\**Presenter Api: App\Api\*Presenter ``` -Но что если мы используем несколько вложенных модулей и у нас есть, например, ведущий `Admin:User:Edit`? В этом случае сегмент со звездочкой, представляющий модуль для каждого уровня, будет просто повторяться, и результатом будет класс `App\Modules\Admin\User\Presenters\EditPresenter`. +Для многоуровневых вложенных модулей, таких как ведущий `Admin:User:Edit`, сегмент звездочки повторяется для каждого уровня, в результате чего получается класс `App\Presentation\Admin\User\Edit\EditPresenter`. Альтернативной нотацией является использование массива, состоящего из трех сегментов, вместо строки. Эта нотация эквивалентна предыдущей: ```neon application: mapping: - *: [App\Modules, *, Presenters\*Presenter] + *: [App\UI, *, **Presenter] + Api: [App\Api, '', *Presenter] ``` -Значение по умолчанию - `*Module\*Presenter`. +Если у нас в конфигурации только одно правило, общее, то можно написать коротко: + +```neon +application: + mapping: App\Presentation\*\**Presenter +``` diff --git a/application/ru/templates.texy b/application/ru/templates.texy index 75f2c784d0..6bd2300402 100644 --- a/application/ru/templates.texy +++ b/application/ru/templates.texy @@ -34,35 +34,81 @@ Nette использует систему шаблонов [Latte |latte:]. Latt Он определяет блок `content`, который вставляется вместо `{include content}` в макете, а также переопределяет блок `title`, который перезаписывает `{block title}` в макете. Попытайтесь представить себе результат. -Поиск шаблонов .[#toc-search-for-templates] -------------------------------------------- +Поиск шаблонов .[#toc-template-lookup] +-------------------------------------- + +В презентаторах вам не нужно указывать, какой шаблон должен быть отображен; фреймворк автоматически определит путь, облегчая вам кодирование. + +Если вы используете структуру каталогов, в которой у каждого ведущего есть своя директория, просто поместите шаблон в эту директорию под именем действия (т. е. представления). Например, для действия `default` используйте шаблон `default.latte`: -Путь к шаблонам определяется ведущим с помощью простой логики. Он попытается проверить, есть ли один из этих файлов, расположенный относительно каталога класса ведущего, где `` это имя текущего ведущего, а `` это имя текущего события: +/--pre +app/ +└── Presentation/ + └── Home/ + ├── HomePresenter.php + └── default.latte +\-- -- `templates//.latte` -- `templates/..latte` +Если вы используете структуру, в которой ведущие находятся в одном каталоге, а шаблоны - в папке `templates`, сохраните их либо в файле `..latte` или `/.latte`: -Если шаблон не найден, он попытается выполнить поиск в каталоге `templates` на один уровень выше, т.е. на том же уровне, что и каталог с классом ведущего. +/--pre +app/ +└── Presenters/ + ├── HomePresenter.php + └── templates/ + ├── Home.default.latte ← 1st variant + └── Home/ + └── default.latte ← 2nd variant +\-- -Если шаблон не найден и там, ответом будет [ошибка 404 |presenters#Error 404 etc.]. +Каталог `templates` можно также разместить на один уровень выше, на том же уровне, что и каталог с классами ведущих. -Вы также можете изменить вид с помощью `$this->setView('jineView')`. Или, вместо прямого поиска, укажите имя файла шаблона с помощью `$this->template->setFile('/path/to/template.latte')`. +Если шаблон не найден, ведущий отвечает [ошибкой 404 - страница не найдена |presenters#Error 404 etc]. + +Изменить вид можно с помощью `$this->setView('anotherView')`. Также можно напрямую указать файл шаблона с помощью `$this->template->setFile('/path/to/template.latte')`. .[note] -Файлы, в которых производится поиск шаблонов, можно изменить, наложив метод [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()], который возвращает массив возможных имен файлов. +Файлы, в которых производится поиск шаблонов, можно изменить, переопределив метод [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()], который возвращает массив возможных имен файлов. + + +Поиск шаблонов макета .[#toc-layout-template-lookup] +---------------------------------------------------- + +Nette также автоматически ищет файл макета. + +Если вы используете структуру каталогов, в которой у каждого ведущего есть своя директория, поместите макет либо в папку с ведущим, если он предназначен только для него, либо на уровень выше, если он общий для нескольких ведущих: + +/--pre +app/ +└── Presentation/ + ├── @layout.latte ← common layout + └── Home/ + ├── @layout.latte ← only for Home presenter + ├── HomePresenter.php + └── default.latte +\-- + +Если вы используете структуру, в которой ведущие сгруппированы в одном каталоге, а шаблоны находятся в папке `templates`, макет будет находиться в следующих местах: -В этих файлах ожидается компоновка: +/--pre +app/ +└── Presenters/ + ├── HomePresenter.php + └── templates/ + ├── @layout.latte ← common layout + ├── Home.@layout.latte ← only for Home, 1st variant + └── Home/ + └── @layout.latte ← only for Home, 2nd variant +\-- -- `templates//@.latte` -- `templates/.@.latte` -- `templates/@.latte` макет, общий для нескольких докладчиков +Если ведущий находится в [модуле |modules], он также будет искать дальше по дереву каталогов в соответствии с вложенностью модуля. -Где `` это имя текущего ведущего и `` это имя макета, которое по умолчанию равно `'layout'`. Имя может быть изменено с помощью `$this->setLayout('jinyLayout')`, поэтому будут опробованы файлы `@jinyLayout.latte`. +Имя макета можно изменить с помощью `$this->setLayout('layoutAdmin')`, и тогда оно будет ожидаться в файле `@layoutAdmin.latte`. Вы также можете напрямую указать файл шаблона макета с помощью `$this->setLayout('/path/to/template.latte')`. -Вы также можете напрямую указать имя файла шаблона макета с помощью `$this->setLayout('/path/to/template.latte')`. Использование `$this->setLayout(false)` отключает отслеживание макета. +Использование тега `$this->setLayout(false)` или `{layout none}` внутри шаблона отключает поиск макета. .[note] -Файлы, в которых производится поиск шаблонов макета, можно изменить, наложив метод [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], который возвращает массив возможных имен файлов. +Файлы, в которых производится поиск шаблонов макетов, можно изменить, переопределив метод [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], который возвращает массив возможных имен файлов. Переменные в шаблоне .[#toc-variables-in-the-template] @@ -104,7 +150,7 @@ class ArticleTemplate extends Nette\Bridges\ApplicationLatte\Template Вы также можете позволить себе роскошь шептать в шаблонах, просто установите плагин Latte в PhpStorm и поместите имя класса в начало шаблона, более подробную информацию смотрите в статье "Latte: как набирать систему":https://blog.nette.org/ru/latte-kak-ispol-zovat-sistemu-tipov: ```latte -{templateType App\Presenters\ArticleTemplate} +{templateType App\Presentation\Article\ArticleTemplate} ... ``` @@ -176,7 +222,7 @@ public function beforeRender(): void Latte версии 3 предлагает более продвинутый способ создания [расширения |latte:creating-extension] для каждого веб-проекта. Вот краткий пример такого класса: ```php -namespace App\Templating; +namespace App\Presentation\Accessory; final class LatteExtension extends Latte\Extension { @@ -214,7 +260,7 @@ final class LatteExtension extends Latte\Extension ```neon latte: extensions: - - App\Templating\LatteExtension + - App\Presentation\Accessory\LatteExtension ``` diff --git a/application/sl/how-it-works.texy b/application/sl/how-it-works.texy index 0149fdc95f..c799e84971 100644 --- a/application/sl/how-it-works.texy +++ b/application/sl/how-it-works.texy @@ -22,13 +22,13 @@ Struktura imenikov je videti nekako takole: /--pre web-project/ ├── app/ ← directory with application -│ ├── Presenters/ ← presenter classes -│ │ ├── HomePresenter.php ← Home presenter class -│ │ └── templates/ ← templates directory -│ │ ├── @layout.latte ← template of shared layout -│ │ └── Home/ ← templates for Home presenter -│ │ └── default.latte ← template for action `default` -│ ├── Router/ ← configuration of URL addresses +│ ├── Core/ ← osnovni potrebni razredi +│ │ └── RouterFactory.php ← konfiguracija naslovov URL +│ ├── Presentation/ ← predstavitev, predloge in podobno. +│ │ ├── @layout.latte ← predloga skupne postavitve +│ │ └── Home/ ← Domači imenik predstavnikov +│ │ ├── HomePresenter.php ← Razred HomePresenter +│ │ └── default.latte ← predloga za akcijo default │ └── Bootstrap.php ← booting class Bootstrap ├── bin/ ← scripts for the command line ├── config/ ← configuration files @@ -91,7 +91,7 @@ Aplikacije, napisane v okolju Nette, so razdeljene na številne tako imenovane p Aplikacija se začne tako, da zahteva od tako imenovanega usmerjevalnika, da se odloči, kateremu od predstavnikov bo posredoval trenutno zahtevo v obdelavo. Usmerjevalnik se odloči, čigava je to odgovornost. Pregleda vhodni naslov URL `https://example.com/product/123`, ki želi `show` izdelek z `id: 123` kot dejanjem. Dobra navada je, da se pari predstavnik + akcija, ločeni z dvopičjem, zapišejo kot `Product:show`. -Usmerjevalnik je torej pretvoril naslov URL v par `Presenter:action` + parametri, v našem primeru `Product:show` + `id: 123`. Kako je videti usmerjevalnik, si lahko ogledate v datoteki `app/Router/RouterFactory.php`, podrobno pa ga bomo opisali v poglavju [Usmerjanje |Routing]. +Usmerjevalnik je torej pretvoril naslov URL v par `Presenter:action` + parametri, v našem primeru `Product:show` + `id: 123`. Kako je videti usmerjevalnik, si lahko ogledate v datoteki `app/Core/RouterFactory.php`, podrobno pa ga bomo opisali v poglavju [Usmerjanje |Routing]. Pojdimo naprej. Aplikacija že pozna ime predavatelja in lahko nadaljuje. Z ustvarjanjem predmeta `ProductPresenter`, ki je koda predstavnika `Product`. Natančneje, za ustvarjanje predstavnika zaprosi vsebnik DI, saj je izdelovanje objektov njegova naloga. @@ -121,12 +121,9 @@ Tako je bila klicana metoda `renderShow(123)`, katere koda je izmišljen primer, Nato predstavnik vrne odgovor. To je lahko stran HTML, slika, dokument XML, pošiljanje datoteke z diska, JSON ali preusmeritev na drugo stran. Pomembno je, da če izrecno ne navedemo, kako odgovoriti (kar je primer `ProductPresenter`), bo odgovor prikaz predloge s stranjo HTML. Zakaj? No, ker v 99 % primerov želimo izrisati predlogo, zato predstavnik to vedenje sprejme kot privzeto in nam želi olajšati delo. To je Nettejeva poanta. -Ni nam treba niti navesti, katero predlogo želimo narisati, on pot do nje izpelje po preprosti logiki. V primeru predstavnika `Product` in akcije `show`, poskuša preveriti, ali obstaja ena od teh datotek s predlogami glede na imenik, v katerem se nahaja razred `ProductPresenter`: +Sploh nam ni treba navesti, katero predlogo je treba prikazati; ogrodje bo pot določilo samo. V primeru akcije `show` preprosto poskuša naložiti predlogo `show.latte` v imeniku z razredom `ProductPresenter`. Prav tako poskuša najti postavitev v datoteki `@layout.latte` (več o [iskanju predlog |templates#Template Lookup]). -- `templates/Product/show.latte` -- `templates/Product.show.latte` - -Prav tako poskuša poiskati postavitev v datoteki `@layout.latte` in nato upodobi predlogo. Zdaj je naloga predstavnika in celotne aplikacije končana. Če predloga ne obstaja, se vrne stran z napako 404. Več o predstavitvah si lahko preberete na strani [Predstavitve |Presenters]. +Nato se predloge izrišejo. S tem je naloga predstavnika in celotne aplikacije končana in delo je opravljeno. Če predloga ne bi obstajala, bi se vrnila stran z napako 404. Več o predstavnikih si lahko preberete na strani [Predstavniki |presenters]. [* request-flow.svg *] @@ -137,7 +134,7 @@ Da bi se prepričali, poskusite celoten postopek ponoviti z nekoliko drugačnim 3) usmerjevalnik dekodira naslov URL kot par `Home:default` 4) ustvari se objekt `HomePresenter` 5) kličemo metodo `renderDefault()` (če obstaja) -6) prikaže se predloga `templates/Home/default.latte` z razporeditvijo `templates/@layout.latte` +6) prikaže se predloga `default.latte` z razporeditvijo `@layout.latte` Morda ste zdaj naleteli na veliko novih konceptov, vendar verjamemo, da so smiselni. Ustvarjanje aplikacij v programu Nette je zelo enostavno. diff --git a/application/sl/modules.texy b/application/sl/modules.texy index c0c01ae28d..77eed68689 100644 --- a/application/sl/modules.texy +++ b/application/sl/modules.texy @@ -2,29 +2,31 @@ Moduli ****** .[perex] -V Nette moduli predstavljajo logične enote, ki sestavljajo aplikacijo. Vključujejo predstavnike, predloge, lahko tudi komponente in razrede modelov. +Moduli vnašajo jasnost v aplikacije Nette, saj omogočajo enostavno razdelitev na logične enote. -En imenik za predstavnike in en imenik za predloge za prave projekte ne bi bil dovolj. Če je v eni mapi na desetine datotek, je to vsaj neorganizirano. Kako to odpraviti? Preprosto jih razdelimo v podimenike na disku in v imenske prostore v kodi. In točno to naredijo moduli Nette. - -Pozabimo torej na eno mapo za predstavnike in predloge in namesto tega ustvarimo module, na primer `Admin` in `Front`. +Podobno kot pri urejanju datotek v mape na trdem disku, lahko v Nette predstavnike, predloge in druge pomožne razrede razdelimo v module. Kako to deluje v praksi? Preprosto z vključevanjem novih podimenikov v strukturo. Tukaj je primer strukture z dvema moduloma, Front in Admin: /--pre -app/ -├── Presenters/ -├── Modules/ ← directory with modules -│ ├── Admin/ ← module Admin -│ │ ├── Presenters/ ← its presenters -│ │ │ ├── DashboardPresenter.php -│ │ │ └── templates/ -│ └── Front/ ← module Front -│ └── Presenters/ ← its presenters -│ └── ... +app/ +├── Presentation/ +│ ├── Admin/ ← Admin module +│ │ ├── @layout.latte +│ │ ├── Dashboard/ +│ │ │ ├── DashboardPresenter.php +│ │ │ └── default.latte +│ │ └── ... +│ ├── Front/ ← Front module +│ │ ├── @layout.latte +│ │ ├── Home/ +│ │ │ ├── HomePresenter.php +│ │ │ └── default.latte +│ │ └── ... \-- -Ta struktura imenikov se bo odražala v imenskih prostorih razredov, tako da bo na primer `DashboardPresenter` v imenskem prostoru `App\Modules\Admin\Presenters`: +Ta imeniška struktura se odraža v imenskih prostorih razredov, tako da se na primer `DashboardPresenter` nahaja v imenskem prostoru `App\Presentation\Admin\Dashboard`: ```php -namespace App\Modules\Admin\Presenters; +namespace App\Presentation\Admin\Dashboard; class DashboardPresenter extends Nette\Application\UI\Presenter { @@ -32,35 +34,49 @@ class DashboardPresenter extends Nette\Application\UI\Presenter } ``` -Na predvajalnik `Dashboard` znotraj modula `Admin` se v aplikaciji sklicujemo z uporabo zapisa v dvopičju kot na `Admin:Dashboard`, na njegovo akcijo `default` pa kot na `Admin:Dashboard:default`. -In kako Nette pravilno ve, da `Admin:Dashboard` predstavlja razred `App\Modules\Admin\Presenters\DashboardPresenter`? To je določeno s [preslikavo |#mapping] v konfiguraciji. -Podana struktura torej ni trdno določena in jo lahko spreminjate glede na svoje potrebe. +V aplikaciji se na predstavnik `Dashboard` znotraj modula `Admin` sklicujemo z uporabo zapisa v dvopičju kot `Admin:Dashboard`. Za njegovo akcijo `default` se sklicujemo na `Admin:Dashboard:default`. -Moduli seveda lahko poleg predstavnikov in predlog vsebujejo tudi vse druge elemente, kot so komponente, razredi modelov itd. +Predstavljena struktura ni toga; v konfiguraciji [jo |#mapping] lahko v [celoti prilagodite svojim potrebam |#mapping]. .[tip] + +Moduli lahko poleg predstavnikov in predlog vključujejo tudi vse druge datoteke, kot so komponente in pomožni razredi. Če razmišljate, kam jih umestiti, razmislite o uporabi mape `Accessory`: + +/--pre +app/ +├── Presentation/ +│ ├── Admin/ +│ │ ├── Accessory/ +│ │ │ ├── FormFactory.php +│ │ │ └── AdminLayout.php +│ │ ├── Dashboard/ +│ │ └── ... +\-- Vgnezdeni moduli .[#toc-nested-modules] --------------------------------------- -Ni nujno, da moduli tvorijo le ravno strukturo, ustvarite lahko tudi podmodule, na primer: +Moduli so lahko vgrajeni na več ravneh, podobno kot struktura imenikov na disku: /--pre -app/ -├── Modules/ ← directory with modules -│ ├── Blog/ ← module Blog -│ │ ├── Admin/ ← submodule Admin -│ │ │ ├── Presenters/ +app/ +├── Presentation/ +│ ├── Blog/ ← Blog module +│ │ ├── Admin/ ← Admin submodule +│ │ │ ├── Dashboard/ +│ │ │ └── ... +│ │ ├── Front/ ← Front submodule +│ │ │ ├── @layout.latte +│ │ │ ├── Home/ │ │ │ └── ... -│ │ └── Front/ ← submodule Front -│ │ ├── Presenters/ -│ │ └── ... -│ ├── Forum/ ← module Forum +│ ├── Forum/ ← Forum module │ │ └── ... \-- -Tako je modul `Blog` razdeljen na podmodula `Admin` in `Front`. Tudi to se bo odražalo v imenskih prostorih, ki bodo `App\Modules\Blog\Admin\Presenters` itd. Predstavnik `Dashboard` znotraj podmodula se imenuje `Blog:Admin:Dashboard`. +Modul `Blog` je razdeljen na podmodula `Admin` in `Front`. To se odraža tudi v imenskih prostorih, ki so nato prikazani kot `App\Presentation\Blog\Admin` in podobno. Če se želimo sklicevati na predstavnik `Dashboard` znotraj podmodula `Admin`, ga imenujemo `Blog:Admin:Dashboard`. -Gnezdenje je lahko tako globoko, kot želite, zato lahko ustvarite podmodule. +Gnezdenje je lahko tako globoko, kot je potrebno, kar omogoča ustvarjanje podmodulov. + +Če imate na primer v administraciji veliko predstavnikov, povezanih z upravljanjem naročil, kot so `OrderDetail`, `OrderEdit`, `OrderDispatch` itd., lahko ustvarite modul `Order`, v katerem bodo organizirani predstavniki, kot so `Detail`, `Edit`, `Dispatch` in drugi. Ustvarjanje povezav .[#toc-creating-links] @@ -102,46 +118,66 @@ Glejte [poglavje o usmerjanju |routing#Modules]. Kartiranje .[#toc-mapping] -------------------------- -Določa pravila, po katerih se ime razreda izpelje iz imena predstavnika. Zapišemo jih v [konfiguracijo |configuration] pod ključ `application › mapping`. +Mapiranje določa pravila za izpeljavo imena razreda iz imena predstavnika. Ta pravila so določena v [konfiguraciji |configuration] pod ključem `application › mapping`. + +Strukture imenikov, omenjene prej na tej strani, temeljijo na naslednjem preslikavanju: + +```neon +application: + mapping: App\Presentation\*\**Presenter +``` -Začnimo z vzorcem, ki ne uporablja modulov. Želeli bomo le, da imajo razredi predstavnikov imenski prostor `App\Presenters`. To pomeni, da mora biti predstavnik, kot je `Home`, preslikan v razred `App\Presenters\HomePresenter`. To lahko dosežemo z naslednjo konfiguracijo: +Kako deluje kartiranje? Za boljše razumevanje si najprej predstavljajmo aplikacijo brez modulov. Želimo, da razredi predstavnikov spadajo v imenski prostor `App\UI`, tako da se predstavnik `Home` preslika v razred `App\Presentation\HomePresenter`. To lahko dosežemo s to konfiguracijo: ```neon application: - mapping: App\Presenters\*Presenter + mapping: App\Presentation\*Presenter ``` -V maski razreda se ime predvajalnika nadomesti z zvezdico, rezultat pa je ime razreda. Enostavno! +Ta preslikava deluje tako, da zvezdico v maski `App\Presentation\*Presenter` nadomestimo z imenom predstavnika `Home`, s čimer dobimo končno ime razreda `App\Presentation\HomePresenter`. Preprosto! + +Vendar, kot lahko vidite v primerih v tem in drugih poglavjih, umeščamo predstavitvene razrede v istoimenske podimenike, npr. predstavitveni razred `Home` je preslikan v razred `App\Presentation\Home\HomePresenter`. To dosežemo s podvojitvijo zvezdice (zahteva program Nette Application 3.2): + +```neon +application: + mapping: App\Presentation\**Presenter +``` -Če voditelje razdelimo na module, lahko za vsak modul pripravimo lastno preslikavo: +Sedaj se lotimo preslikave predstavnikov v module. Za vsak modul lahko opredelimo posebna preslikavanja: ```neon application: mapping: - Front: App\Modules\Front\Presenters\*Presenter - Admin: App\Modules\Admin\Presenters\*Presenter + Front: App\Presentation\Front\**Presenter + Admin: App\Presentation\Admin\**Presenter Api: App\Api\*Presenter ``` -Sedaj je predstavnik `Front:Home` preslikan v razred `App\Modules\Front\Presenters\HomePresenter`, predstavnik `Admin:Dashboard` pa v razred `App\Modules\Admin\Presenters\DashboardPresenter`. +V skladu s to konfiguracijo se predstavnik `Front:Home` prikaže v razred `App\Presentation\Front\Home\HomePresenter`, predstavnik `Api:OAuth` pa v razred `App\Api\OAuthPresenter`. -Bolj praktično je ustvariti splošno (zvezdno) pravilo, ki bo nadomestilo prvi dve. Dodatna zvezdica bo dodana maski razreda samo za ta modul: +Ker imata modula `Front` in `Admin` podoben pristop k preslikavi in ker bo takih modulov verjetno več, je mogoče ustvariti splošno pravilo, ki ju nadomesti. V masko razreda se doda nova zvezdica za modul: ```neon application: mapping: - *: App\Modules\*\Presenters\*Presenter + *: App\Presentation\*\**Presenter Api: App\Api\*Presenter ``` -Kaj pa, če uporabljamo vgnezdene module in imamo predvajalnik `Admin:User:Edit`? V tem primeru se segment z zvezdico, ki predstavlja modul za vsako raven, preprosto ponovi in rezultat je razred `App\Modules\Admin\User\Presenters\EditPresenter`. +Za večnivojske vgnezdene module, kot je predstavnik `Admin:User:Edit`, se segment z zvezdico ponovi za vsako raven, tako da nastane razred `App\Presentation\Admin\User\Edit\EditPresenter`. Alternativni zapis je, da namesto niza uporabimo polje, sestavljeno iz treh segmentov. Ta zapis je enakovreden prejšnjemu: ```neon application: mapping: - *: [App\Modules, *, Presenters\*Presenter] + *: [App\UI, *, **Presenter] + Api: [App\Api, '', *Presenter] ``` -Privzeta vrednost je `*Module\*Presenter`. +Če imamo v konfiguraciji samo eno pravilo, splošno, lahko zapišemo na kratko: + +```neon +application: + mapping: App\Presentation\*\**Presenter +``` diff --git a/application/sl/templates.texy b/application/sl/templates.texy index 66005783a9..7f90130d97 100644 --- a/application/sl/templates.texy +++ b/application/sl/templates.texy @@ -34,35 +34,81 @@ To pa je lahko predloga za dejanja: V njej je opredeljen blok `content`, ki se v postavitev vstavi namesto bloka `{include content}`, prav tako pa je na novo opredeljen blok `title`, ki v postavitvi prepiše blok `{block title}`. Poskusite si predstavljati rezultat. -Iskanje predlog .[#toc-search-for-templates] --------------------------------------------- +Iskanje predloge .[#toc-template-lookup] +---------------------------------------- -Pot do predlog se določi po preprosti logiki. Poskusi preveriti, ali obstaja ena od teh datotek s predlogami glede na imenik, v katerem se nahaja razred presenter, kjer `` je ime trenutnega predstavnika in `` je ime trenutnega dejanja: +V predstavitvenih programih vam ni treba določiti, katera predloga naj se prikaže; ogrodje samodejno določi pot, kar vam olajša kodiranje. -- `templates//.latte` -- `templates/..latte` +Če uporabljate imeniško strukturo, v kateri ima vsak predstavnik svoj imenik, preprosto postavite predlogo v ta imenik pod ime dejanja (npr. pogleda). Na primer, za dejanje `default` uporabite predlogo `default.latte`: -Če predloge ne najde, jo poskuša poiskati v imeniku `templates` eno raven višje, tj. na isti ravni kot imenik z razredom predstavnika. +/--pre +app/ +└── Presentation/ + └── Home/ + ├── HomePresenter.php + └── default.latte +\-- -Če predloge ne najde niti tam, se kot odgovor prikaže [napaka 404 |presenters#Error 404 etc.]. +Če uporabljate strukturo, v kateri so predstavniki skupaj v enem imeniku, predloge pa v mapi `templates`, jo shranite bodisi v datoteko `..latte` ali . `/.latte`: -Pogled lahko spremenite tudi z uporabo `$this->setView('otherView')`. Lahko pa namesto iskanja neposredno določite ime datoteke s predlogo z uporabo `$this->template->setFile('/path/to/template.latte')`. +/--pre +app/ +└── Presenters/ + ├── HomePresenter.php + └── templates/ + ├── Home.default.latte ← 1st variant + └── Home/ + └── default.latte ← 2nd variant +\-- + +Imenik `templates` lahko postavite tudi eno raven višje, na isto raven kot imenik z razredi predavateljev. + +Če predloge ni mogoče najti, se predstavitveni program odzove z [napako 404 - stran ni najdena |presenters#Error 404 etc]. + +Prikaz lahko spremenite z uporabo spletne strani `$this->setView('anotherView')`. Datoteko s predlogo lahko določite tudi neposredno z uporabo `$this->template->setFile('/path/to/template.latte')`. .[note] -Poti, po katerih se iščejo predloge, lahko spremenite tako, da nadgradite metodo [formatTemplateFiles |api:Nette\Application\UI\Presenter::formatTemplateFiles()], ki vrne polje možnih poti do datotek. +Datoteke, v katerih se iščejo predloge, lahko spremenite tako, da nadgradite metodo [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()], ki vrne polje možnih imen datotek. + + +Iskanje predlog za postavitev .[#toc-layout-template-lookup] +------------------------------------------------------------ + +Nette samodejno poišče tudi datoteko z maketo. + +Če uporabljate imeniško strukturo, v kateri ima vsak predavatelj svoj imenik, postavite postavitev bodisi v mapo s predavateljem, če je namenjena samo njemu, bodisi za stopnjo višje, če je skupna več predavateljem: + +/--pre +app/ +└── Presentation/ + ├── @layout.latte ← common layout + └── Home/ + ├── @layout.latte ← only for Home presenter + ├── HomePresenter.php + └── default.latte +\-- + +Če uporabljate strukturo, v kateri so predstavniki združeni v enem imeniku, predloge pa so v mapi `templates`, bo postavitev pričakovana na naslednjih mestih: -Postavitev se pričakuje v naslednjih datotekah: +/--pre +app/ +└── Presenters/ + ├── HomePresenter.php + └── templates/ + ├── @layout.latte ← common layout + ├── Home.@layout.latte ← only for Home, 1st variant + └── Home/ + └── @layout.latte ← only for Home, 2nd variant +\-- -- `templates//@.latte` -- `templates/.@.latte` -- `templates/@.latte` postavitev, ki je skupna več predstavnikom +Če je predstavnik v [modulu |modules], se bo poiskal tudi naprej po drevesu imenika v skladu z gnezdenjem modula. -`` je ime trenutnega predavatelja in `` je ime postavitve, ki je privzeto `'layout'`. Ime lahko spremenite s `$this->setLayout('otherLayout')`, tako da se bodo poskušale uporabiti datoteke `@otherLayout.latte`. +Ime postavitve lahko spremenite z uporabo spletne strani `$this->setLayout('layoutAdmin')`, nato pa jo boste pričakali v datoteki `@layoutAdmin.latte`. Datoteko s predlogo postavitve lahko določite tudi neposredno z uporabo `$this->setLayout('/path/to/template.latte')`. -Ime datoteke za predlogo postavitve lahko določite tudi neposredno z uporabo `$this->setLayout('/path/to/template.latte')`. Z uporabo spletne strani `$this->setLayout(false)` bo iskanje postavitve onemogočeno. +Uporaba `$this->setLayout(false)` ali oznake `{layout none}` znotraj predloge onemogoči iskanje postavitve. .[note] -Poti, po katerih se iščejo predloge, lahko spremenite tako, da nadgradite metodo [formatLayoutTemplateFiles |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], ki vrne polje možnih poti do datotek. +Datoteke, v katerih se iščejo predloge postavitve, lahko spremenite tako, da nadgradite metodo [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], ki vrne polje možnih imen datotek. Spremenljivke v predlogi .[#toc-variables-in-the-template] @@ -104,7 +150,7 @@ Opomba `@property-read` je namenjena IDE in statični analizi, zaradi nje bo del Privoščite si lahko tudi razkošje šepetanja v predlogah, samo namestite vtičnik Latte v PhpStorm in na začetku predloge navedite ime razreda, glejte članek "Latte: kako vtipkati sistem":https://blog.nette.org/sl/latte-kako-uporabljati-sistem-tipov: ```latte -{templateType App\Presenters\ArticleTemplate} +{templateType App\Presentation\Article\ArticleTemplate} ... ``` @@ -176,7 +222,7 @@ public function beforeRender(): void Različica Latte 3 ponuja naprednejši način z ustvarjanjem [razširitve |latte:creating-extension] za vsak spletni projekt. Tukaj je približni primer takega razreda: ```php -namespace App\Templating; +namespace App\Presentation\Accessory; final class LatteExtension extends Latte\Extension { @@ -214,7 +260,7 @@ Registriramo ga z uporabo [konfiguracije|configuration#Latte]: ```neon latte: extensions: - - App\Templating\LatteExtension + - App\Presentation\Accessory\LatteExtension ``` diff --git a/application/tr/how-it-works.texy b/application/tr/how-it-works.texy index 78f72c450c..6e82000d67 100644 --- a/application/tr/how-it-works.texy +++ b/application/tr/how-it-works.texy @@ -22,13 +22,13 @@ Dizin yapısı şuna benzer: /--pre web-project/ ├── app/ ← directory with application -│ ├── Presenters/ ← presenter classes -│ │ ├── HomePresenter.php ← Home presenter class -│ │ └── templates/ ← templates directory -│ │ ├── @layout.latte ← template of shared layout -│ │ └── Home/ ← templates for Home presenter -│ │ └── default.latte ← template for action `default` -│ ├── Router/ ← configuration of URL addresses +│ ├── Core/ ← temel gerekli sınıflar +│ │ └── RouterFactory.php ← URL adreslerinin yapılandırılması +│ ├── Presentation/ ← presenters, templates & co. +│ │ ├── @layout.latte ← paylaşılan düzen şablonu +│ │ └── Home/ ← Ana Sayfa sunucu dizini +│ │ ├── HomePresenter.php ← Ev sunucusu sınıfı +│ │ └── default.latte ← eylem için şablon default │ └── Bootstrap.php ← booting class Bootstrap ├── bin/ ← scripts for the command line ├── config/ ← configuration files @@ -91,7 +91,7 @@ Nette'de yazılan uygulamalar, belirli bir web sitesi sayfasını temsil eden s Uygulama, yönlendirici olarak adlandırılan kişiden mevcut talebin işlenmek üzere hangi sunuculara iletileceğine karar vermesini isteyerek başlar. Yönlendirici bunun kimin sorumluluğunda olduğuna karar verir. `https://example.com/product/123` ile bir ürünü `id: 123` eylem olarak isteyen **sunucu** `Product` için bir iş olduğuna karar verir. Sunucu + eylem çiftlerini iki nokta üst üste ile ayırarak `Product:show` şeklinde yazmak iyi bir alışkanlıktır. -Böylece yönlendirici URL'yi bir `Presenter:action` + parametreler çiftine dönüştürdü, bizim durumumuzda `Product:show` + `id: 123`. Bir yönlendiricinin nasıl göründüğünü `app/Router/RouterFactory.php` dosyasında görebilirsiniz ve bunu [Yönlendirme |Routing] bölümünde ayrıntılı olarak açıklayacağız. +Böylece yönlendirici URL'yi bir `Presenter:action` + parametreler çiftine dönüştürdü, bizim durumumuzda `Product:show` + `id: 123`. Bir yönlendiricinin nasıl göründüğünü `app/Core/RouterFactory.php` dosyasında görebilirsiniz ve bunu [Yönlendirme |Routing] bölümünde ayrıntılı olarak açıklayacağız. Devam edelim. Uygulama zaten sunucunun adını biliyor ve devam edebilir. Sunum yapan kişinin kodu olan `ProductPresenter` nesnesini oluşturarak `Product`. Daha doğrusu, DI konteynerinden sunucuyu yaratmasını ister, çünkü nesneleri üretmek onun işidir. @@ -121,12 +121,9 @@ Böylece, kodu kurgusal bir örnek olan `renderShow(123)` yöntemi çağrıldı, Daha sonra, sunum yapan kişi yanıtı döndürür. Bu bir HTML sayfası, bir resim, bir XML belgesi, diskten bir dosya gönderme, JSON veya başka bir sayfaya yönlendirme olabilir. Daha da önemlisi, nasıl yanıt verileceğini açıkça belirtmezsek ( `ProductPresenter` adresinde olduğu gibi), yanıt şablonu bir HTML sayfası ile işlemek olacaktır. Neden mi? Çünkü vakaların %99'unda bir şablon çizmek isteriz, dolayısıyla sunum yapan kişi bu davranışı varsayılan olarak kabul eder ve işimizi kolaylaştırmak ister. Nette'in amacı da bu. -Hangi şablonun çizileceğini belirtmemize bile gerek yok, basit bir mantıkla o şablona giden yolu türetiyor. Sunucu `Product` ve eylem `show` durumunda, bu şablon dosyalarından birinin `ProductPresenter` sınıfının bulunduğu dizine göre var olup olmadığını görmeye çalışır: +Hangi şablonun işleneceğini belirtmemize bile gerek yoktur; framework yolu kendisi çıkaracaktır. `show` eylemi söz konusu olduğunda, basitçe `ProductPresenter` sınıfının bulunduğu dizindeki `show.latte` şablonunu yüklemeye çalışır. Ayrıca `@layout.latte` dosyasındaki düzeni bulmaya çalışır ( [şablon arama |templates#Template Lookup] hakkında daha fazla bilgi). -- `templates/Product/show.latte` -- `templates/Product.show.latte` - -Ayrıca `@layout.latte` dosyasında düzeni bulmaya çalışacak ve ardından şablonu oluşturacaktır. Artık sunucunun ve tüm uygulamanın görevi tamamlanmıştır. Şablon mevcut değilse, 404 hatalı bir sayfa döndürülecektir. Sunumcular hakkında daha fazla bilgiyi [Sunumcular |Presenters] sayfasında bulabilirsiniz. +Daha sonra şablonlar işlenir. Bu, sunucunun ve tüm uygulamanın görevini tamamlar ve iş biter. Eğer şablon mevcut değilse, 404 hata sayfası döndürülür. Sunucular hakkında daha fazla bilgi için [Sunucular |presenters] sayfasına bakabilirsiniz. [* request-flow.svg *] @@ -137,7 +134,7 @@ Sadece emin olmak için, tüm süreci biraz farklı bir URL ile özetlemeye çal 3) yönlendirici URL'yi bir çift olarak çözer `Home:default` 4) bir `HomePresenter` nesnesi oluşturulur 5) `renderDefault()` yöntemi çağrılır (eğer varsa) -6) `templates/@layout.latte` düzenine sahip bir `templates/Home/default.latte` şablonu oluşturulur +6) `@layout.latte` düzenine sahip bir `default.latte` şablonu oluşturulur Şu anda birçok yeni kavramla karşılaşmış olabilirsiniz, ancak bunların anlamlı olduğuna inanıyoruz. Nette'de uygulama oluşturmak çocuk oyuncağı. diff --git a/application/tr/modules.texy b/application/tr/modules.texy index 63da6e9e48..5161095c1e 100644 --- a/application/tr/modules.texy +++ b/application/tr/modules.texy @@ -2,29 +2,31 @@ Modüller ******** .[perex] -Nette'de modüller bir uygulamayı oluşturan mantıksal birimleri temsil eder. Sunucuları, şablonları, muhtemelen bileşenleri ve model sınıflarını içerirler. +Modüller, mantıksal birimlere kolayca bölünmeyi kolaylaştırarak Nette uygulamalarına netlik kazandırır. -Sunucular için bir dizin ve şablonlar için bir dizin gerçek projeler için yeterli olmayacaktır. Bir klasörde düzinelerce dosya olması en azından düzensizdir. Bundan nasıl kurtulabiliriz? Basitçe onları diskteki alt dizinlere ve koddaki ad alanlarına böleriz. Nette modüllerinin yaptığı da tam olarak budur. - -Sunucular ve şablonlar için tek bir klasör oluşturmayı unutalım ve bunun yerine örneğin `Admin` ve `Front` gibi modüller oluşturalım. +Dosyaları sabit diskte klasörler halinde düzenlemeye benzer şekilde, Nette'de sunum yapan kişileri, şablonları ve diğer yardımcı sınıfları modüllere bölebiliriz. Bu pratikte nasıl çalışır? Basitçe yapıya yeni alt dizinler ekleyerek. İşte Front ve Admin olmak üzere iki modüllü bir yapı örneği: /--pre -app/ -├── Presenters/ -├── Modules/ ← directory with modules -│ ├── Admin/ ← module Admin -│ │ ├── Presenters/ ← its presenters -│ │ │ ├── DashboardPresenter.php -│ │ │ └── templates/ -│ └── Front/ ← module Front -│ └── Presenters/ ← its presenters -│ └── ... +app/ +├── Presentation/ +│ ├── Admin/ ← Admin module +│ │ ├── @layout.latte +│ │ ├── Dashboard/ +│ │ │ ├── DashboardPresenter.php +│ │ │ └── default.latte +│ │ └── ... +│ ├── Front/ ← Front module +│ │ ├── @layout.latte +│ │ ├── Home/ +│ │ │ ├── HomePresenter.php +│ │ │ └── default.latte +│ │ └── ... \-- -Bu dizin yapısı sınıf ad alanları tarafından yansıtılacaktır, bu nedenle örneğin `DashboardPresenter` `App\Modules\Admin\Presenters` ad alanında olacaktır: +Bu dizin yapısı sınıfların isim alanlarına da yansıtılır; örneğin `DashboardPresenter`, `App\Presentation\Admin\Dashboard` isim alanında yer alır: ```php -namespace App\Modules\Admin\Presenters; +namespace App\Presentation\Admin\Dashboard; class DashboardPresenter extends Nette\Application\UI\Presenter { @@ -32,35 +34,49 @@ class DashboardPresenter extends Nette\Application\UI\Presenter } ``` -`Admin` modülü içindeki `Dashboard` sunumcusuna uygulama içinde iki nokta üst üste gösterimi kullanılarak `Admin:Dashboard` şeklinde ve `default` eylemine `Admin:Dashboard:default` şeklinde referans verilir. -Peki Nette proper `Admin:Dashboard` 'un `App\Modules\Admin\Presenters\DashboardPresenter` sınıfını temsil ettiğini nasıl biliyor? Bu, yapılandırmadaki [eşleme |#mapping] ile belirlenir. -Bu nedenle, verilen yapı sabit değildir ve ihtiyaçlarınıza göre değiştirebilirsiniz. +Uygulamada, `Admin` modülü içindeki `Dashboard` sunumcusuna iki nokta üst üste gösterimini kullanarak `Admin:Dashboard` olarak atıfta bulunuyoruz. `default` eylemi için `Admin:Dashboard:default` olarak adlandırıyoruz. -Modüller elbette sunum yapanların ve şablonların yanı sıra bileşenler, model sınıfları vb. gibi diğer tüm öğeleri de içerebilir. +Sunulan yapı katı değildir; yapılandırmada [ihtiyaçlarınıza göre tamamen özelleştirebilirsiniz |#mapping]. .[tip] + +Modüller, sunucular ve şablonların yanı sıra bileşenler ve yardımcı sınıflar gibi diğer tüm dosyaları da içerebilir. Bunları nereye yerleştireceğinizi düşünüyorsanız, bir `Accessory` klasörü kullanmayı düşünün: + +/--pre +app/ +├── Presentation/ +│ ├── Admin/ +│ │ ├── Accessory/ +│ │ │ ├── FormFactory.php +│ │ │ └── AdminLayout.php +│ │ ├── Dashboard/ +│ │ └── ... +\-- İç İçe Modüller .[#toc-nested-modules] -------------------------------------- -Modüller sadece düz bir yapı oluşturmak zorunda değildir, örneğin alt modüller de oluşturabilirsiniz: +Modüller, diskteki bir dizin yapısına benzer şekilde birden fazla iç içe geçme seviyesine sahip olabilir: /--pre -app/ -├── Modules/ ← directory with modules -│ ├── Blog/ ← module Blog -│ │ ├── Admin/ ← submodule Admin -│ │ │ ├── Presenters/ +app/ +├── Presentation/ +│ ├── Blog/ ← Blog module +│ │ ├── Admin/ ← Admin submodule +│ │ │ ├── Dashboard/ +│ │ │ └── ... +│ │ ├── Front/ ← Front submodule +│ │ │ ├── @layout.latte +│ │ │ ├── Home/ │ │ │ └── ... -│ │ └── Front/ ← submodule Front -│ │ ├── Presenters/ -│ │ └── ... -│ ├── Forum/ ← module Forum +│ ├── Forum/ ← Forum module │ │ └── ... \-- -Böylece, `Blog` modülü `Admin` ve `Front` alt modüllerine bölünmüştür. Yine, bu durum `App\Modules\Blog\Admin\Presenters` vb. isim alanlarına da yansıyacaktır. Alt modülün içindeki `Dashboard` sunucusu `Blog:Admin:Dashboard` olarak adlandırılır. + `Blog` modülü `Admin` ve `Front` alt modüllerine ayrılmıştır. Bu aynı zamanda `App\Presentation\Blog\Admin` ve benzer şekilde görünen isim alanlarına da yansıtılır. `Admin` alt modülü içindeki `Dashboard` sunucusuna atıfta bulunmak için, bunu `Blog:Admin:Dashboard` olarak adlandırıyoruz. -İç içe geçme istediğiniz kadar derin olabilir, böylece alt alt modüller oluşturulabilir. +Yerleştirme, alt alt modüllerin oluşturulmasına izin vererek gerektiği kadar derin olabilir. + +Örneğin, yönetimde `OrderDetail`, `OrderEdit`, `OrderDispatch`, vb. gibi sipariş yönetimiyle ilgili birçok sunucunuz varsa, `Detail`, `Edit`, `Dispatch` ve diğerleri gibi sunucuların düzenleneceği bir `Order` modülü oluşturabilirsiniz. Bağlantı Oluşturma .[#toc-creating-links] @@ -102,46 +118,66 @@ Yönlendirme .[#toc-routing] Haritalama .[#toc-mapping] -------------------------- -Sınıf adının sunum yapan kişinin adından türetildiği kuralları tanımlar. Bunları [yapılandırmada |configuration] `application › mapping` anahtarının altına yazıyoruz. +Eşleme, sınıf adının sunum yapan kişinin adından türetilmesine ilişkin kuralları tanımlar. Bu kurallar [yapılandırmada |configuration] `application › mapping` anahtarı altında belirtilir. + +Bu sayfada daha önce bahsedilen dizin yapıları aşağıdaki eşleştirmeye dayanmaktadır: + +```neon +application: + mapping: App\Presentation\*\**Presenter +``` -Modül kullanmayan bir örnekle başlayalım. Sadece sunum yapan sınıfların `App\Presenters` ad alanına sahip olmasını isteyeceğiz. Bu, `Home` gibi bir sunucunun `App\Presenters\HomePresenter` sınıfıyla eşleşmesi gerektiği anlamına gelir. Bu, aşağıdaki yapılandırma ile gerçekleştirilebilir: +Eşleme nasıl çalışır? Daha iyi anlamak için öncelikle modülsüz bir uygulama hayal edelim. Sunucu sınıflarının `App\UI` ad alanı altında olmasını istiyoruz, böylece `Home` sunucusu `App\Presentation\HomePresenter` sınıfıyla eşleşir. Bu, şu yapılandırma ile gerçekleştirilebilir: ```neon application: - mapping: App\Presenters\*Presenter + mapping: App\Presentation\*Presenter ``` -Sunum yapan kişinin adı sınıf maskesindeki yıldız işaretiyle değiştirilir ve sonuç sınıf adı olur. Kolay! +Bu eşleme, `App\Presentation\*Presenter` maskesindeki yıldız işaretini `Home` sunum yapan kişi adıyla değiştirerek çalışır ve sonuçta `App\Presentation\HomePresenter` nihai sınıf adı elde edilir. Çok basit! + +Ancak, bu ve diğer bölümlerdeki örneklerde görebileceğiniz gibi, sunum yapan sınıfları isimsiz alt dizinlere yerleştiriyoruz, örneğin, `Home` sunum yapan `App\Presentation\Home\HomePresenter` sınıfıyla eşleştirilmiştir. Bu, yıldız işaretinin iki katına çıkarılmasıyla elde edilir (Nette Application 3.2 gerektirir): + +```neon +application: + mapping: App\Presentation\**Presenter +``` -Sunum yapanları modüllere ayırırsak, her modül için kendi eşlememizi yapabiliriz: +Şimdi, sunum yapan kişileri modüllerle eşleştirmeye geçelim. Her modül için özel eşlemeler tanımlayabiliriz: ```neon application: mapping: - Front: App\Modules\Front\Presenters\*Presenter - Admin: App\Modules\Admin\Presenters\*Presenter + Front: App\Presentation\Front\**Presenter + Admin: App\Presentation\Admin\**Presenter Api: App\Api\*Presenter ``` -Şimdi `Front:Home` sunucusu `App\Modules\Front\Presenters\HomePresenter` sınıfıyla ve `Admin:Dashboard` sunucusu `App\Modules\Admin\Presenters\DashboardPresenter` sınıfıyla eşleşir. +Bu yapılandırmaya göre, `Front:Home` sunucusu `App\Presentation\Front\Home\HomePresenter` sınıfıyla eşleşirken, `Api:OAuth` sunucusu `App\Api\OAuthPresenter` sınıfıyla eşleşir. -İlk ikisini değiştirmek için genel bir (yıldız) kural oluşturmak daha pratiktir. Ekstra yıldız işareti sadece modül için sınıf maskesine eklenecektir: + `Front` ve `Admin` modülleri benzer bir eşleme yaklaşımına sahip olduğundan ve bu türden daha fazla modül olması muhtemel olduğundan, bunların yerini alan genel bir kural oluşturmak mümkündür. Sınıf maskesine modül için yeni bir yıldız işareti eklenir: ```neon application: mapping: - *: App\Modules\*\Presenters\*Presenter + *: App\Presentation\*\**Presenter Api: App\Api\*Presenter ``` -Peki ya iç içe modüller kullanıyorsak ve bir sunumcumuz varsa `Admin:User:Edit`? Bu durumda, her seviye için modülü temsil eden yıldız işaretli bölüm basitçe tekrarlanır ve sonuç `App\Modules\Admin\User\Presenters\EditPresenter` sınıfı olur. +Sunum yapan kişi `Admin:User:Edit` gibi çok seviyeli iç içe modüller için yıldız işareti segmenti her seviye için tekrarlanır ve `App\Presentation\Admin\User\Edit\EditPresenter` sınıfı ortaya çıkar. -Alternatif bir gösterim, bir dize yerine üç segmentten oluşan bir dizi kullanmaktır. Bu gösterim bir öncekine eşdeğerdir: +Alternatif bir gösterim, dize yerine üç segmentten oluşan bir dizi kullanmaktır. Bu gösterim bir öncekine eşdeğerdir: ```neon application: mapping: - *: [App\Modules, *, Presenters\*Presenter] + *: [App\UI, *, **Presenter] + Api: [App\Api, '', *Presenter] ``` -Varsayılan değer `*Module\*Presenter`'dur. +Konfigürasyonda sadece bir kuralımız varsa, genel olanı, kısaca yazabiliriz: + +```neon +application: + mapping: App\Presentation\*\**Presenter +``` diff --git a/application/tr/templates.texy b/application/tr/templates.texy index d817bc2d45..3f50c9344a 100644 --- a/application/tr/templates.texy +++ b/application/tr/templates.texy @@ -34,35 +34,81 @@ Bu da eylem şablonu olabilir: Düzende `{include content}` yerine eklenen `content` bloğunu tanımlar ve ayrıca düzende `{block title}` 'un üzerine yazılan `title` bloğunu yeniden tanımlar. Sonucu hayal etmeye çalışın. -Şablon Arama .[#toc-search-for-templates] ------------------------------------------ +Şablon Arama .[#toc-template-lookup] +------------------------------------ + +Sunucularda, hangi şablonun işleneceğini belirtmenize gerek yoktur; çerçeve yolu otomatik olarak belirleyerek kodlamayı sizin için kolaylaştıracaktır. + +Her sunucunun kendi dizinine sahip olduğu bir dizin yapısı kullanıyorsanız, şablonu bu dizine eylemin adı (yani görünüm) altında yerleştirmeniz yeterlidir. Örneğin, `default` eylemi için `default.latte` şablonunu kullanın: -Şablonların yolu basit bir mantığa göre çıkarılır. Sunucu sınıfının bulunduğu dizine göre bu şablon dosyalarından birinin var olup olmadığına bakılır, burada `` geçerli sunum yapan kişinin adı ve `` geçerli eylemin adıdır: +/--pre +app/ +└── Presentation/ + └── Home/ + ├── HomePresenter.php + └── default.latte +\-- -- `templates//.latte` -- `templates/..latte` +Sunucuların tek bir dizinde ve şablonların `templates` klasöründe bir arada olduğu bir yapı kullanıyorsanız, bunu bir dosyaya kaydedin `..latte` veya `/.latte`: -Şablon bulunamazsa, `templates` dizininde bir seviye yukarıda, yani sunum yapan sınıfın bulunduğu dizinle aynı seviyede arama yapmaya çalışacaktır. +/--pre +app/ +└── Presenters/ + ├── HomePresenter.php + └── templates/ + ├── Home.default.latte ← 1st variant + └── Home/ + └── default.latte ← 2nd variant +\-- -Şablon orada da bulunamazsa, yanıt [404 hatası |presenters#Error 404 etc.] olur. + `templates` dizini, sunum yapan sınıfların bulunduğu dizinle aynı seviyede, bir seviye daha yükseğe de yerleştirilebilir. -Ayrıca `$this->setView('otherView')` adresini kullanarak görünümü değiştirebilirsiniz. Ya da arama yapmak yerine `$this->template->setFile('/path/to/template.latte')` adresini kullanarak şablon dosyasının adını doğrudan belirtin. +Şablon bulunamazsa, sunum yapan kişi [404 - sayfa bulunamadı hatası |presenters#Error 404 etc] ile yanıt verir. + +Görünümü `$this->setView('anotherView')` adresini kullanarak değiştirebilirsiniz. Şablon dosyasını `$this->template->setFile('/path/to/template.latte')` ile doğrudan belirtmek de mümkündür. .[note] -Olası dosya yollarından oluşan bir dizi döndüren [formatTemplateFiles |api:Nette\Application\UI\Presenter::formatTemplateFiles()] yöntemini geçersiz kılarak şablonların arandığı yolları değiştirebilirsiniz. +Şablonların arandığı dosyalar, olası dosya adlarından oluşan bir dizi döndüren [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()] yöntemi geçersiz kılınarak değiştirilebilir. + + +Düzen Şablonu Arama .[#toc-layout-template-lookup] +-------------------------------------------------- + +Nette ayrıca otomatik olarak yerleşim dosyasını arar. + +Her sunum yapan kişinin kendi dizinine sahip olduğu bir dizin yapısı kullanıyorsanız, düzeni ya sadece sunum yapan kişiye özelse sunum yapan kişinin bulunduğu klasöre ya da birden fazla sunum yapan kişi için ortaksa bir üst seviyeye yerleştirin: + +/--pre +app/ +└── Presentation/ + ├── @layout.latte ← common layout + └── Home/ + ├── @layout.latte ← only for Home presenter + ├── HomePresenter.php + └── default.latte +\-- + +Sunum yapanların tek bir dizinde gruplandığı ve şablonların `templates` klasöründe bulunduğu bir yapı kullanıyorsanız, düzen aşağıdaki yerlerde beklenecektir: -Düzen aşağıdaki dosyalarda beklenmektedir: +/--pre +app/ +└── Presenters/ + ├── HomePresenter.php + └── templates/ + ├── @layout.latte ← common layout + ├── Home.@layout.latte ← only for Home, 1st variant + └── Home/ + └── @layout.latte ← only for Home, 2nd variant +\-- -- `templates//@.latte` -- `templates/.@.latte` -- `templates/@.latte` birden fazla sunumcu için ortak düzen +Sunucu bir [modüldeyse |modules], modülün iç içe geçmesine göre dizin ağacının daha yukarısında da arama yapacaktır. -`` geçerli sunum yapan kişinin adı ve `` varsayılan olarak `'layout'` olan düzenin adıdır. İsim `$this->setLayout('otherLayout')` ile değiştirilebilir, böylece `@otherLayout.latte` dosyaları denenecektir. +Düzenin adı `$this->setLayout('layoutAdmin')` kullanılarak değiştirilebilir ve ardından `@layoutAdmin.latte` dosyasında beklenir. Düzen şablon dosyasını `$this->setLayout('/path/to/template.latte')` adresini kullanarak doğrudan da belirtebilirsiniz. -Düzen şablonunun dosya adını `$this->setLayout('/path/to/template.latte')` adresini kullanarak doğrudan da belirtebilirsiniz. `$this->setLayout(false)` adresini kullanmak düzen aramayı devre dışı bırakacaktır. +Şablon içinde `$this->setLayout(false)` veya `{layout none}` etiketinin kullanılması düzen aramayı devre dışı bırakır. .[note] -Olası dosya yollarından oluşan bir dizi döndüren [formatLayoutTemplateFiles |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()] yöntemini geçersiz kılarak şablonların arandığı yolları değiştirebilirsiniz. +Düzen şablonlarının arandığı dosyalar, olası dosya adlarından oluşan bir dizi döndüren [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()] yöntemi geçersiz kılınarak değiştirilebilir. Şablondaki Değişkenler .[#toc-variables-in-the-template] @@ -104,7 +150,7 @@ Sunucudaki `$this->template` nesnesi artık `ArticleTemplate` sınıfının bir Şablonlarda da fısıldama lüksünün tadını çıkarabilirsiniz, sadece PhpStorm'da Latte eklentisini kurun ve şablonun başında sınıf adını belirtin, "Latte: sistem nasıl yazılır":https://blog.nette.org/tr/latte-tip-sistemi-nasil-kullanilir makalesine bakın: ```latte -{templateType App\Presenters\ArticleTemplate} +{templateType App\Presentation\Article\ArticleTemplate} ... ``` @@ -176,7 +222,7 @@ public function beforeRender(): void Latte sürüm 3, her web projesi için bir [uzantı |latte:creating-extension] oluşturarak daha gelişmiş bir yol sunar. İşte böyle bir sınıfın kabaca bir örneği: ```php -namespace App\Templating; +namespace App\Presentation\Accessory; final class LatteExtension extends Latte\Extension { @@ -214,7 +260,7 @@ final class LatteExtension extends Latte\Extension ```neon latte: extensions: - - App\Templating\LatteExtension + - App\Presentation\Accessory\LatteExtension ``` diff --git a/application/uk/how-it-works.texy b/application/uk/how-it-works.texy index be1f7ce5aa..ed6999cbb8 100644 --- a/application/uk/how-it-works.texy +++ b/application/uk/how-it-works.texy @@ -22,13 +22,13 @@ /--pre web-project/ ├── app/ ← каталог с приложением -│ ├── Presenters/ ← классы презентеров -│ │ ├── HomePresenter.php ← Класс презентера главной страницы -│ │ └── templates/ ← директория шаблонов -│ │ ├── @layout.latte ← шаблон общего макета -│ │ └── Home/ ← шаблоны презентера главной страницы -│ │ └── default.latte ← шаблон действия `default` -│ ├── Router/ ← конфигурация URL-адресов +│ ├── Core/ ← основні необхідні класи +│ │ └── RouterFactory.php ← конфігурація URL-адрес +│ ├── Presentation/ ← презентатори, шаблони та інше +│ │ ├── @layout.latte ← шаблон спільного макета +│ │ └── Home/ ← домашній каталог доповідачів +│ │ ├── HomePresenter.php ← клас головного доповідача +│ │ └── default.latte ← шаблон дії default │ └── Bootstrap.php ← загрузочный класс Bootstrap ├── bin/ ← скрипты командной строки ├── config/ ← файлы конфигурации @@ -91,7 +91,7 @@ Nette - це наставник, який спрямовує вас до нап Додаток починає роботу з того, що просить так званий маршрутизатор вирішити, якому з презентерів передати поточний запит на обробку. Маршрутизатор вирішує, чия це відповідальність. Він переглядає вхідний URL `https://example.com/product/123`, який хоче `показать` продукт із `id: 123` як дію. Доброю звичкою є написання пар презентер + дія, розділених двокрапкою: `Продукт:показать`. -Тому маршрутизатор перетворив URL у пару `Presenter:action` + параметри, у нашому випадку `Product:show` + `id`: 123`. Вы можете увидеть, как выглядит маршрутизатор в файле `app/Router/RouterFactory.php`, і ми детально опишемо його в розділі [Маршрутизація |routing]. +Тому маршрутизатор перетворив URL у пару `Presenter:action` + параметри, у нашому випадку `Product:show` + `id`: 123`. Вы можете увидеть, как выглядит маршрутизатор в файле `app/Core/RouterFactory.php`, і ми детально опишемо його в розділі [Маршрутизація |routing]. Давайте рухатися далі. Додаток уже знає ім'я презентера і може продовжити роботу. Шляхом створення об'єкта `ProductPresenter`, який є кодом презентера `Product`. Точніше, він просить контейнер DI створити презентера, тому що створення об'єктів - це його робота. @@ -121,12 +121,9 @@ class ProductPresenter extends Nette\Application\UI\Presenter Після цього презентер повертає відповідь. Це може бути HTML-сторінка, зображення, XML-документ, надсилання файлу з диска, JSON або перенаправлення на іншу сторінку. Важливо зазначити, що якщо ми явно не вказуємо, як реагувати (що має місце у випадку з `ProductPresenter`), відповіддю буде відображення шаблону з HTML-сторінкою. Чому? Ну, тому що в 99% випадків ми хочемо відобразити шаблон, тому презентер приймає таку поведінку за замовчуванням і хоче полегшити нашу роботу. Це точка зору Nette. -Нам навіть не потрібно вказувати, який шаблон потрібно вивести, він сам виводить шлях до нього відповідно до простої логіки. У випадку з презентером `Product` і дією `show`, він намагається перевірити, чи існує один із цих файлів шаблонів відносно каталогу, в якому знаходиться клас `ProductPresenter`: +Нам навіть не потрібно вказувати, який шаблон рендерити; фреймворк сам визначить шлях. У випадку дії `show` він просто намагається завантажити шаблон `show.latte` з каталогу з класом `ProductPresenter`. Він також намагається знайти макет у файлі `@layout.latte` (докладніше про [пошук шаблонів |templates#Template Lookup]). -- `templates/Product/show.latte` -- `templates/Product.show.latte` - -І потім він відображає шаблон. Тепер завдання презентера і всієї програми виконано. Якщо шаблону не існує, буде повернуто сторінку з помилкою 404. Детальніше про презентери ви можете прочитати на сторінці [Презентери |presenters]. +Згодом шаблони візуалізуються. На цьому завдання доповідача і всієї програми завершується, і робота завершується. Якщо шаблон не існує, буде повернута сторінка помилки 404. Ви можете прочитати більше про доповідачів на сторінці [Доповідачі |presenters]. [* request-flow.svg *] @@ -137,7 +134,7 @@ class ProductPresenter extends Nette\Application\UI\Presenter 3) маршрутизатор декодує URL як пару `Home:default` 4) створюється об'єкт `HomePresenter` 5) викликається метод `renderDefault()` (якщо існує) -6) шаблон `templates/Home/default.latte` з макетом `templates/@layout.latte` відмальований +6) шаблон `default.latte` з макетом `@layout.latte` відмальований Можливо, зараз ви зіткнулися з безліччю нових понять, але ми вважаємо, що вони мають сенс. Створювати додатки в Nette - простіше простого. diff --git a/application/uk/modules.texy b/application/uk/modules.texy index e660553440..ee1390fa3e 100644 --- a/application/uk/modules.texy +++ b/application/uk/modules.texy @@ -2,29 +2,31 @@ ****** .[perex] -У Nette модулі являють собою логічні одиниці, з яких складається додаток. Вони включають ведучі, шаблони, можливо, компоненти та класи моделей. +Модулі вносять ясність у додатки Nette, полегшуючи поділ на логічні блоки. -Одного компонента для презентаторів і одного для шаблонів буде недостатньо для реальних проектів. Наявність десятків файлів в одній папці щонайменше неорганізована. Як вийти з цього становища? Ми просто розділяємо їх на підкаталоги на диску і на простори імен у коді. І це саме те, що роблять модулі Nette. - -Тому давайте забудемо про єдину папку для ведучих і шаблонів і натомість створимо модулі, наприклад, `Admin` і `Front`. +Подібно до організації файлів у папки на жорсткому диску, в Nette ми можемо розділити презентатори, шаблони та інші допоміжні класи на модулі. Як це працює на практиці? Просто додаванням нових підкаталогів до структури. Ось приклад структури з двома модулями, Front і Admin: /--pre -app/ -├── Presenters/ -├── Modules/ ← директория с модулями -│ ├── Admin/ ← модуль Admin -│ │ ├── Presenters/ ← его презентеры -│ │ │ ├── DashboardPresenter.php -│ │ │ └── templates/ -│ └── Front/ ← модуль Front -│ └── Presenters/ ← его презентеры -│ └── ... +app/ +├── Presentation/ +│ ├── Admin/ ← Admin module +│ │ ├── @layout.latte +│ │ ├── Dashboard/ +│ │ │ ├── DashboardPresenter.php +│ │ │ └── default.latte +│ │ └── ... +│ ├── Front/ ← Front module +│ │ ├── @layout.latte +│ │ ├── Home/ +│ │ │ ├── HomePresenter.php +│ │ │ └── default.latte +│ │ └── ... \-- -Ця структура каталогів буде відображена в просторах імен класів, так, наприклад, `DashboardPresenter` буде знаходитися в просторі `App\Modules\Admin\Presenters`: +Ця структура каталогів відображається в просторах імен класів, тому, наприклад, `DashboardPresenter` знаходиться в просторі імен `App\Presentation\Admin\Dashboard`: ```php -namespace App\Modules\Admin\Presenters; +namespace App\Presentation\Admin\Dashboard; class DashboardPresenter extends Nette\Application\UI\Presenter { @@ -32,35 +34,49 @@ class DashboardPresenter extends Nette\Application\UI\Presenter } ``` -Ведучий `Dashboard` усередині модуля `Admin` позначається в додатку за допомогою подвійної точкової нотації як `Admin:Dashboard`, а його дія `default` позначається як `Admin:Dashboard:default`. -А звідки Nette знає, що `Admin:Dashboard` представляє клас `App\Modules\Admin\Presenters\DashboardPresenter`? Ми говоримо про це, використовуючи [відображення |#Mapping] в конфігурації. -Таким чином, наведена структура не є фіксованою, і ви можете змінювати її на свій розсуд. +У програмі ми звертаємось до доповідача `Dashboard` у модулі `Admin`, використовуючи двокрапку, як `Admin:Dashboard`. Для його дії `default` ми звертаємось до нього як `Admin:Dashboard:default`. -Модулі, звісно, можуть містити всі інші частини, крім презентаторів і шаблонів, такі як компоненти, класи моделей тощо. +Представлена структура не є жорсткою; ви можете [повністю налаштувати її відповідно до ваших потреб |#mapping] у конфігурації. .[tip] + +Модулі можуть включати всі інші файли, такі як компоненти і допоміжні класи, на додаток до презентаторів і шаблонів. Якщо ви обмірковуєте, де їх розмістити, розгляньте можливість використання папки `Accessory`: + +/--pre +app/ +├── Presentation/ +│ ├── Admin/ +│ │ ├── Accessory/ +│ │ │ ├── FormFactory.php +│ │ │ └── AdminLayout.php +│ │ ├── Dashboard/ +│ │ └── ... +\-- Вкладені модулі .[#toc-nested-modules] -------------------------------------- -Модулі не обов'язково повинні формувати тільки плоску структуру, ви також можете створювати, наприклад, підмодулі: +Модулі можуть мати кілька рівнів вкладеності, подібно до структури каталогів на диску: /--pre -app/ -├── Modules/ ← директория с модулями -│ ├── Blog/ ← модуль Blog -│ │ ├── Admin/ ← подмодуль Admin -│ │ │ ├── Presenters/ +app/ +├── Presentation/ +│ ├── Blog/ ← Blog module +│ │ ├── Admin/ ← Admin submodule +│ │ │ ├── Dashboard/ +│ │ │ └── ... +│ │ ├── Front/ ← Front submodule +│ │ │ ├── @layout.latte +│ │ │ ├── Home/ │ │ │ └── ... -│ │ └── Front/ ← подмодуль Front -│ │ ├── Presenters/ -│ │ └── ... -│ ├── Forum/ ← модуль Forum +│ ├── Forum/ ← Forum module │ │ └── ... \-- -Таким чином, модуль `Blog` розбивається на підмодулі `Admin` і `Front`. І знову ж таки це буде відображено в просторах імен, які будуть `App\Modules\Blog\Admin\Presenters` тощо. Ведучий `Dashboard` всередині підмодуля називається `Blog:Admin:Dashboard`. +Модуль `Blog` поділяється на підмодулі `Admin` і `Front`. Це також відображається у просторах імен, які потім з'являються як `App\Presentation\Blog\Admin` і подібним чином. Щоб звернутися до доповідача `Dashboard` у підмодулі `Admin`, ми посилаємося на нього як `Blog:Admin:Dashboard`. -Розгалуження може бути настільки глибоким, наскільки ви захочете, тому ви можете створювати підмодулі. +Вкладеність може бути настільки глибокою, наскільки це необхідно, що дозволяє створювати підмодулі. + +Наприклад, якщо в адмініструванні ви маєте багато доповідачів, пов'язаних з управлінням замовленнями, таких як `OrderDetail`, `OrderEdit`, `OrderDispatch` і т.д., ви можете створити модуль `Order`, в якому будуть організовані доповідачі `Detail`, `Edit`, `Dispatch` та інші. Створення посилань .[#toc-creating-links] @@ -99,49 +115,69 @@ class DashboardPresenter extends Nette\Application\UI\Presenter Див. [розділ про маршрутизацію |routing#modules]. -Складання карти .[#toc-mapping] +Картографування .[#toc-mapping] ------------------------------- -Визначає правила, за якими ім'я класу виводиться з імені ведучого. Ми записуємо їх у [конфігурацію |configuration] під ключем `application › mapping`. +Відображення визначає правила отримання імені класу з імені доповідача. Ці правила задаються у [конфігурації |configuration] під ключем `application › mapping`. + +Структури каталогів, згадані раніше на цій сторінці, базуються на наступному відображенні: + +```neon +application: + mapping: App\Presentation\*\**Presenter +``` -Почнемо з прикладу, в якому не використовуються модулі. Ми просто хочемо, щоб класи ведучого мали простір імен `App\Presenters`. Тобто ми хочемо, щоб ведучий, наприклад, `Home` відображався на клас `App\Presenters\HomePresenter`. Цього можна досягти за допомогою такої конфігурації: +Як працює мапування? Для кращого розуміння, давайте спочатку уявимо додаток без модулів. Ми хочемо, щоб класи доповідача потрапляли до простору імен `App\UI`, щоб доповідач `Home` відображався у клас `App\Presentation\HomePresenter`. Цього можна досягти за допомогою такої конфігурації: ```neon application: - mapping: App\Presenters\*Presenter + mapping: App\Presentation\*Presenter ``` -Ім'я презентера замінюється зірочкою, і в результаті виходить назва класу. Легко! +Це відображення працює шляхом заміни зірочки у масці `App\Presentation\*Presenter` на ім'я доповідача `Home`, в результаті чого ми отримаємо кінцеве ім'я класу `App\Presentation\HomePresenter`. Все просто! + +Однак, як ви можете бачити у прикладах у цій та інших главах, ми розміщуємо класи доповідачів у однойменних підкаталогах, наприклад, доповідач `Home` зіставляється з класом `App\Presentation\Home\HomePresenter`. Це досягається за допомогою подвоєння зірочки (потрібно Nette Application 3.2): + +```neon +application: + mapping: App\Presentation\**Presenter +``` -Якщо ми розділимо доповідачів на модулі, то для кожного модуля в нас може бути свій маппінг: +Тепер перейдемо до зіставлення доповідачів з модулями. Для кожного модуля ми можемо визначити специфічні відображення: ```neon application: mapping: - Front: App\Modules\Front\Presenters\*Presenter - Admin: App\Modules\Admin\Presenters\*Presenter + Front: App\Presentation\Front\**Presenter + Admin: App\Presentation\Admin\**Presenter Api: App\Api\*Presenter ``` -Тепер презентер `Front:Home` визначається класом `App\Modules\Front\HomePresenter`, а презентер `Admin:Dashboard` ` - `App\AdminModule\DashboardPresenter`. +Згідно з цією конфігурацією, доповідач `Front:Home` зіставляється з класом `App\Presentation\Front\Home\HomePresenter`, а доповідач `Api:OAuth` зіставляється з класом `App\Api\OAuthPresenter`. -Зручніше буде створити загальне правило (зірочка), яке замінить перші два правила і додасть додаткову зірочку тільки для модуля: +Оскільки модулі `Front` і `Admin` мають подібний підхід до зіставлення і таких модулів, ймовірно, буде більше, можна створити загальне правило, яке замінить їх. До маски класу буде додано нову зірочку для модуля: ```neon application: mapping: - *: App\Modules\*\Presenters\*Presenter + *: App\Presentation\*\**Presenter Api: App\Api\*Presenter ``` -Але що якщо ми використовуємо кілька вкладених модулів і в нас є, наприклад, провідний `Admin:User:Edit`? У цьому випадку сегмент із зірочкою, що представляє модуль для кожного рівня, буде просто повторюватися, і результатом буде клас `App\Modules\Admin\User\Presenters\EditPresenter`. +Для багаторівневих вкладених модулів, таких як доповідач `Admin:User:Edit`, сегмент зірочки повторюється для кожного рівня, в результаті чого утворюється клас `App\Presentation\Admin\User\Edit\EditPresenter`. -Альтернативною нотацією є використання масиву, що складається з трьох сегментів, замість рядка. Ця нотація еквівалентна попередній: +Альтернативним варіантом запису є використання масиву, що складається з трьох сегментів, замість рядка. Цей запис еквівалентний попередньому: ```neon application: mapping: - *: [App\Modules, *, Presenters\*Presenter] + *: [App\UI, *, **Presenter] + Api: [App\Api, '', *Presenter] ``` -Значення за замовчуванням - `*Module\*Presenter`. +Якщо в конфігурації є лише одне правило, загальне, ми можемо написати його коротко: + +```neon +application: + mapping: App\Presentation\*\**Presenter +``` diff --git a/application/uk/templates.texy b/application/uk/templates.texy index 2dc5f8f053..e3e639ccc5 100644 --- a/application/uk/templates.texy +++ b/application/uk/templates.texy @@ -34,35 +34,81 @@ Nette використовує систему шаблонів [Latte |latte:]. Він визначає блок `content`, який вставляється замість `{include content}` у макеті, а також перевизначає блок `title`, який перезаписує `{block title}` у макеті. Спробуйте уявити собі результат. -Пошук шаблонів .[#toc-search-for-templates] -------------------------------------------- +Пошук шаблонів .[#toc-template-lookup] +-------------------------------------- -Шлях до шаблонів визначається ведучим за допомогою простої логіки. Він спробує перевірити, чи є один із цих файлів, розташований відносно каталогу класу ведучого, де `` це ім'я поточного ведучого, а `` це ім'я поточної події: +У презентаторах вам не потрібно вказувати, який шаблон має бути відрендерений; фреймворк автоматично визначить шлях, полегшуючи вам кодування. -- `templates//.latte` -- `templates/..latte` +Якщо ви використовуєте структуру каталогів, де кожен презентер має власний каталог, просто розмістіть шаблон у цьому каталозі під назвою дії (тобто подання). Наприклад, для дії `default` використовуйте шаблон `default.latte`: -Якщо шаблон не буде знайдено, він спробує виконати пошук у каталозі `templates` на один рівень вище, тобто на тому ж рівні, що і каталог з класом presenter. +/--pre +app/ +└── Presentation/ + └── Home/ + ├── HomePresenter.php + └── default.latte +\-- -Якщо шаблон не буде знайдено і там, у відповідь буде видано [помилку 404 |presenters#Error 404 etc.]. +Якщо ви використовуєте структуру, де доповідачі знаходяться разом в одному каталозі, а шаблони - в папці `templates`, збережіть її або у файлі `..latte` або `/.latte`: -Ви також можете змінити вигляд за допомогою `$this->setView('jineView')`. Або, замість прямого пошуку, вкажіть ім'я файлу шаблону за допомогою `$this->template->setFile('/path/to/template.latte')`. +/--pre +app/ +└── Presenters/ + ├── HomePresenter.php + └── templates/ + ├── Home.default.latte ← 1st variant + └── Home/ + └── default.latte ← 2nd variant +\-- + +Директорію `templates` також можна розмістити на один рівень вище, на тому ж рівні, що і директорію з класами ведучого. + +Якщо шаблон не знайдено, доповідач видає [помилку 404 - сторінка не знайдена |presenters#Error 404 etc]. + +Ви можете змінити вигляд за допомогою `$this->setView('anotherView')`. Також можна безпосередньо вказати файл шаблону за допомогою `$this->template->setFile('/path/to/template.latte')`. .[note] -Файли, в яких здійснюється пошук шаблонів, можна змінити, наклавши метод [formatTemplateFiles() |api:Nette\Application\UI\Presenter::formatTemplateFiles()], який повертає масив можливих імен файлів. +Файли, в яких шукаються шаблони, можна змінити, перевизначивши метод [formatTemplateFiles( |api:Nette\Application\UI\Presenter::formatTemplateFiles()]), який повертає масив можливих імен файлів. + + +Пошук шаблонів макетів .[#toc-layout-template-lookup] +----------------------------------------------------- + +Nette також автоматично шукає файл макета. + +Якщо ви використовуєте структуру каталогів, де кожен доповідач має власний каталог, розмістіть макет або в папці доповідача, якщо він стосується лише його, або на рівень вище, якщо він є спільним для кількох доповідачів: + +/--pre +app/ +└── Presentation/ + ├── @layout.latte ← common layout + └── Home/ + ├── @layout.latte ← only for Home presenter + ├── HomePresenter.php + └── default.latte +\-- + +Якщо ви використовуєте структуру, в якій ведучі згруповані в одному каталозі, а шаблони знаходяться в папці `templates`, макет буде знаходитися в наступних місцях: -У цих файлах очікується компонування: +/--pre +app/ +└── Presenters/ + ├── HomePresenter.php + └── templates/ + ├── @layout.latte ← common layout + ├── Home.@layout.latte ← only for Home, 1st variant + └── Home/ + └── @layout.latte ← only for Home, 2nd variant +\-- -- `templates//@.latte` -- `templates/.@.latte` -- `templates/@.latte` макет, спільний для кількох доповідачів +Якщо доповідач знаходиться в [модулі |modules], він також буде шукати далі по дереву каталогів відповідно до вкладеності модуля. -Де `` це ім'я поточного ведучого і `` це ім'я макета, яке за замовчуванням дорівнює `'layout'`. Ім'я може бути змінено за допомогою `$this->setLayout('jinyLayout')`, тому будуть випробувані файли `@jinyLayout.latte`. +Назву шаблону можна змінити за допомогою `$this->setLayout('layoutAdmin')` і тоді вона буде очікуватися у файлі `@layoutAdmin.latte`. Ви також можете безпосередньо вказати файл шаблону розкладки за допомогою `$this->setLayout('/path/to/template.latte')`. -Ви також можете безпосередньо вказати ім'я файлу шаблону макета за допомогою `$this->setLayout('/path/to/template.latte')`. Використання `$this->setLayout(false)` відключає відстеження макета. +Використання `$this->setLayout(false)` або тегу `{layout none}` всередині шаблону вимикає пошук макетів. .[note] -Файли, в яких здійснюється пошук шаблонів макета, можна змінити, наклавши метод [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()], який повертає масив можливих імен файлів. +Файли, в яких шукаються шаблони макетів, можна змінити, перевизначивши метод [formatLayoutTemplateFiles( |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()]), який повертає масив можливих імен файлів. Змінні в шаблоні .[#toc-variables-in-the-template] @@ -104,7 +150,7 @@ class ArticleTemplate extends Nette\Bridges\ApplicationLatte\Template Ви також можете дозволити собі розкіш шепотіти в шаблонах, просто встановіть плагін Latte в PhpStorm і помістіть ім'я класу на початок шаблону, докладнішу інформацію дивіться в статті "Latte: як набирати систему":https://blog.nette.org/uk/latte-yak-koristuvatisya-sistemoyu-tipiv: ```latte -{templateType App\Presenters\ArticleTemplate} +{templateType App\Presentation\Article\ArticleTemplate} ... ``` @@ -176,7 +222,7 @@ public function beforeRender(): void Latte версії 3 пропонує більш просунутий спосіб створення [розширення |latte:creating-extension] для кожного веб-проекту. Ось короткий приклад такого класу: ```php -namespace App\Templating; +namespace App\Presentation\Accessory; final class LatteExtension extends Latte\Extension { @@ -214,7 +260,7 @@ final class LatteExtension extends Latte\Extension ```neon latte: extensions: - - App\Templating\LatteExtension + - App\Presentation\Accessory\LatteExtension ``` From 855fb709052c2e9e1bd5df87ac62e2c8dbccecab Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 18 Apr 2024 18:04:12 +0200 Subject: [PATCH 074/137] new directory structure throughout documentation --- application/bg/routing.texy | 10 +++---- application/cs/routing.texy | 10 +++---- application/de/routing.texy | 10 +++---- application/el/routing.texy | 10 +++---- application/en/routing.texy | 10 +++---- application/es/routing.texy | 10 +++---- application/fr/routing.texy | 10 +++---- application/hu/routing.texy | 10 +++---- application/it/routing.texy | 10 +++---- application/pl/routing.texy | 10 +++---- application/pt/routing.texy | 10 +++---- application/ro/routing.texy | 10 +++---- application/ru/routing.texy | 10 +++---- application/sl/routing.texy | 10 +++---- application/tr/routing.texy | 10 +++---- application/uk/routing.texy | 10 +++---- best-practices/bg/composer.texy | 2 +- .../bg/lets-create-contact-form.texy | 2 +- best-practices/bg/pagination.texy | 10 +++---- best-practices/cs/composer.texy | 2 +- .../cs/lets-create-contact-form.texy | 2 +- best-practices/cs/pagination.texy | 10 +++---- best-practices/de/composer.texy | 2 +- .../de/lets-create-contact-form.texy | 2 +- best-practices/de/pagination.texy | 10 +++---- best-practices/el/composer.texy | 2 +- .../el/lets-create-contact-form.texy | 2 +- best-practices/el/pagination.texy | 10 +++---- best-practices/en/composer.texy | 2 +- .../en/lets-create-contact-form.texy | 2 +- best-practices/en/pagination.texy | 10 +++---- best-practices/es/composer.texy | 2 +- .../es/lets-create-contact-form.texy | 2 +- best-practices/es/pagination.texy | 10 +++---- best-practices/fr/composer.texy | 2 +- .../fr/lets-create-contact-form.texy | 2 +- best-practices/fr/pagination.texy | 10 +++---- best-practices/hu/composer.texy | 2 +- .../hu/lets-create-contact-form.texy | 2 +- best-practices/hu/pagination.texy | 10 +++---- best-practices/it/composer.texy | 2 +- .../it/lets-create-contact-form.texy | 2 +- best-practices/it/pagination.texy | 10 +++---- best-practices/pl/composer.texy | 2 +- .../pl/lets-create-contact-form.texy | 2 +- best-practices/pl/pagination.texy | 10 +++---- best-practices/pt/composer.texy | 2 +- .../pt/lets-create-contact-form.texy | 2 +- best-practices/pt/pagination.texy | 10 +++---- best-practices/ro/composer.texy | 2 +- .../ro/lets-create-contact-form.texy | 2 +- best-practices/ro/pagination.texy | 10 +++---- best-practices/ru/composer.texy | 2 +- .../ru/lets-create-contact-form.texy | 2 +- best-practices/ru/pagination.texy | 10 +++---- best-practices/sl/composer.texy | 2 +- .../sl/lets-create-contact-form.texy | 2 +- best-practices/sl/pagination.texy | 10 +++---- best-practices/tr/composer.texy | 2 +- .../tr/lets-create-contact-form.texy | 2 +- best-practices/tr/pagination.texy | 10 +++---- best-practices/uk/composer.texy | 2 +- .../uk/lets-create-contact-form.texy | 2 +- best-practices/uk/pagination.texy | 10 +++---- dependency-injection/bg/configuration.texy | 2 +- dependency-injection/bg/factory.texy | 2 +- dependency-injection/cs/configuration.texy | 2 +- dependency-injection/cs/factory.texy | 2 +- dependency-injection/de/configuration.texy | 2 +- dependency-injection/de/factory.texy | 2 +- dependency-injection/el/configuration.texy | 2 +- dependency-injection/el/factory.texy | 2 +- dependency-injection/en/configuration.texy | 2 +- dependency-injection/en/factory.texy | 2 +- dependency-injection/es/configuration.texy | 2 +- dependency-injection/es/factory.texy | 2 +- dependency-injection/fr/configuration.texy | 2 +- dependency-injection/fr/factory.texy | 2 +- dependency-injection/hu/configuration.texy | 2 +- dependency-injection/hu/factory.texy | 2 +- dependency-injection/it/configuration.texy | 2 +- dependency-injection/it/factory.texy | 2 +- dependency-injection/ja/configuration.texy | 2 +- dependency-injection/ja/factory.texy | 2 +- dependency-injection/pl/configuration.texy | 2 +- dependency-injection/pl/factory.texy | 2 +- dependency-injection/pt/configuration.texy | 2 +- dependency-injection/pt/factory.texy | 2 +- dependency-injection/ro/configuration.texy | 2 +- dependency-injection/ro/factory.texy | 2 +- dependency-injection/ru/configuration.texy | 2 +- dependency-injection/ru/factory.texy | 2 +- dependency-injection/sl/configuration.texy | 2 +- dependency-injection/sl/factory.texy | 2 +- dependency-injection/tr/configuration.texy | 2 +- dependency-injection/tr/factory.texy | 2 +- dependency-injection/uk/configuration.texy | 2 +- dependency-injection/uk/factory.texy | 2 +- forms/bg/in-presenter.texy | 4 +-- forms/cs/in-presenter.texy | 4 +-- forms/de/in-presenter.texy | 4 +-- forms/el/in-presenter.texy | 4 +-- forms/en/in-presenter.texy | 4 +-- forms/es/in-presenter.texy | 4 +-- forms/fr/in-presenter.texy | 4 +-- forms/hu/in-presenter.texy | 4 +-- forms/it/in-presenter.texy | 4 +-- forms/pl/in-presenter.texy | 4 +-- forms/pt/in-presenter.texy | 4 +-- forms/ro/in-presenter.texy | 4 +-- forms/ru/in-presenter.texy | 4 +-- forms/sl/in-presenter.texy | 4 +-- forms/tr/in-presenter.texy | 4 +-- forms/uk/in-presenter.texy | 4 +-- latte/bg/template-inheritance.texy | 2 +- latte/de/template-inheritance.texy | 2 +- latte/el/template-inheritance.texy | 2 +- latte/en/template-inheritance.texy | 2 +- latte/es/template-inheritance.texy | 2 +- latte/fr/template-inheritance.texy | 2 +- latte/hu/template-inheritance.texy | 2 +- latte/it/template-inheritance.texy | 2 +- latte/ja/template-inheritance.texy | 2 +- latte/pl/template-inheritance.texy | 2 +- latte/pt/template-inheritance.texy | 2 +- latte/ro/template-inheritance.texy | 2 +- latte/ru/template-inheritance.texy | 2 +- latte/sl/template-inheritance.texy | 2 +- latte/tr/template-inheritance.texy | 2 +- latte/uk/template-inheritance.texy | 2 +- quickstart/bg/@home.texy | 12 ++++---- quickstart/bg/authentication.texy | 22 +++++++------- quickstart/bg/comments.texy | 14 ++++----- quickstart/bg/creating-posts.texy | 24 +++++++-------- quickstart/bg/home-page.texy | 25 ++++++++-------- quickstart/bg/model.texy | 4 +-- quickstart/bg/single-post.texy | 28 +++++++++--------- quickstart/cs/@home.texy | 12 ++++---- quickstart/cs/authentication.texy | 18 +++++------ quickstart/cs/comments.texy | 12 ++++---- quickstart/cs/creating-posts.texy | 22 +++++++------- quickstart/cs/home-page.texy | 21 +++++++------ quickstart/cs/model.texy | 4 +-- quickstart/cs/single-post.texy | 26 ++++++++-------- quickstart/de/@home.texy | 12 ++++---- quickstart/de/authentication.texy | 18 +++++------ quickstart/de/comments.texy | 12 ++++---- quickstart/de/creating-posts.texy | 22 +++++++------- quickstart/de/home-page.texy | 21 +++++++------ quickstart/de/model.texy | 4 +-- quickstart/de/single-post.texy | 26 ++++++++-------- quickstart/el/@home.texy | 12 ++++---- quickstart/el/authentication.texy | 18 +++++------ quickstart/el/comments.texy | 12 ++++---- quickstart/el/creating-posts.texy | 22 +++++++------- quickstart/el/home-page.texy | 21 +++++++------ quickstart/el/model.texy | 4 +-- quickstart/el/single-post.texy | 26 ++++++++-------- quickstart/en/@home.texy | 12 ++++---- quickstart/en/authentication.texy | 18 +++++------ quickstart/en/comments.texy | 12 ++++---- quickstart/en/creating-posts.texy | 22 +++++++------- quickstart/en/home-page.texy | 21 +++++++------ quickstart/en/model.texy | 4 +-- quickstart/en/single-post.texy | 26 ++++++++-------- quickstart/es/@home.texy | 12 ++++---- quickstart/es/authentication.texy | 18 +++++------ quickstart/es/comments.texy | 12 ++++---- quickstart/es/creating-posts.texy | 22 +++++++------- quickstart/es/home-page.texy | 21 +++++++------ quickstart/es/model.texy | 4 +-- quickstart/es/single-post.texy | 26 ++++++++-------- quickstart/files/qs-tracy.avif | Bin 0 -> 14828 bytes quickstart/files/qs-tracy.webp | Bin 40154 -> 0 bytes quickstart/fr/@home.texy | 12 ++++---- quickstart/fr/authentication.texy | 18 +++++------ quickstart/fr/comments.texy | 12 ++++---- quickstart/fr/creating-posts.texy | 22 +++++++------- quickstart/fr/home-page.texy | 21 +++++++------ quickstart/fr/model.texy | 4 +-- quickstart/fr/single-post.texy | 26 ++++++++-------- quickstart/hu/@home.texy | 12 ++++---- quickstart/hu/authentication.texy | 18 +++++------ quickstart/hu/comments.texy | 12 ++++---- quickstart/hu/creating-posts.texy | 22 +++++++------- quickstart/hu/home-page.texy | 21 +++++++------ quickstart/hu/model.texy | 4 +-- quickstart/hu/single-post.texy | 26 ++++++++-------- quickstart/it/@home.texy | 12 ++++---- quickstart/it/authentication.texy | 18 +++++------ quickstart/it/comments.texy | 12 ++++---- quickstart/it/creating-posts.texy | 22 +++++++------- quickstart/it/home-page.texy | 21 +++++++------ quickstart/it/model.texy | 4 +-- quickstart/it/single-post.texy | 26 ++++++++-------- quickstart/pl/@home.texy | 12 ++++---- quickstart/pl/authentication.texy | 18 +++++------ quickstart/pl/comments.texy | 12 ++++---- quickstart/pl/creating-posts.texy | 22 +++++++------- quickstart/pl/home-page.texy | 21 +++++++------ quickstart/pl/model.texy | 4 +-- quickstart/pl/single-post.texy | 26 ++++++++-------- quickstart/pt/@home.texy | 12 ++++---- quickstart/pt/authentication.texy | 18 +++++------ quickstart/pt/comments.texy | 12 ++++---- quickstart/pt/creating-posts.texy | 22 +++++++------- quickstart/pt/home-page.texy | 21 +++++++------ quickstart/pt/model.texy | 4 +-- quickstart/pt/single-post.texy | 26 ++++++++-------- quickstart/ro/@home.texy | 12 ++++---- quickstart/ro/authentication.texy | 18 +++++------ quickstart/ro/comments.texy | 12 ++++---- quickstart/ro/creating-posts.texy | 22 +++++++------- quickstart/ro/home-page.texy | 21 +++++++------ quickstart/ro/model.texy | 4 +-- quickstart/ro/single-post.texy | 26 ++++++++-------- quickstart/ru/@home.texy | 12 ++++---- quickstart/ru/authentication.texy | 22 +++++++------- quickstart/ru/comments.texy | 14 ++++----- quickstart/ru/creating-posts.texy | 24 +++++++-------- quickstart/ru/home-page.texy | 25 ++++++++-------- quickstart/ru/model.texy | 4 +-- quickstart/ru/single-post.texy | 28 +++++++++--------- quickstart/sl/@home.texy | 12 ++++---- quickstart/sl/authentication.texy | 18 +++++------ quickstart/sl/comments.texy | 12 ++++---- quickstart/sl/creating-posts.texy | 22 +++++++------- quickstart/sl/home-page.texy | 21 +++++++------ quickstart/sl/model.texy | 4 +-- quickstart/sl/single-post.texy | 26 ++++++++-------- quickstart/tr/@home.texy | 12 ++++---- quickstart/tr/authentication.texy | 18 +++++------ quickstart/tr/comments.texy | 12 ++++---- quickstart/tr/creating-posts.texy | 22 +++++++------- quickstart/tr/home-page.texy | 21 +++++++------ quickstart/tr/model.texy | 4 +-- quickstart/tr/single-post.texy | 26 ++++++++-------- quickstart/uk/@home.texy | 12 ++++---- quickstart/uk/authentication.texy | 22 +++++++------- quickstart/uk/comments.texy | 14 ++++----- quickstart/uk/creating-posts.texy | 24 +++++++-------- quickstart/uk/home-page.texy | 25 ++++++++-------- quickstart/uk/model.texy | 4 +-- quickstart/uk/single-post.texy | 28 +++++++++--------- robot-loader/bg/@home.texy | 2 +- robot-loader/cs/@home.texy | 2 +- robot-loader/de/@home.texy | 2 +- robot-loader/el/@home.texy | 2 +- robot-loader/en/@home.texy | 2 +- robot-loader/es/@home.texy | 2 +- robot-loader/fr/@home.texy | 2 +- robot-loader/hu/@home.texy | 2 +- robot-loader/it/@home.texy | 2 +- robot-loader/pl/@home.texy | 2 +- robot-loader/pt/@home.texy | 2 +- robot-loader/ro/@home.texy | 2 +- robot-loader/ru/@home.texy | 2 +- robot-loader/sl/@home.texy | 2 +- robot-loader/tr/@home.texy | 2 +- robot-loader/uk/@home.texy | 2 +- tracy/bg/guide.texy | 6 ++-- tracy/cs/guide.texy | 6 ++-- tracy/de/guide.texy | 6 ++-- tracy/el/guide.texy | 6 ++-- tracy/en/guide.texy | 6 ++-- tracy/es/guide.texy | 6 ++-- tracy/fr/guide.texy | 6 ++-- tracy/hu/guide.texy | 6 ++-- tracy/it/guide.texy | 6 ++-- tracy/pl/guide.texy | 6 ++-- tracy/pt/guide.texy | 6 ++-- tracy/ro/guide.texy | 6 ++-- tracy/ru/guide.texy | 6 ++-- tracy/sl/guide.texy | 6 ++-- tracy/tr/guide.texy | 6 ++-- tracy/uk/guide.texy | 6 ++-- 276 files changed, 1255 insertions(+), 1303 deletions(-) create mode 100644 quickstart/files/qs-tracy.avif delete mode 100644 quickstart/files/qs-tracy.webp diff --git a/application/bg/routing.texy b/application/bg/routing.texy index 300a7755e2..e71cd50516 100644 --- a/application/bg/routing.texy +++ b/application/bg/routing.texy @@ -477,10 +477,10 @@ $router->addRoute('index', /* ... */); Интеграция .[#toc-integration] ============================== -За да свържем маршрутизатора си с приложението, трябва да информираме за това контейнера DI. Най-лесният начин е да се подготви фабрика, която ще създаде обект маршрутизатор, и да се каже на конфигурацията на контейнера да го използва. Да предположим, че напишем метод за това, `App\Router\RouterFactory::createRouter()`: +За да свържем маршрутизатора си с приложението, трябва да информираме за това контейнера DI. Най-лесният начин е да се подготви фабрика, която ще създаде обект маршрутизатор, и да се каже на конфигурацията на контейнера да го използва. Да предположим, че напишем метод за това, `App\Core\RouterFactory::createRouter()`: ```php -namespace App\Router; +namespace App\Core; use Nette\Application\Routers\RouteList; @@ -499,7 +499,7 @@ class RouterFactory ```neon services: - - App\Router\RouterFactory::createRouter + - App\Core\RouterFactory::createRouter ``` Всички зависимости, като например връзки към бази данни и т.н., се предават на метода на фабриката като параметри, като се използва [автоматично свързване |dependency-injection:autowiring]: @@ -663,7 +663,7 @@ $router->addRoute(/* ... */); Затова отново ще добавим метод, който ще създаде например маршрутизатор: ```php -namespace App\Router; +namespace App\Core; use Nette\Routing\RouteList; @@ -694,7 +694,7 @@ $httpRequest = $container->getByType(Nette\Http\IRequest::class); Или ще създадем обектите директно: ```php -$router = App\Router\RouterFactory::createRouter(); +$router = App\Core\RouterFactory::createRouter(); $httpRequest = (new Nette\Http\RequestFactory)->fromGlobals(); ``` diff --git a/application/cs/routing.texy b/application/cs/routing.texy index 3f58166681..adb92c1cae 100644 --- a/application/cs/routing.texy +++ b/application/cs/routing.texy @@ -477,10 +477,10 @@ $router->addRoute('index', /* ... */); Začlenění do aplikace ===================== -Abychom vytvořený router zapojili do aplikace, musíme o něm říci DI kontejneru. Nejsnazší cesta je připravit továrnu, která objekt routeru vyrobí, a sdělit v konfiguraci kontejneru, že ji má použít. Dejme tomu, že k tomu účelu napíšeme metodu `App\Router\RouterFactory::createRouter()`: +Abychom vytvořený router zapojili do aplikace, musíme o něm říci DI kontejneru. Nejsnazší cesta je připravit továrnu, která objekt routeru vyrobí, a sdělit v konfiguraci kontejneru, že ji má použít. Dejme tomu, že k tomu účelu napíšeme metodu `App\Core\RouterFactory::createRouter()`: ```php -namespace App\Router; +namespace App\Core; use Nette\Application\Routers\RouteList; @@ -499,7 +499,7 @@ Do [konfigurace |dependency-injection:services] pak zapíšeme: ```neon services: - - App\Router\RouterFactory::createRouter + - App\Core\RouterFactory::createRouter ``` Jakékoliv závislosti, třeba na databázi atd, se předají tovární metodě jako její parametry pomocí [autowiringu|dependency-injection:autowiring]: @@ -663,7 +663,7 @@ Samostatným použitím myslíme využití schopností routeru v aplikaci, kter Takže opět si vytvoříme metodu, která nám sestaví router, např.: ```php -namespace App\Router; +namespace App\Core; use Nette\Routing\RouteList; @@ -694,7 +694,7 @@ $httpRequest = $container->getByType(Nette\Http\IRequest::class); Anebo objekty přímo vyrobíme: ```php -$router = App\Router\RouterFactory::createRouter(); +$router = App\Core\RouterFactory::createRouter(); $httpRequest = (new Nette\Http\RequestFactory)->fromGlobals(); ``` diff --git a/application/de/routing.texy b/application/de/routing.texy index dac42c271d..d398f7f759 100644 --- a/application/de/routing.texy +++ b/application/de/routing.texy @@ -477,10 +477,10 @@ $router->addRoute('index', /* ... */); Einbindung .[#toc-integration] ============================== -Um unseren Router in die Anwendung einzubinden, müssen wir ihn dem DI-Container mitteilen. Am einfachsten ist es, die Fabrik vorzubereiten, die das Router-Objekt erstellt, und der Container-Konfiguration mitzuteilen, dass sie es verwenden soll. Schreiben wir also eine Methode für diesen Zweck `App\Router\RouterFactory::createRouter()`: +Um unseren Router in die Anwendung einzubinden, müssen wir ihn dem DI-Container mitteilen. Am einfachsten ist es, die Fabrik vorzubereiten, die das Router-Objekt erstellt, und der Container-Konfiguration mitzuteilen, dass sie es verwenden soll. Schreiben wir also eine Methode für diesen Zweck `App\Core\RouterFactory::createRouter()`: ```php -namespace App\Router; +namespace App\Core; use Nette\Application\Routers\RouteList; @@ -499,7 +499,7 @@ Dann schreiben wir in [configuration |dependency-injection:services]: ```neon services: - - App\Router\RouterFactory::createRouter + - App\Core\RouterFactory::createRouter ``` Alle Abhängigkeiten, wie z. B. eine Datenbankverbindung usw., werden der Factory-Methode als Parameter über [Autowiring |dependency-injection:autowiring] übergeben: @@ -663,7 +663,7 @@ Unter getrennter Nutzung verstehen wir die Verwendung der Router-Funktionen in e Wir werden also wieder eine Methode erstellen, die einen Router aufbaut, zum Beispiel: ```php -namespace App\Router; +namespace App\Core; use Nette\Routing\RouteList; @@ -694,7 +694,7 @@ $httpRequest = $container->getByType(Nette\Http\IRequest::class); Oder wir erstellen die Objekte direkt: ```php -$router = App\Router\RouterFactory::createRouter(); +$router = App\Core\RouterFactory::createRouter(); $httpRequest = (new Nette\Http\RequestFactory)->fromGlobals(); ``` diff --git a/application/el/routing.texy b/application/el/routing.texy index 448fa6f67b..cb79da06a4 100644 --- a/application/el/routing.texy +++ b/application/el/routing.texy @@ -477,10 +477,10 @@ $router->addRoute('index', /* ... */); Ενσωμάτωση .[#toc-integration] ============================== -Για να συνδέσουμε τον δρομολογητή μας στην εφαρμογή, πρέπει να ενημερώσουμε το DI container σχετικά με αυτόν. Ο ευκολότερος τρόπος είναι να προετοιμάσουμε το εργοστάσιο που θα κατασκευάσει το αντικείμενο του δρομολογητή και να πούμε στη διαμόρφωση του δοχείου να το χρησιμοποιήσει. Ας πούμε λοιπόν ότι γράφουμε μια μέθοδο για το σκοπό αυτό `App\Router\RouterFactory::createRouter()`: +Για να συνδέσουμε τον δρομολογητή μας στην εφαρμογή, πρέπει να ενημερώσουμε το DI container σχετικά με αυτόν. Ο ευκολότερος τρόπος είναι να προετοιμάσουμε το εργοστάσιο που θα κατασκευάσει το αντικείμενο του δρομολογητή και να πούμε στη διαμόρφωση του δοχείου να το χρησιμοποιήσει. Ας πούμε λοιπόν ότι γράφουμε μια μέθοδο για το σκοπό αυτό `App\Core\RouterFactory::createRouter()`: ```php -namespace App\Router; +namespace App\Core; use Nette\Application\Routers\RouteList; @@ -499,7 +499,7 @@ class RouterFactory ```neon services: - - App\Router\RouterFactory::createRouter + - App\Core\RouterFactory::createRouter ``` Οποιεσδήποτε εξαρτήσεις, όπως μια σύνδεση βάσης δεδομένων κ.λπ., περνούν στη μέθοδο factory ως παράμετροι με τη χρήση [αυτόματης σύνδεσης |dependency-injection:autowiring]: @@ -663,7 +663,7 @@ $router->addRoute(/* ... */); Έτσι και πάλι θα δημιουργήσουμε μια μέθοδο που θα κατασκευάσει ένα δρομολογητή, για παράδειγμα: ```php -namespace App\Router; +namespace App\Core; use Nette\Routing\RouteList; @@ -694,7 +694,7 @@ $httpRequest = $container->getByType(Nette\Http\IRequest::class); Ή θα δημιουργήσουμε αντικείμενα απευθείας: ```php -$router = App\Router\RouterFactory::createRouter(); +$router = App\Core\RouterFactory::createRouter(); $httpRequest = (new Nette\Http\RequestFactory)->fromGlobals(); ``` diff --git a/application/en/routing.texy b/application/en/routing.texy index c35c692adb..9c49994566 100644 --- a/application/en/routing.texy +++ b/application/en/routing.texy @@ -477,10 +477,10 @@ $router->addRoute('index', /* ... */); Integration =========== -In order to connect the our router into the application, we must tell the DI container about it. The easiest way is to prepare the factory that will build the router object and tell the container configuration to use it. So let's say we write a method for this purpose `App\Router\RouterFactory::createRouter()`: +In order to connect the our router into the application, we must tell the DI container about it. The easiest way is to prepare the factory that will build the router object and tell the container configuration to use it. So let's say we write a method for this purpose `App\Core\RouterFactory::createRouter()`: ```php -namespace App\Router; +namespace App\Core; use Nette\Application\Routers\RouteList; @@ -499,7 +499,7 @@ Then we write in [configuration |dependency-injection:services]: ```neon services: - - App\Router\RouterFactory::createRouter + - App\Core\RouterFactory::createRouter ``` Any dependencies, such as a database connection etc., are passed to the factory method as its parameters using [autowiring |dependency-injection:autowiring]: @@ -663,7 +663,7 @@ By separated usage, we mean the use of the router's capabilities in an applicati So again we will create a method that will build a router, for example: ```php -namespace App\Router; +namespace App\Core; use Nette\Routing\RouteList; @@ -694,7 +694,7 @@ $httpRequest = $container->getByType(Nette\Http\IRequest::class); Or we will create objects directly: ```php -$router = App\Router\RouterFactory::createRouter(); +$router = App\Core\RouterFactory::createRouter(); $httpRequest = (new Nette\Http\RequestFactory)->fromGlobals(); ``` diff --git a/application/es/routing.texy b/application/es/routing.texy index c6ed0f3950..8898449791 100644 --- a/application/es/routing.texy +++ b/application/es/routing.texy @@ -477,10 +477,10 @@ $router->addRoute('index', /* ... */); Integración .[#toc-integration] =============================== -Para conectar nuestro router a la aplicación, debemos informar al contenedor DI sobre él. La forma más sencilla es preparar la fábrica que construirá el objeto router y decirle a la configuración del contenedor que lo utilice. Digamos que escribimos un método para este propósito `App\Router\RouterFactory::createRouter()`: +Para conectar nuestro router a la aplicación, debemos informar al contenedor DI sobre él. La forma más sencilla es preparar la fábrica que construirá el objeto router y decirle a la configuración del contenedor que lo utilice. Digamos que escribimos un método para este propósito `App\Core\RouterFactory::createRouter()`: ```php -namespace App\Router; +namespace App\Core; use Nette\Application\Routers\RouteList; @@ -499,7 +499,7 @@ Luego escribimos en [configuración |dependency-injection:services]: ```neon services: - - App\Router\RouterFactory::createRouter + - App\Core\RouterFactory::createRouter ``` Cualquier dependencia, como una conexión de base de datos, etc., se pasa al método de fábrica como sus parámetros utilizando [autowiring |dependency-injection:autowiring]: @@ -663,7 +663,7 @@ Por uso separado, nos referimos al uso de las capacidades del router en una apli Así que de nuevo crearemos un método que construirá un enrutador, por ejemplo ```php -namespace App\Router; +namespace App\Core; use Nette\Routing\RouteList; @@ -694,7 +694,7 @@ $httpRequest = $container->getByType(Nette\Http\IRequest::class); O crearemos los objetos directamente: ```php -$router = App\Router\RouterFactory::createRouter(); +$router = App\Core\RouterFactory::createRouter(); $httpRequest = (new Nette\Http\RequestFactory)->fromGlobals(); ``` diff --git a/application/fr/routing.texy b/application/fr/routing.texy index 9fe5d5e4a6..3f1cb29675 100644 --- a/application/fr/routing.texy +++ b/application/fr/routing.texy @@ -477,10 +477,10 @@ $router->addRoute('index', /* ... */); Intégration .[#toc-integration] =============================== -Afin de connecter notre routeur à l'application, nous devons en informer le conteneur DI. Le moyen le plus simple est de préparer la fabrique qui construira l'objet routeur et de dire à la configuration du conteneur de l'utiliser. Disons que nous écrivons une méthode dans ce but `App\Router\RouterFactory::createRouter()`: +Afin de connecter notre routeur à l'application, nous devons en informer le conteneur DI. Le moyen le plus simple est de préparer la fabrique qui construira l'objet routeur et de dire à la configuration du conteneur de l'utiliser. Disons que nous écrivons une méthode dans ce but `App\Core\RouterFactory::createRouter()`: ```php -namespace App\Router; +namespace App\Core; use Nette\Application\Routers\RouteList; @@ -499,7 +499,7 @@ Puis nous écrivons dans la [configuration |dependency-injection:services]: ```neon services: - - App\Router\RouterFactory::createRouter + - App\Core\RouterFactory::createRouter ``` Toutes les dépendances, telles qu'une connexion à une base de données, etc., sont transmises à la méthode factory en tant que paramètres en utilisant le [câblage automatique |dependency-injection:autowiring]: @@ -663,7 +663,7 @@ Par utilisation séparée, nous entendons l'utilisation des capacités du routeu Donc encore une fois nous allons créer une méthode qui va construire un routeur, par exemple : ```php -namespace App\Router; +namespace App\Core; use Nette\Routing\RouteList; @@ -694,7 +694,7 @@ $httpRequest = $container->getByType(Nette\Http\IRequest::class); Ou bien nous créerons directement des objets : ```php -$router = App\Router\RouterFactory::createRouter(); +$router = App\Core\RouterFactory::createRouter(); $httpRequest = (new Nette\Http\RequestFactory)->fromGlobals(); ``` diff --git a/application/hu/routing.texy b/application/hu/routing.texy index 5cf399296b..c2b8f71eda 100644 --- a/application/hu/routing.texy +++ b/application/hu/routing.texy @@ -477,10 +477,10 @@ $router->addRoute('index', /* ... */); Integráció .[#toc-integration] ============================== -Ahhoz, hogy a routerünket az alkalmazásba kapcsoljuk, tájékoztatnunk kell róla a DI konténert. A legegyszerűbb, ha elkészítjük a gyárat, amely a router objektumot fogja felépíteni, és megmondjuk a konténer konfigurációjának, hogy használja azt. Tegyük fel, hogy írunk egy metódust erre a célra `App\Router\RouterFactory::createRouter()`: +Ahhoz, hogy a routerünket az alkalmazásba kapcsoljuk, tájékoztatnunk kell róla a DI konténert. A legegyszerűbb, ha elkészítjük a gyárat, amely a router objektumot fogja felépíteni, és megmondjuk a konténer konfigurációjának, hogy használja azt. Tegyük fel, hogy írunk egy metódust erre a célra `App\Core\RouterFactory::createRouter()`: ```php -namespace App\Router; +namespace App\Core; use Nette\Application\Routers\RouteList; @@ -499,7 +499,7 @@ Ezután beírjuk a [konfigurációba |dependency-injection:services]: ```neon services: - - App\Router\RouterFactory::createRouter + - App\Core\RouterFactory::createRouter ``` Az esetleges függőségeket, például az adatbázis-kapcsolatot stb., az [autowiring |dependency-injection:autowiring] segítségével paraméterként átadjuk a gyári metódusnak: @@ -663,7 +663,7 @@ A szeparált használat alatt a router képességeinek olyan alkalmazásban tör Tehát ismét létrehozunk egy metódust, amely létrehoz egy útválasztót, például: ```php -namespace App\Router; +namespace App\Core; use Nette\Routing\RouteList; @@ -694,7 +694,7 @@ $httpRequest = $container->getByType(Nette\Http\IRequest::class); Vagy közvetlenül hozzuk létre az objektumokat: ```php -$router = App\Router\RouterFactory::createRouter(); +$router = App\Core\RouterFactory::createRouter(); $httpRequest = (new Nette\Http\RequestFactory)->fromGlobals(); ``` diff --git a/application/it/routing.texy b/application/it/routing.texy index c01d4ac823..128e2edf26 100644 --- a/application/it/routing.texy +++ b/application/it/routing.texy @@ -477,10 +477,10 @@ $router->addRoute('index', /* ... */); Integrazione .[#toc-integration] ================================ -Per collegare il nostro router all'applicazione, dobbiamo comunicarlo al contenitore DI. Il modo più semplice è preparare il factory che costruirà l'oggetto router e dire al contenitore di configurazione di usarlo. Diciamo quindi di scrivere un metodo a questo scopo `App\Router\RouterFactory::createRouter()`: +Per collegare il nostro router all'applicazione, dobbiamo comunicarlo al contenitore DI. Il modo più semplice è preparare il factory che costruirà l'oggetto router e dire al contenitore di configurazione di usarlo. Diciamo quindi di scrivere un metodo a questo scopo `App\Core\RouterFactory::createRouter()`: ```php -namespace App\Router; +namespace App\Core; use Nette\Application\Routers\RouteList; @@ -499,7 +499,7 @@ Poi scriviamo nella [configurazione |dependency-injection:services]: ```neon services: - - App\Router\RouterFactory::createRouter + - App\Core\RouterFactory::createRouter ``` Tutte le dipendenze, come la connessione al database, ecc. vengono passate al metodo factory come parametri, utilizzando l'[autowiring |dependency-injection:autowiring]: @@ -663,7 +663,7 @@ Per uso separato si intende l'uso delle funzionalità del router in un'applicazi Quindi creeremo di nuovo un metodo che costruirà un router, ad esempio: ```php -namespace App\Router; +namespace App\Core; use Nette\Routing\RouteList; @@ -694,7 +694,7 @@ $httpRequest = $container->getByType(Nette\Http\IRequest::class); Oppure creeremo direttamente gli oggetti: ```php -$router = App\Router\RouterFactory::createRouter(); +$router = App\Core\RouterFactory::createRouter(); $httpRequest = (new Nette\Http\RequestFactory)->fromGlobals(); ``` diff --git a/application/pl/routing.texy b/application/pl/routing.texy index 4ce1af8644..699114b6e0 100644 --- a/application/pl/routing.texy +++ b/application/pl/routing.texy @@ -477,10 +477,10 @@ $router->addRoute('index', /* ... */); Integracja aplikacji .[#toc-integration] ======================================== -Aby zintegrować stworzony router z aplikacją, musimy powiedzieć o nim kontenerowi DI. Najprostszym sposobem na to jest przygotowanie fabryki tworzącej obiekt routera i powiedzenie konfiguracji kontenera, aby go użyć. Załóżmy, że w tym celu napiszemy metodę `App\Router\RouterFactory::createRouter()`: +Aby zintegrować stworzony router z aplikacją, musimy powiedzieć o nim kontenerowi DI. Najprostszym sposobem na to jest przygotowanie fabryki tworzącej obiekt routera i powiedzenie konfiguracji kontenera, aby go użyć. Załóżmy, że w tym celu napiszemy metodę `App\Core\RouterFactory::createRouter()`: ```php -namespace App\Router; +namespace App\Core; use Nette\Application\Routers\RouteList; @@ -499,7 +499,7 @@ Następnie wpisujemy do [konfiguracji |dependency-injection:services]: ```neon services: - - App\Router\RouterFactory::createRouter + - App\Core\RouterFactory::createRouter ``` Wszelkie zależności, na przykład od bazy danych itp, są przekazywane do metody fabrycznej jako jej parametry przez [autowiring |dependency-injection:autowiring]: @@ -663,7 +663,7 @@ Przez użycie samodzielne rozumiemy wykorzystanie możliwości routera w aplikac Czyli znowu tworzymy metodę, która buduje dla nas np. router: ```php -namespace App\Router; +namespace App\Core; use Nette\Routing\RouteList; @@ -694,7 +694,7 @@ $httpRequest = $container->getByType(Nette\Http\IRequest::class); Możemy też wykonać obiekty bezpośrednio: ```php -$router = App\Router\RouterFactory::createRouter(); +$router = App\Core\RouterFactory::createRouter(); $httpRequest = (new Nette\Http\RequestFactory)->fromGlobals(); ``` diff --git a/application/pt/routing.texy b/application/pt/routing.texy index 6caf887e2d..d9c249abe6 100644 --- a/application/pt/routing.texy +++ b/application/pt/routing.texy @@ -477,10 +477,10 @@ $router->addRoute('index', /* ... */); Integração .[#toc-integration] ============================== -A fim de conectar nosso roteador à aplicação, devemos informar o recipiente DI sobre isso. A maneira mais fácil é preparar a fábrica que irá construir o objeto roteador e dizer à configuração do contêiner para usá-lo. Portanto, digamos que escrevemos um método para este fim `App\Router\RouterFactory::createRouter()`: +A fim de conectar nosso roteador à aplicação, devemos informar o recipiente DI sobre isso. A maneira mais fácil é preparar a fábrica que irá construir o objeto roteador e dizer à configuração do contêiner para usá-lo. Portanto, digamos que escrevemos um método para este fim `App\Core\RouterFactory::createRouter()`: ```php -namespace App\Router; +namespace App\Core; use Nette\Application\Routers\RouteList; @@ -499,7 +499,7 @@ Em seguida, escrevemos em [configuração |dependency-injection:services]: ```neon services: - - App\Router\RouterFactory::createRouter + - App\Core\RouterFactory::createRouter ``` Quaisquer dependências, tais como uma conexão de banco de dados, etc., são passadas para o método de fábrica como seus parâmetros usando [a fiação automática |dependency-injection:autowiring]: @@ -663,7 +663,7 @@ Por uso separado, entendemos o uso das capacidades do roteador em uma aplicaçã Assim, mais uma vez, criaremos um método que construirá um roteador, por exemplo: ```php -namespace App\Router; +namespace App\Core; use Nette\Routing\RouteList; @@ -694,7 +694,7 @@ $httpRequest = $container->getByType(Nette\Http\IRequest::class); Ou criaremos objetos diretamente: ```php -$router = App\Router\RouterFactory::createRouter(); +$router = App\Core\RouterFactory::createRouter(); $httpRequest = (new Nette\Http\RequestFactory)->fromGlobals(); ``` diff --git a/application/ro/routing.texy b/application/ro/routing.texy index 4f80ca99be..125ac60d22 100644 --- a/application/ro/routing.texy +++ b/application/ro/routing.texy @@ -477,10 +477,10 @@ $router->addRoute('index', /* ... */); Integrare .[#toc-integration] ============================= -Pentru a conecta routerul nostru la aplicație, trebuie să informăm containerul DI despre acesta. Cel mai simplu este să pregătim fabrica care va construi obiectul router și să spunem configurației containerului să o folosească. Să spunem că scriem o metodă în acest scop `App\Router\RouterFactory::createRouter()`: +Pentru a conecta routerul nostru la aplicație, trebuie să informăm containerul DI despre acesta. Cel mai simplu este să pregătim fabrica care va construi obiectul router și să spunem configurației containerului să o folosească. Să spunem că scriem o metodă în acest scop `App\Core\RouterFactory::createRouter()`: ```php -namespace App\Router; +namespace App\Core; use Nette\Application\Routers\RouteList; @@ -499,7 +499,7 @@ Apoi scriem în [configurație |dependency-injection:services]: ```neon services: - - App\Router\RouterFactory::createRouter + - App\Core\RouterFactory::createRouter ``` Orice dependență, cum ar fi o conexiune la o bază de date etc., este transmisă metodei factory ca parametru al acesteia folosind [autowiring |dependency-injection:autowiring]: @@ -663,7 +663,7 @@ Prin utilizare separată se înțelege utilizarea capacităților routerului în Deci, din nou, vom crea o metodă care va construi un router, de exemplu: ```php -namespace App\Router; +namespace App\Core; use Nette\Routing\RouteList; @@ -694,7 +694,7 @@ $httpRequest = $container->getByType(Nette\Http\IRequest::class); Sau vom crea obiecte direct: ```php -$router = App\Router\RouterFactory::createRouter(); +$router = App\Core\RouterFactory::createRouter(); $httpRequest = (new Nette\Http\RequestFactory)->fromGlobals(); ``` diff --git a/application/ru/routing.texy b/application/ru/routing.texy index dd37c4fd4d..0e90a2aca6 100644 --- a/application/ru/routing.texy +++ b/application/ru/routing.texy @@ -477,10 +477,10 @@ $router->addRoute('index', /* ... */); Интеграция .[#toc-integration] ============================== -Чтобы подключить наш маршрутизатор к приложению, мы должны сообщить о нем контейнеру DI. Самый простой способ - это подготовить фабрику, которая будет создавать объект маршрутизатора, и сообщить конфигурации контейнера, чтобы она его использовала. Допустим, мы напишем для этого метод `App\Router\RouterFactory::createRouter()`: +Чтобы подключить наш маршрутизатор к приложению, мы должны сообщить о нем контейнеру DI. Самый простой способ - это подготовить фабрику, которая будет создавать объект маршрутизатора, и сообщить конфигурации контейнера, чтобы она его использовала. Допустим, мы напишем для этого метод `App\Core\RouterFactory::createRouter()`: ```php -namespace App\Router; +namespace App\Core; use Nette\Application\Routers\RouteList; @@ -499,7 +499,7 @@ class RouterFactory ```neon services: - - App\Router\RouterFactory::createRouter + - App\Core\RouterFactory::createRouter ``` Любые зависимости, такие как подключение к базе данных и т.д., передаются методу фабрики в качестве параметров с помощью [autowiring |dependency-injection:autowiring]: @@ -663,7 +663,7 @@ $router->addRoute(/* ... */); Итак, мы снова добавим метод, который будет создавать, например, маршрутизатор: ```php -namespace App\Router; +namespace App\Core; use Nette\Routing\RouteList; @@ -694,7 +694,7 @@ $httpRequest = $container->getByType(Nette\Http\IRequest::class); Или мы будем создавать объекты напрямую: ```php -$router = App\Router\RouterFactory::createRouter(); +$router = App\Core\RouterFactory::createRouter(); $httpRequest = (new Nette\Http\RequestFactory)->fromGlobals(); ``` diff --git a/application/sl/routing.texy b/application/sl/routing.texy index 0f717178bb..6430a8c631 100644 --- a/application/sl/routing.texy +++ b/application/sl/routing.texy @@ -477,10 +477,10 @@ $router->addRoute('index', /* ... */); Integracija .[#toc-integration] =============================== -Da bi naš usmerjevalnik povezali z aplikacijo, moramo o tem obvestiti vsebnik DI. Najlažje je pripraviti tovarno, ki bo zgradila objekt usmerjevalnika, in povedati konfiguraciji vsebnika, naj jo uporabi. Recimo, da v ta namen napišemo metodo `App\Router\RouterFactory::createRouter()`: +Da bi naš usmerjevalnik povezali z aplikacijo, moramo o tem obvestiti vsebnik DI. Najlažje je pripraviti tovarno, ki bo zgradila objekt usmerjevalnika, in povedati konfiguraciji vsebnika, naj jo uporabi. Recimo, da v ta namen napišemo metodo `App\Core\RouterFactory::createRouter()`: ```php -namespace App\Router; +namespace App\Core; use Nette\Application\Routers\RouteList; @@ -499,7 +499,7 @@ Nato zapišemo v [konfiguracijo |dependency-injection:services]: ```neon services: - - App\Router\RouterFactory::createRouter + - App\Core\RouterFactory::createRouter ``` Vse odvisnosti, kot je povezava s podatkovno bazo itd., se metodi tovarne posredujejo kot njeni parametri z uporabo [samodejnega povezovanja |dependency-injection:autowiring]: @@ -663,7 +663,7 @@ Z ločeno uporabo mislimo na uporabo zmožnosti usmerjevalnika v aplikaciji, ki Tako bomo ponovno ustvarili metodo, ki bo zgradila usmerjevalnik, na primer: ```php -namespace App\Router; +namespace App\Core; use Nette\Routing\RouteList; @@ -694,7 +694,7 @@ $httpRequest = $container->getByType(Nette\Http\IRequest::class); Ali pa bomo predmete ustvarili neposredno: ```php -$router = App\Router\RouterFactory::createRouter(); +$router = App\Core\RouterFactory::createRouter(); $httpRequest = (new Nette\Http\RequestFactory)->fromGlobals(); ``` diff --git a/application/tr/routing.texy b/application/tr/routing.texy index cbd1656234..d298997568 100644 --- a/application/tr/routing.texy +++ b/application/tr/routing.texy @@ -477,10 +477,10 @@ $router->addRoute('index', /* ... */); Entegrasyon .[#toc-integration] =============================== -Yönlendiricimizi uygulamaya bağlamak için DI konteynerine bunu söylemeliyiz. Bunun en kolay yolu router nesnesini oluşturacak fabrikayı hazırlamak ve container konfigürasyonuna bunu kullanmasını söylemektir. Diyelim ki bu amaçla bir metot yazdık `App\Router\RouterFactory::createRouter()`: +Yönlendiricimizi uygulamaya bağlamak için DI konteynerine bunu söylemeliyiz. Bunun en kolay yolu router nesnesini oluşturacak fabrikayı hazırlamak ve container konfigürasyonuna bunu kullanmasını söylemektir. Diyelim ki bu amaçla bir metot yazdık `App\Core\RouterFactory::createRouter()`: ```php -namespace App\Router; +namespace App\Core; use Nette\Application\Routers\RouteList; @@ -499,7 +499,7 @@ Daha sonra [yapılandırmaya |dependency-injection:services] yazıyoruz: ```neon services: - - App\Router\RouterFactory::createRouter + - App\Core\RouterFactory::createRouter ``` Veritabanı bağlantısı vb. gibi tüm bağımlılıklar, [otomatik |dependency-injection:autowiring] bağlantı kullanılarak fabrika yöntemine parametreleri olarak aktarılır: @@ -663,7 +663,7 @@ Ayrı kullanımla, yönlendiricinin yeteneklerinin Nette Uygulaması ve sunucula Bu yüzden yine örneğin bir yönlendirici oluşturacak bir yöntem oluşturacağız: ```php -namespace App\Router; +namespace App\Core; use Nette\Routing\RouteList; @@ -694,7 +694,7 @@ $httpRequest = $container->getByType(Nette\Http\IRequest::class); Ya da doğrudan nesneler oluşturacağız: ```php -$router = App\Router\RouterFactory::createRouter(); +$router = App\Core\RouterFactory::createRouter(); $httpRequest = (new Nette\Http\RequestFactory)->fromGlobals(); ``` diff --git a/application/uk/routing.texy b/application/uk/routing.texy index c19046885b..f270ca67fd 100644 --- a/application/uk/routing.texy +++ b/application/uk/routing.texy @@ -477,10 +477,10 @@ $router->addRoute('index', /* ... */); Інтеграція .[#toc-integration] ============================== -Щоб підключити наш маршрутизатор до застосунку, ми повинні повідомити про нього контейнер DI. Найпростіший спосіб - це підготувати фабрику, яка буде створювати об'єкт маршрутизатора, і повідомити конфігурацію контейнера, щоб вона його використовувала. Припустимо, ми напишемо для цього метод `App\Router\RouterFactory::createRouter()`: +Щоб підключити наш маршрутизатор до застосунку, ми повинні повідомити про нього контейнер DI. Найпростіший спосіб - це підготувати фабрику, яка буде створювати об'єкт маршрутизатора, і повідомити конфігурацію контейнера, щоб вона його використовувала. Припустимо, ми напишемо для цього метод `App\Core\RouterFactory::createRouter()`: ```php -namespace App\Router; +namespace App\Core; use Nette\Application\Routers\RouteList; @@ -499,7 +499,7 @@ class RouterFactory ```neon services: - - App\Router\RouterFactory::createRouter + - App\Core\RouterFactory::createRouter ``` Будь-які залежності, такі як підключення до бази даних тощо, передаються методу фабрики як параметри за допомогою [autowiring |dependency-injection:autowiring]: @@ -663,7 +663,7 @@ $router->addRoute(/* ... */); Отже, ми знову додамо метод, який буде створювати, наприклад, маршрутизатор: ```php -namespace App\Router; +namespace App\Core; use Nette\Routing\RouteList; @@ -694,7 +694,7 @@ $httpRequest = $container->getByType(Nette\Http\IRequest::class); Або ми будемо створювати об'єкти безпосередньо: ```php -$router = App\Router\RouterFactory::createRouter(); +$router = App\Core\RouterFactory::createRouter(); $httpRequest = (new Nette\Http\RequestFactory)->fromGlobals(); ``` diff --git a/best-practices/bg/composer.texy b/best-practices/bg/composer.texy index 13bf7df4cc..2852264f64 100644 --- a/best-practices/bg/composer.texy +++ b/best-practices/bg/composer.texy @@ -189,7 +189,7 @@ Packagist.org - глобално хранилище .[#toc-packagist-org-global- Впоследствие трябва да стартирате командата `composer dumpautoload` при всяка промяна и да позволите на таблиците на автоматичния модул да се възстановят. Това е изключително неудобно и е много по-добре да оставите тази задача на [RobotLoader |robot-loader:], който върши същата работа автоматично във фонов режим и много по-бързо. -Вторият вариант е да следвате [PSR-4 |https://www.php-fig.org/psr/psr-4/]. Казано по-просто, това е система, в която пространствата от имена и имената на класовете съответстват на структурата на директориите и имената на файловете, т.е. `App\Router\RouterFactory` се намира в `/path/to/App/Router/RouterFactory.php`. Примерна конфигурация: +Вторият вариант е да следвате [PSR-4 |https://www.php-fig.org/psr/psr-4/]. Казано по-просто, това е система, в която пространствата от имена и имената на класовете съответстват на структурата на директориите и имената на файловете, т.е. `App\Core\RouterFactory` се намира в `/path/to/App/Core/RouterFactory.php`. Примерна конфигурация: ```js { diff --git a/best-practices/bg/lets-create-contact-form.texy b/best-practices/bg/lets-create-contact-form.texy index b0f3d7ccf6..80a29d0e4e 100644 --- a/best-practices/bg/lets-create-contact-form.texy +++ b/best-practices/bg/lets-create-contact-form.texy @@ -39,7 +39,7 @@ class HomePresenter extends Presenter Но какво ще стане, ако потребителят не попълни някои полета? В такъв случай трябва да го уведомим, че това е задължително поле. Направихме това с метода `setRequired()`. Накрая добавихме и [събитие |nette:glossary#events] `onSuccess`, което се задейства, ако формулярът е изпратен успешно. В нашия случай то извиква метода `contactFormSucceeded`, който се грижи за обработката на изпратения формуляр. След малко ще добавим това към кода. -Нека компонентът `contantForm` бъде визуализиран в шаблона `templates/Home/default.latte`: +Нека компонентът `contantForm` бъде визуализиран в шаблона `Home/default.latte`: ```latte {block content} diff --git a/best-practices/bg/pagination.texy b/best-practices/bg/pagination.texy index 28256dd731..b3621af913 100644 --- a/best-practices/bg/pagination.texy +++ b/best-practices/bg/pagination.texy @@ -11,7 +11,6 @@ namespace App\Model; use Nette; - class ArticleRepository { public function __construct( @@ -34,7 +33,7 @@ class ArticleRepository След това въвеждаме класа на модела в презентатора и в метода `render` правим справка за публикуваните статии, които предаваме на шаблона: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; @@ -53,7 +52,7 @@ class HomePresenter extends Nette\Application\UI\Presenter } ``` -В шаблона се грижим за извеждането на списъка със статии: +След това шаблонът `default.latte` ще се погрижи за изброяването на статиите: ```latte {block content} @@ -114,7 +113,7 @@ class ArticleRepository Също така разширяваме метода `render`, за да получим инстанцията Paginator, да я конфигурираме и да изберем желаните статии, които да се показват в шаблона. HomePresenter ще изглежда по следния начин: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; @@ -190,7 +189,6 @@ namespace App\Model; use Nette; - class ArticleRepository { public function __construct( @@ -210,7 +208,7 @@ class ArticleRepository Не е необходимо да създаваме Paginator в презентатора, вместо това ще използваме метода на обекта `Selection`, върнат от хранилището: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; diff --git a/best-practices/cs/composer.texy b/best-practices/cs/composer.texy index 9ac10dc558..8ea7581472 100644 --- a/best-practices/cs/composer.texy +++ b/best-practices/cs/composer.texy @@ -189,7 +189,7 @@ Nicméně je možné používat Composer i pro načítání dalších tříd i m Následně je potřeba při každé změně spustit příkaz `composer dumpautoload` a nechat autoloadovací tabulky přegenerovat. To je nesmírně nepohodlné a daleko lepší je tento úkol svěřit [RobotLoaderu|robot-loader:], který stejnou činnost provádí automaticky na pozadí a mnohem rychleji. -Druhou možností je dodržovat [PSR-4|https://www.php-fig.org/psr/psr-4/]. Zjednodušeně řečeno jde o systém, kdy jmenné prostory a názvy tříd odpovídají adresářové struktuře a názvům souborů, tedy např. `App\Router\RouterFactory` bude v souboru `/path/to/App/Router/RouterFactory.php`. Příklad konfigurace: +Druhou možností je dodržovat [PSR-4|https://www.php-fig.org/psr/psr-4/]. Zjednodušeně řečeno jde o systém, kdy jmenné prostory a názvy tříd odpovídají adresářové struktuře a názvům souborů, tedy např. `App\Core\RouterFactory` bude v souboru `/path/to/App/Core/RouterFactory.php`. Příklad konfigurace: ```js { diff --git a/best-practices/cs/lets-create-contact-form.texy b/best-practices/cs/lets-create-contact-form.texy index 78f2f92886..80503acf55 100644 --- a/best-practices/cs/lets-create-contact-form.texy +++ b/best-practices/cs/lets-create-contact-form.texy @@ -39,7 +39,7 @@ Jak vidíte, vytvořili jsme dvě metody. První metoda `createComponentContactF Ale co když uživatel nevyplní nějaké pole? V takovém případě bychom mu měli dát vědět, že je to povinné pole. Toho jsme docílili metodou `setRequired()`. Nakonec jsme přidali také [událost |nette:glossary#Události] `onSuccess`, která se spustí, pokud je formulář úspěšně odeslán. V našem případě zavolá metodu `contactFormSucceeded`, která se postará o zpracování odeslaného formuláře. To do kódu doplníme za okamžik. -Komponentu `contantForm` necháme vykreslit v šabloně `templates/Home/default.latte`: +Komponentu `contantForm` necháme vykreslit v šabloně `Home/default.latte`: ```latte {block content} diff --git a/best-practices/cs/pagination.texy b/best-practices/cs/pagination.texy index bf7d18a418..2f7e473131 100644 --- a/best-practices/cs/pagination.texy +++ b/best-practices/cs/pagination.texy @@ -11,7 +11,6 @@ namespace App\Model; use Nette; - class ArticleRepository { public function __construct( @@ -34,7 +33,7 @@ class ArticleRepository V presenteru si pak injectujeme modelovou třídu a v render metodě si vyžádáme publikované články, které předáme do šablony: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; @@ -53,7 +52,7 @@ class HomePresenter extends Nette\Application\UI\Presenter } ``` -V šabloně se pak postaráme o výpis článků: +V šabloně `default.latte` se pak postaráme o výpis článků: ```latte {block content} @@ -114,7 +113,7 @@ Následně se pustíme do úprav presenteru. Do render metody budeme předávat Dále také render metodu rozšíříme o získání instance Paginatoru, jeho nastavení a výběru správných článků pro zobrazení v šabloně. HomePresenter bude po úpravách vypadat takto: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; @@ -190,7 +189,6 @@ namespace App\Model; use Nette; - class ArticleRepository { public function __construct( @@ -210,7 +208,7 @@ class ArticleRepository V presenteru nemusíme vytvářet Paginator, použijeme místo něj metodu třídy `Selection`, kterou nám vrací repositář: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; diff --git a/best-practices/de/composer.texy b/best-practices/de/composer.texy index 8910b9e603..10aed8c202 100644 --- a/best-practices/de/composer.texy +++ b/best-practices/de/composer.texy @@ -189,7 +189,7 @@ Es ist jedoch auch möglich, Composer zu verwenden, um andere Klassen außerhalb Anschließend müssen Sie bei jeder Änderung den Befehl `composer dumpautoload` ausführen und die Autoloader-Tabellen neu generieren lassen. Dies ist äußerst lästig, und es ist weitaus besser, diese Aufgabe [RobotLoader |robot-loader:] anzuvertrauen, der dieselbe Tätigkeit automatisch im Hintergrund und viel schneller durchführt. -Die zweite Möglichkeit ist, [PSR-4 |https://www.php-fig.org/psr/psr-4/] zu folgen. Einfach gesagt handelt es sich um ein System, bei dem die Namensräume und Klassennamen der Verzeichnisstruktur und den Dateinamen entsprechen, d. h. `App\Router\RouterFactory` befindet sich in der Datei `/path/to/App/Router/RouterFactory.php`. Beispiel für eine Konfiguration: +Die zweite Möglichkeit ist, [PSR-4 |https://www.php-fig.org/psr/psr-4/] zu folgen. Einfach gesagt handelt es sich um ein System, bei dem die Namensräume und Klassennamen der Verzeichnisstruktur und den Dateinamen entsprechen, d. h. `App\Core\RouterFactory` befindet sich in der Datei `/path/to/App/Core/RouterFactory.php`. Beispiel für eine Konfiguration: ```js { diff --git a/best-practices/de/lets-create-contact-form.texy b/best-practices/de/lets-create-contact-form.texy index 67b26710b2..886b452767 100644 --- a/best-practices/de/lets-create-contact-form.texy +++ b/best-practices/de/lets-create-contact-form.texy @@ -39,7 +39,7 @@ Wie Sie sehen können, haben wir zwei Methoden erstellt. Die erste Methode `crea Was aber, wenn der Benutzer einige Felder nicht ausfüllt? In diesem Fall sollten wir ihn darauf hinweisen, dass es sich um ein Pflichtfeld handelt. Wir haben dies mit der Methode `setRequired()` getan. Schließlich haben wir auch ein [Ereignis |nette:glossary#events] `onSuccess` hinzugefügt, das ausgelöst wird, wenn das Formular erfolgreich abgeschickt wurde. In unserem Fall ruft es die Methode `contactFormSucceeded` auf, die sich um die Verarbeitung des übermittelten Formulars kümmert. Das fügen wir dem Code gleich hinzu. -Die Komponente `contantForm` soll in der Vorlage `templates/Home/default.latte` gerendert werden: +Die Komponente `contantForm` soll in der Vorlage `Home/default.latte` gerendert werden: ```latte {block content} diff --git a/best-practices/de/pagination.texy b/best-practices/de/pagination.texy index ef5a0920ad..20d4cf9349 100644 --- a/best-practices/de/pagination.texy +++ b/best-practices/de/pagination.texy @@ -11,7 +11,6 @@ namespace App\Model; use Nette; - class ArticleRepository { public function __construct( @@ -34,7 +33,7 @@ class ArticleRepository In den Presenter injizieren wir dann die Modellklasse, und in der Rendering-Methode fragen wir nach den veröffentlichten Artikeln, die wir an die Vorlage übergeben: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; @@ -53,7 +52,7 @@ class HomePresenter extends Nette\Application\UI\Presenter } ``` -In der Vorlage kümmern wir uns um das Rendern einer Artikelliste: +Die Vorlage `default.latte` kümmert sich dann um die Auflistung der Artikel: ```latte {block content} @@ -114,7 +113,7 @@ Der nächste Schritt besteht darin, den Präsentator zu bearbeiten. Wir werden d Wir erweitern die Render-Methode auch, um die Paginator-Instanz zu erhalten, sie einzurichten und die richtigen Artikel für die Anzeige in der Vorlage auszuwählen. Der HomePresenter wird wie folgt aussehen: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; @@ -190,7 +189,6 @@ namespace App\Model; use Nette; - class ArticleRepository { public function __construct( @@ -210,7 +208,7 @@ class ArticleRepository Wir müssen keinen Paginator im Presenter erstellen, sondern verwenden die Methode des `Selection` -Objekts, das vom Repository zurückgegeben wird: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; diff --git a/best-practices/el/composer.texy b/best-practices/el/composer.texy index 410b88c45a..75f9e3f0bc 100644 --- a/best-practices/el/composer.texy +++ b/best-practices/el/composer.texy @@ -189,7 +189,7 @@ Packagist.org - Παγκόσμιο αποθετήριο .[#toc-packagist-org-glo Στη συνέχεια, είναι απαραίτητο να εκτελείτε την εντολή `composer dumpautoload` με κάθε αλλαγή και να αφήνετε τους πίνακες αυτόματης φόρτωσης να αναγεννώνται. Αυτό είναι εξαιρετικά άβολο και είναι πολύ καλύτερο να αναθέσετε αυτή την εργασία στο [RobotLoader |robot-loader:], το οποίο εκτελεί την ίδια δραστηριότητα αυτόματα στο παρασκήνιο και πολύ πιο γρήγορα. -Η δεύτερη επιλογή είναι να ακολουθήσετε το [PSR-4 |https://www.php-fig.org/psr/psr-4/]. Με απλά λόγια, πρόκειται για ένα σύστημα όπου τα namespaces και τα ονόματα των κλάσεων αντιστοιχούν στη δομή των καταλόγων και των ονομάτων των αρχείων, δηλαδή το `App\Router\RouterFactory` βρίσκεται στο αρχείο `/path/to/App/Router/RouterFactory.php`. Παράδειγμα διαμόρφωσης: +Η δεύτερη επιλογή είναι να ακολουθήσετε το [PSR-4 |https://www.php-fig.org/psr/psr-4/]. Με απλά λόγια, πρόκειται για ένα σύστημα όπου τα namespaces και τα ονόματα των κλάσεων αντιστοιχούν στη δομή των καταλόγων και των ονομάτων των αρχείων, δηλαδή το `App\Core\RouterFactory` βρίσκεται στο αρχείο `/path/to/App/Core/RouterFactory.php`. Παράδειγμα διαμόρφωσης: ```js { diff --git a/best-practices/el/lets-create-contact-form.texy b/best-practices/el/lets-create-contact-form.texy index aeded4979a..8cf6ab9a9f 100644 --- a/best-practices/el/lets-create-contact-form.texy +++ b/best-practices/el/lets-create-contact-form.texy @@ -39,7 +39,7 @@ class HomePresenter extends Presenter Τι γίνεται όμως αν ο χρήστης δεν συμπληρώσει κάποια πεδία; Σε αυτή την περίπτωση, θα πρέπει να τον ενημερώσουμε ότι πρόκειται για υποχρεωτικό πεδίο. Αυτό το κάναμε με τη μέθοδο `setRequired()`. Τέλος, προσθέσαμε και ένα [συμβάν |nette:glossary#events] `onSuccess`, το οποίο ενεργοποιείται αν η φόρμα υποβληθεί με επιτυχία. Στην περίπτωσή μας, καλεί τη μέθοδο `contactFormSucceeded`, η οποία αναλαμβάνει την επεξεργασία της υποβληθείσας φόρμας. Θα το προσθέσουμε αυτό στον κώδικα σε λίγο. -Αφήστε το στοιχείο `contantForm` να αποδοθεί στο πρότυπο `templates/Home/default.latte`: +Αφήστε το στοιχείο `contantForm` να αποδοθεί στο πρότυπο `Home/default.latte`: ```latte {block content} diff --git a/best-practices/el/pagination.texy b/best-practices/el/pagination.texy index 06fca7da8a..ee67e769f6 100644 --- a/best-practices/el/pagination.texy +++ b/best-practices/el/pagination.texy @@ -11,7 +11,6 @@ namespace App\Model; use Nette; - class ArticleRepository { public function __construct( @@ -34,7 +33,7 @@ class ArticleRepository Στον Presenter στη συνέχεια εισάγουμε την κλάση model και στη μέθοδο render θα ζητήσουμε τα δημοσιευμένα άρθρα που θα περάσουμε στο template: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; @@ -53,7 +52,7 @@ class HomePresenter extends Nette\Application\UI\Presenter } ``` -Στο πρότυπο, θα φροντίσουμε για την απόδοση μιας λίστας άρθρων: +Το πρότυπο `default.latte` θα αναλάβει στη συνέχεια την καταχώριση των άρθρων: ```latte {block content} @@ -114,7 +113,7 @@ class ArticleRepository Επεκτείνουμε επίσης τη μέθοδο render για να λάβουμε την περίπτωση Paginator, να τη ρυθμίσουμε και να επιλέξουμε τα σωστά άρθρα που θα εμφανίζονται στο πρότυπο. Το HomePresenter θα μοιάζει με αυτό: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; @@ -190,7 +189,6 @@ namespace App\Model; use Nette; - class ArticleRepository { public function __construct( @@ -210,7 +208,7 @@ class ArticleRepository Δεν χρειάζεται να δημιουργήσουμε Paginator στο Presenter, αντίθετα θα χρησιμοποιήσουμε τη μέθοδο του αντικειμένου `Selection` που επιστρέφεται από το αποθετήριο: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; diff --git a/best-practices/en/composer.texy b/best-practices/en/composer.texy index bc65bb1c55..d8753b98bd 100644 --- a/best-practices/en/composer.texy +++ b/best-practices/en/composer.texy @@ -189,7 +189,7 @@ However, it is also possible to use Composer to load other classes outside the f Subsequently, it is necessary to run the command `composer dumpautoload` with each change and let the autoloading tables regenerate. This is extremely inconvenient, and it is far better to entrust this task to [RobotLoader|robot-loader:], which performs the same activity automatically in the background and much faster. -The second option is to follow [PSR-4 |https://www.php-fig.org/psr/psr-4/]. Simply saying, it is a system where the namespaces and class names correspond to the directory structure and file names, ie `App\Router\RouterFactory` is located in the file `/path/to/App/Router/RouterFactory.php`. Configuration example: +The second option is to follow [PSR-4 |https://www.php-fig.org/psr/psr-4/]. Simply saying, it is a system where the namespaces and class names correspond to the directory structure and file names, ie `App\Core\RouterFactory` is located in the file `/path/to/App/Core/RouterFactory.php`. Configuration example: ```js { diff --git a/best-practices/en/lets-create-contact-form.texy b/best-practices/en/lets-create-contact-form.texy index ad2472ed15..f00cad1b75 100644 --- a/best-practices/en/lets-create-contact-form.texy +++ b/best-practices/en/lets-create-contact-form.texy @@ -39,7 +39,7 @@ As you can see, we have created two methods. The first method `createComponentCo But what if the user doesn't fill in some fields? In that case, we should let him know that it is a required field. We did this with the `setRequired()` method. Finally, we also added an [event |nette:glossary#events] `onSuccess`, which is triggered if the form is submitted successfully. In our case, it calls the `contactFormSucceeded` method , which takes care of processing the submitted form. We'll add that to the code in a moment. -Let the `contantForm` component be rendered in the `templates/Home/default.latte` template: +Let the `contantForm` component be rendered in the `Home/default.latte` template: ```latte {block content} diff --git a/best-practices/en/pagination.texy b/best-practices/en/pagination.texy index 113ce80193..f8ad2de0e1 100644 --- a/best-practices/en/pagination.texy +++ b/best-practices/en/pagination.texy @@ -11,7 +11,6 @@ namespace App\Model; use Nette; - class ArticleRepository { public function __construct( @@ -34,7 +33,7 @@ class ArticleRepository In the Presenter we then inject the model class and in the render method we will ask for the published articles that we pass to the template: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; @@ -53,7 +52,7 @@ class HomePresenter extends Nette\Application\UI\Presenter } ``` -In the template, we will take care of rendering an articles list: +The `default.latte` template will then take care of listing the articles: ```latte {block content} @@ -114,7 +113,7 @@ The next step is to edit the presenter. We will forward the number of the curren We also expand the render method to get the Paginator instance, setting it up, and selecting the correct articles to display in the template. HomePresenter will look like this: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; @@ -190,7 +189,6 @@ namespace App\Model; use Nette; - class ArticleRepository { public function __construct( @@ -210,7 +208,7 @@ class ArticleRepository We do not have to create Paginator in the Presenter, instead we will use the method of `Selection` object returned by the repository: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; diff --git a/best-practices/es/composer.texy b/best-practices/es/composer.texy index e9fd4a1bf3..86cf99808a 100644 --- a/best-practices/es/composer.texy +++ b/best-practices/es/composer.texy @@ -189,7 +189,7 @@ Sin embargo, también es posible utilizar Composer para cargar otras clases fuer Posteriormente, es necesario ejecutar el comando `composer dumpautoload` con cada cambio y dejar que se regeneren las tablas de autocarga. Esto es extremadamente incómodo, y es mucho mejor confiar esta tarea a [RobotLoader |robot-loader:], que realiza la misma actividad automáticamente en segundo plano y mucho más rápido. -La segunda opción es seguir [PSR-4 |https://www.php-fig.org/psr/psr-4/]. En pocas palabras, se trata de un sistema en el que los espacios de nombres y los nombres de las clases se corresponden con la estructura de directorios y los nombres de los archivos, es decir, `App\Router\RouterFactory` se encuentra en el archivo `/path/to/App/Router/RouterFactory.php`. Ejemplo de configuración: +La segunda opción es seguir [PSR-4 |https://www.php-fig.org/psr/psr-4/]. En pocas palabras, se trata de un sistema en el que los espacios de nombres y los nombres de las clases se corresponden con la estructura de directorios y los nombres de los archivos, es decir, `App\Core\RouterFactory` se encuentra en el archivo `/path/to/App/Core/RouterFactory.php`. Ejemplo de configuración: ```js { diff --git a/best-practices/es/lets-create-contact-form.texy b/best-practices/es/lets-create-contact-form.texy index 2c7e155167..142740037a 100644 --- a/best-practices/es/lets-create-contact-form.texy +++ b/best-practices/es/lets-create-contact-form.texy @@ -39,7 +39,7 @@ Como puedes ver, hemos creado dos métodos. El primer método `createComponentCo Pero, ¿qué pasa si el usuario no rellena algunos campos? En ese caso, debemos hacerle saber que se trata de un campo obligatorio. Hicimos esto con el método `setRequired()`. Por último, también añadimos un [evento |nette:glossary#events] `onSuccess`, que se activa si el formulario se envía correctamente. En nuestro caso, llama al método `contactFormSucceeded`, que se encarga de procesar el formulario enviado. Lo añadiremos al código en un momento. -Dejemos que el componente `contantForm` sea renderizado en la plantilla `templates/Home/default.latte`: +Dejemos que el componente `contantForm` sea renderizado en la plantilla `Home/default.latte`: ```latte {block content} diff --git a/best-practices/es/pagination.texy b/best-practices/es/pagination.texy index 44d6fddd5f..18df6c7906 100644 --- a/best-practices/es/pagination.texy +++ b/best-practices/es/pagination.texy @@ -11,7 +11,6 @@ namespace App\Model; use Nette; - class ArticleRepository { public function __construct( @@ -34,7 +33,7 @@ class ArticleRepository En el Presentador inyectamos entonces la clase modelo y en el método render pediremos los artículos publicados que pasamos al modelo: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; @@ -53,7 +52,7 @@ class HomePresenter extends Nette\Application\UI\Presenter } ``` -En la plantilla nos encargaremos de renderizar una lista de artículos: +La plantilla `default.latte` se encargará de listar los artículos: ```latte {block content} @@ -114,7 +113,7 @@ El siguiente paso es editar el presentador. Enviaremos el número de la página También expandimos el método render para obtener la instancia Paginator, configurándola, y seleccionando los artículos correctos para mostrar en la plantilla. HomePresenter tendrá este aspecto: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; @@ -190,7 +189,6 @@ namespace App\Model; use Nette; - class ArticleRepository { public function __construct( @@ -210,7 +208,7 @@ class ArticleRepository No tenemos que crear Paginator en el Presentador, en su lugar utilizaremos el método del objeto `Selection` devuelto por el repositorio: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; diff --git a/best-practices/fr/composer.texy b/best-practices/fr/composer.texy index d934b6499d..bb6de406f9 100644 --- a/best-practices/fr/composer.texy +++ b/best-practices/fr/composer.texy @@ -189,7 +189,7 @@ Toutefois, il est également possible d'utiliser Composer pour charger d'autres Par la suite, il est nécessaire d'exécuter la commande `composer dumpautoload` à chaque modification et de laisser les tables d'autoloadage se régénérer. Ceci est extrêmement gênant, et il est de loin préférable de confier cette tâche à [RobotLoader |robot-loader:], qui effectue la même activité automatiquement en arrière-plan et beaucoup plus rapidement. -La deuxième option consiste à suivre le [système PSR-4 |https://www.php-fig.org/psr/psr-4/]. Pour faire simple, il s'agit d'un système où les espaces de noms et les noms de classes correspondent à la structure des répertoires et aux noms de fichiers, c'est-à-dire que `App\Router\RouterFactory` est situé dans le fichier `/path/to/App/Router/RouterFactory.php`. Exemple de configuration : +La deuxième option consiste à suivre le [système PSR-4 |https://www.php-fig.org/psr/psr-4/]. Pour faire simple, il s'agit d'un système où les espaces de noms et les noms de classes correspondent à la structure des répertoires et aux noms de fichiers, c'est-à-dire que `App\Core\RouterFactory` est situé dans le fichier `/path/to/App/Core/RouterFactory.php`. Exemple de configuration : ```js { diff --git a/best-practices/fr/lets-create-contact-form.texy b/best-practices/fr/lets-create-contact-form.texy index 50afc50327..0b3b5b4409 100644 --- a/best-practices/fr/lets-create-contact-form.texy +++ b/best-practices/fr/lets-create-contact-form.texy @@ -39,7 +39,7 @@ Comme vous pouvez le voir, nous avons créé deux méthodes. La première métho Mais que se passe-t-il si l'utilisateur ne remplit pas certains champs ? Dans ce cas, nous devons l'informer qu'il s'agit d'un champ obligatoire. C'est ce que nous avons fait avec la méthode `setRequired()`. Enfin, nous avons également ajouté un [événement |nette:glossary#events] `onSuccess`, qui est déclenché si le formulaire est soumis avec succès. Dans notre cas, il appelle la méthode `contactFormSucceeded`, qui se charge de traiter le formulaire soumis. Nous l'ajouterons au code dans un instant. -Laissez le composant `contantForm` être rendu dans le modèle `templates/Home/default.latte`: +Laissez le composant `contantForm` être rendu dans le modèle `Home/default.latte`: ```latte {block content} diff --git a/best-practices/fr/pagination.texy b/best-practices/fr/pagination.texy index cbd07b5ec6..54f1b59e69 100644 --- a/best-practices/fr/pagination.texy +++ b/best-practices/fr/pagination.texy @@ -11,7 +11,6 @@ namespace App\Model; use Nette; - class ArticleRepository { public function __construct( @@ -34,7 +33,7 @@ class ArticleRepository Dans le Presenter nous injectons ensuite la classe model et dans la méthode render nous allons demander les articles publiés que nous passons au template : ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; @@ -53,7 +52,7 @@ class HomePresenter extends Nette\Application\UI\Presenter } ``` -Dans le modèle, nous allons nous occuper de rendre une liste d'articles : +Le modèle `default.latte` se chargera ensuite de répertorier les articles : ```latte {block content} @@ -114,7 +113,7 @@ L'étape suivante consiste à modifier le présentateur. Nous allons transmettre Nous étendons également la méthode de rendu pour obtenir l'instance de Paginator, la configurer et sélectionner les bons articles à afficher dans le modèle. Le HomePresenter ressemblera à ceci : ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; @@ -190,7 +189,6 @@ namespace App\Model; use Nette; - class ArticleRepository { public function __construct( @@ -210,7 +208,7 @@ class ArticleRepository Nous n'avons pas besoin de créer le Paginator dans le Presenter, à la place nous utiliserons la méthode de l'objet `Selection` retourné par le référentiel : ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; diff --git a/best-practices/hu/composer.texy b/best-practices/hu/composer.texy index fee65b20c5..d3c767b633 100644 --- a/best-practices/hu/composer.texy +++ b/best-practices/hu/composer.texy @@ -189,7 +189,7 @@ Lehetőség van azonban arra is, hogy a Composer segítségével a `vendor` mapp Ezt követően minden egyes változtatásnál el kell indítani a `composer dumpautoload` parancsot, és hagyni kell, hogy az autoloading táblák újratermelődjenek. Ez rendkívül kényelmetlen, és sokkal jobb, ha ezt a feladatot a [RobotLoaderre |robot-loader:] bízzuk, amely a háttérben automatikusan és sokkal gyorsabban végzi el ugyanezt a tevékenységet. -A második lehetőség a [PSR-4 |https://www.php-fig.org/psr/psr-4/] követése. Egyszerűen fogalmazva, ez egy olyan rendszer, ahol a névterek és az osztálynevek megfelelnek a könyvtárszerkezetnek és a fájlneveknek, azaz a `App\Router\RouterFactory` a `/path/to/App/Router/RouterFactory.php` fájlban található. Konfigurációs példa: +A második lehetőség a [PSR-4 |https://www.php-fig.org/psr/psr-4/] követése. Egyszerűen fogalmazva, ez egy olyan rendszer, ahol a névterek és az osztálynevek megfelelnek a könyvtárszerkezetnek és a fájlneveknek, azaz a `App\Core\RouterFactory` a `/path/to/App/Core/RouterFactory.php` fájlban található. Konfigurációs példa: ```js { diff --git a/best-practices/hu/lets-create-contact-form.texy b/best-practices/hu/lets-create-contact-form.texy index 0f6e9b14d8..f13d2dc808 100644 --- a/best-practices/hu/lets-create-contact-form.texy +++ b/best-practices/hu/lets-create-contact-form.texy @@ -39,7 +39,7 @@ Mint látható, két metódust hoztunk létre. Az első metódus `createComponen De mi van akkor, ha a felhasználó nem tölt ki néhány mezőt? Ebben az esetben tudatnunk kell vele, hogy az adott mező kötelezően kitöltendő. Ezt a `setRequired()` metódussal tettük meg. Végül hozzáadtunk egy `onSuccess`[eseményt |nette:glossary#events] is, amely akkor lép működésbe, ha az űrlapot sikeresen elküldtük. A mi esetünkben meghívja a `contactFormSucceeded` metódust , amely a beküldött űrlap feldolgozásáról gondoskodik. Ezt is hozzáadjuk a kódhoz egy pillanat múlva. -Legyen a `contantForm` komponens megjelenítve a `templates/Home/default.latte` sablonban: +Legyen a `contantForm` komponens megjelenítve a `Home/default.latte` sablonban: ```latte {block content} diff --git a/best-practices/hu/pagination.texy b/best-practices/hu/pagination.texy index e1805afd07..8624e9e074 100644 --- a/best-practices/hu/pagination.texy +++ b/best-practices/hu/pagination.texy @@ -11,7 +11,6 @@ namespace App\Model; use Nette; - class ArticleRepository { public function __construct( @@ -34,7 +33,7 @@ class ArticleRepository A Presenterben ezután befecskendezzük a modell osztályt, és a render metódusban lekérdezzük a publikált cikkeket, amelyeket átadunk a sablonhoz: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; @@ -53,7 +52,7 @@ class HomePresenter extends Nette\Application\UI\Presenter } ``` -A sablonban gondoskodunk egy cikklista rendereléséről: +A `default.latte` sablon ezután gondoskodik a cikkek felsorolásáról: ```latte {block content} @@ -114,7 +113,7 @@ A következő lépés a bemutató szerkesztése. Az aktuálisan megjelenített o A render metódust kibővítjük a Paginator példány megszerzésével, beállításával és a sablonban megjelenítendő megfelelő cikkek kiválasztásával is. A HomePresenter így fog kinézni: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; @@ -190,7 +189,6 @@ namespace App\Model; use Nette; - class ArticleRepository { public function __construct( @@ -210,7 +208,7 @@ class ArticleRepository Nem kell Paginátort létrehoznunk a Presenterben, helyette az adattár által visszaadott `Selection` objektum metódusát fogjuk használni: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; diff --git a/best-practices/it/composer.texy b/best-practices/it/composer.texy index 93f33e4133..6ca7aff82e 100644 --- a/best-practices/it/composer.texy +++ b/best-practices/it/composer.texy @@ -189,7 +189,7 @@ Tuttavia, è anche possibile usare Composer per caricare altre classi al di fuor Successivamente, è necessario eseguire il comando `composer dumpautoload` a ogni modifica e lasciare che le tabelle di autocaricamento si rigenerino. Questo è estremamente scomodo ed è molto meglio affidare questo compito a [RobotLoader |robot-loader:], che svolge la stessa attività automaticamente in background e molto più velocemente. -La seconda opzione consiste nel seguire [PSR-4 |https://www.php-fig.org/psr/psr-4/]. In parole povere, si tratta di un sistema in cui gli spazi dei nomi e i nomi delle classi corrispondono alla struttura delle directory e ai nomi dei file, cioè `App\Router\RouterFactory` si trova nel file `/path/to/App/Router/RouterFactory.php`. Esempio di configurazione: +La seconda opzione consiste nel seguire [PSR-4 |https://www.php-fig.org/psr/psr-4/]. In parole povere, si tratta di un sistema in cui gli spazi dei nomi e i nomi delle classi corrispondono alla struttura delle directory e ai nomi dei file, cioè `App\Core\RouterFactory` si trova nel file `/path/to/App/Core/RouterFactory.php`. Esempio di configurazione: ```js { diff --git a/best-practices/it/lets-create-contact-form.texy b/best-practices/it/lets-create-contact-form.texy index 463ed21c39..468790dce9 100644 --- a/best-practices/it/lets-create-contact-form.texy +++ b/best-practices/it/lets-create-contact-form.texy @@ -39,7 +39,7 @@ Come si può vedere, abbiamo creato due metodi. Il primo metodo `createComponent Ma cosa succede se l'utente non compila alcuni campi? In questo caso, dovremmo fargli sapere che si tratta di un campo obbligatorio. Lo abbiamo fatto con il metodo `setRequired()`. Infine, abbiamo aggiunto anche un [evento |nette:glossary#events] `onSuccess`, che si attiva se il form viene inviato con successo. Nel nostro caso, richiama il metodo `contactFormSucceeded`, che si occupa di elaborare il modulo inviato. Lo aggiungeremo al codice tra poco. -Il componente `contantForm` deve essere reso nel template `templates/Home/default.latte`: +Il componente `contantForm` deve essere reso nel template `Home/default.latte`: ```latte {block content} diff --git a/best-practices/it/pagination.texy b/best-practices/it/pagination.texy index 0d6ca96483..12687b4ccd 100644 --- a/best-practices/it/pagination.texy +++ b/best-practices/it/pagination.texy @@ -11,7 +11,6 @@ namespace App\Model; use Nette; - class ArticleRepository { public function __construct( @@ -34,7 +33,7 @@ class ArticleRepository Nel Presenter iniettiamo poi la classe Model e nel metodo render chiediamo gli articoli pubblicati che passiamo al template: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; @@ -53,7 +52,7 @@ class HomePresenter extends Nette\Application\UI\Presenter } ``` -Nel modello, ci occuperemo di rendere un elenco di articoli: +Il modello `default.latte` si occuperà di elencare gli articoli: ```latte {block content} @@ -114,7 +113,7 @@ Il passo successivo è modificare il presentatore. Inoltreremo il numero della p Espandiamo inoltre il metodo render per ottenere l'istanza di Paginator, impostandola e selezionando gli articoli corretti da visualizzare nel template. HomePresenter avrà questo aspetto: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; @@ -190,7 +189,6 @@ namespace App\Model; use Nette; - class ArticleRepository { public function __construct( @@ -210,7 +208,7 @@ class ArticleRepository Non è necessario creare il Paginator nel Presenter, ma si utilizzerà il metodo dell'oggetto `Selection` restituito dal repository: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; diff --git a/best-practices/pl/composer.texy b/best-practices/pl/composer.texy index 125441e90d..77950657da 100644 --- a/best-practices/pl/composer.texy +++ b/best-practices/pl/composer.texy @@ -189,7 +189,7 @@ Jednakże możliwe jest również użycie Composera do załadowania innych klas Następnie musisz uruchomić polecenie `composer dumpautoload` za każdym razem, gdy dokonujesz zmiany i masz ponownie wygenerowane tabele autoloader. Jest to niezwykle uciążliwe i zdecydowanie lepiej powierzyć to zadanie [RobotLoaderowi |robot-loader:], który wykonuje tę samą pracę automatycznie w tle i znacznie szybciej. -Inną możliwością jest zastosowanie się do [PSR-4 |https://www.php-fig.org/psr/psr-4/]. Mówiąc najprościej, jest to system, w którym przestrzenie nazw i nazwy klas odpowiadają strukturom katalogów i nazwom plików, więc na przykład `App\Router\RouterFactory` będzie w pliku `/path/to/App/Router/RouterFactory.php`. Przykładowa konfiguracja: +Inną możliwością jest zastosowanie się do [PSR-4 |https://www.php-fig.org/psr/psr-4/]. Mówiąc najprościej, jest to system, w którym przestrzenie nazw i nazwy klas odpowiadają strukturom katalogów i nazwom plików, więc na przykład `App\Core\RouterFactory` będzie w pliku `/path/to/App/Core/RouterFactory.php`. Przykładowa konfiguracja: ```js { diff --git a/best-practices/pl/lets-create-contact-form.texy b/best-practices/pl/lets-create-contact-form.texy index 25c109b3c9..40f832e01b 100644 --- a/best-practices/pl/lets-create-contact-form.texy +++ b/best-practices/pl/lets-create-contact-form.texy @@ -39,7 +39,7 @@ Jak widać, stworzyliśmy dwie metody. Pierwsza metoda `createComponentContactFo Ale co jeśli użytkownik nie wypełni niektórych pól? W takim przypadku powinniśmy dać mu znać, że jest to pole wymagane. Zrobiliśmy to za pomocą metody `setRequired()`. Na koniec dodaliśmy również [zdarzenie |nette:glossary#events] `onSuccess`, które jest wywoływane, jeśli formularz zostanie przesłany pomyślnie. W naszym przypadku wywołuje ono metodę `contactFormSucceeded`, która zajmuje się przetwarzaniem przesłanego formularza. Za chwilę dodamy to do kodu. -Niech komponent `contantForm` będzie renderowany w szablonie `templates/Home/default.latte`: +Niech komponent `contantForm` będzie renderowany w szablonie `Home/default.latte`: ```latte {block content} diff --git a/best-practices/pl/pagination.texy b/best-practices/pl/pagination.texy index d6da41b76b..5ce00ae417 100644 --- a/best-practices/pl/pagination.texy +++ b/best-practices/pl/pagination.texy @@ -11,7 +11,6 @@ namespace App\Model; use Nette; - class ArticleRepository { public function __construct( @@ -34,7 +33,7 @@ class ArticleRepository Następnie wstrzykujemy klasę modelu w prezenterze i w metodzie render żądamy opublikowanych artykułów do przekazania do szablonu: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; @@ -53,7 +52,7 @@ class HomePresenter extends Nette\Application\UI\Presenter } ``` -W szablonie zajmujemy się następnie wyszczególnieniem artykułów: +Szablon `default.latte` zajmie się następnie listą artykułów: ```latte {block content} @@ -114,7 +113,7 @@ Następnie zabierzemy się do pracy nad modyfikacją prezentera. Do metody rende Następnie rozszerzymy również metodę render, aby uzyskać instancję Paginatora, skonfigurować ją i wybrać odpowiednie artykuły do wyświetlenia w szablonie. HomePresenter po modyfikacjach będzie wyglądał tak: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; @@ -190,7 +189,6 @@ namespace App\Model; use Nette; - class ArticleRepository { public function __construct( @@ -210,7 +208,7 @@ class ArticleRepository Nie musimy tworzyć Paginatora w prezenterze, zamiast tego używamy metody klasy `Selection` zwracanej przez repozytorium: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; diff --git a/best-practices/pt/composer.texy b/best-practices/pt/composer.texy index a22608c832..bc48d771b3 100644 --- a/best-practices/pt/composer.texy +++ b/best-practices/pt/composer.texy @@ -189,7 +189,7 @@ Entretanto, também é possível utilizar o Composer para carregar outras classe Em seguida, é necessário executar o comando `composer dumpautoload` a cada mudança e deixar as mesas de auto-carga se regenerar. Isto é extremamente inconveniente, e é muito melhor confiar esta tarefa ao [RobotLoader |robot-loader:], que executa a mesma atividade automaticamente em segundo plano e muito mais rápido. -A segunda opção é seguir o [PSR-4 |https://www.php-fig.org/psr/psr-4/]. Simplesmente dizendo, é um sistema onde os namespaces e nomes de classes correspondem à estrutura do diretório e nomes de arquivos, ou seja, `App\Router\RouterFactory` está localizado no arquivo `/path/to/App/Router/RouterFactory.php`. Exemplo de configuração: +A segunda opção é seguir o [PSR-4 |https://www.php-fig.org/psr/psr-4/]. Simplesmente dizendo, é um sistema onde os namespaces e nomes de classes correspondem à estrutura do diretório e nomes de arquivos, ou seja, `App\Core\RouterFactory` está localizado no arquivo `/path/to/App/Core/RouterFactory.php`. Exemplo de configuração: ```js { diff --git a/best-practices/pt/lets-create-contact-form.texy b/best-practices/pt/lets-create-contact-form.texy index 73db878db9..6fd619dd72 100644 --- a/best-practices/pt/lets-create-contact-form.texy +++ b/best-practices/pt/lets-create-contact-form.texy @@ -39,7 +39,7 @@ Como você pode ver, nós criamos dois métodos. O primeiro método `createCompo Mas e se o usuário não preencher alguns campos? Nesse caso, devemos avisá-lo que se trata de um campo obrigatório. Fizemos isso com o método `setRequired()`. Finalmente, adicionamos também um [evento |nette:glossary#events] `onSuccess`, que é acionado se o formulário for submetido com sucesso. Em nosso caso, ele chama o método `contactFormSucceeded`, que se encarrega de processar o formulário submetido. Acrescentaremos isso ao código em um momento. -Deixe o componente `contantForm` ser apresentado no modelo `templates/Home/default.latte`: +Deixe o componente `contantForm` ser apresentado no modelo `Home/default.latte`: ```latte {block content} diff --git a/best-practices/pt/pagination.texy b/best-practices/pt/pagination.texy index 7fae6d5b5e..0aa0e7f093 100644 --- a/best-practices/pt/pagination.texy +++ b/best-practices/pt/pagination.texy @@ -11,7 +11,6 @@ namespace App\Model; use Nette; - class ArticleRepository { public function __construct( @@ -34,7 +33,7 @@ class ArticleRepository No Apresentador injetamos então a classe do modelo e no método de renderização pediremos os artigos publicados que passamos para o modelo: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; @@ -53,7 +52,7 @@ class HomePresenter extends Nette\Application\UI\Presenter } ``` -No modelo, nós nos encarregaremos de elaborar uma lista de artigos: +O modelo `default.latte` se encarregará de listar os artigos: ```latte {block content} @@ -114,7 +113,7 @@ O próximo passo é editar o apresentador. Nós encaminharemos o número da pág Também expandimos o método de renderização para obter a instância Paginator, configurando-a e selecionando os artigos corretos a serem exibidos no modelo. Home PagePresenter terá este aspecto: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; @@ -190,7 +189,6 @@ namespace App\Model; use Nette; - class ArticleRepository { public function __construct( @@ -210,7 +208,7 @@ class ArticleRepository Não temos que criar o Paginador no Apresentador, em vez disso usaremos o método do objeto `Selection` devolvido pelo repositório: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; diff --git a/best-practices/ro/composer.texy b/best-practices/ro/composer.texy index a2c5f12e81..0905a7c202 100644 --- a/best-practices/ro/composer.texy +++ b/best-practices/ro/composer.texy @@ -189,7 +189,7 @@ Cu toate acestea, este de asemenea posibil să utilizați Composer pentru a înc Ulterior, este necesar să executați comanda `composer dumpautoload` cu fiecare modificare și să lăsați tabelele de autoloading să se regenereze. Acest lucru este extrem de incomod și este mult mai bine să încredințați această sarcină lui [RobotLoader |robot-loader:], care efectuează aceeași activitate în mod automat în fundal și mult mai rapid. -A doua opțiune este să urmați [PSR-4 |https://www.php-fig.org/psr/psr-4/]. Spunând simplu, este un sistem în care spațiile de nume și numele claselor corespund structurii directoarelor și numelor de fișiere, adică `App\Router\RouterFactory` se află în fișierul `/path/to/App/Router/RouterFactory.php`. Exemplu de configurare: +A doua opțiune este să urmați [PSR-4 |https://www.php-fig.org/psr/psr-4/]. Spunând simplu, este un sistem în care spațiile de nume și numele claselor corespund structurii directoarelor și numelor de fișiere, adică `App\Core\RouterFactory` se află în fișierul `/path/to/App/Core/RouterFactory.php`. Exemplu de configurare: ```js { diff --git a/best-practices/ro/lets-create-contact-form.texy b/best-practices/ro/lets-create-contact-form.texy index eecffd9791..42435507e4 100644 --- a/best-practices/ro/lets-create-contact-form.texy +++ b/best-practices/ro/lets-create-contact-form.texy @@ -39,7 +39,7 @@ După cum puteți vedea, am creat două metode. Prima metodă `createComponentCo Dar ce se întâmplă dacă utilizatorul nu completează unele câmpuri? În acest caz, ar trebui să-l anunțăm că este un câmp obligatoriu. Am făcut acest lucru cu metoda `setRequired()`. În cele din urmă, am adăugat și un [eveniment |nette:glossary#events] `onSuccess`, care este declanșat dacă formularul este trimis cu succes. În cazul nostru, acesta apelează metoda `contactFormSucceeded`, care se ocupă de procesarea formularului trimis. Vom adăuga acest lucru în cod imediat. -Lăsați componenta `contantForm` să fie redată în șablonul `templates/Home/default.latte`: +Lăsați componenta `contantForm` să fie redată în șablonul `Home/default.latte`: ```latte {block content} diff --git a/best-practices/ro/pagination.texy b/best-practices/ro/pagination.texy index 40d9de47aa..4be1cfff5c 100644 --- a/best-practices/ro/pagination.texy +++ b/best-practices/ro/pagination.texy @@ -11,7 +11,6 @@ namespace App\Model; use Nette; - class ArticleRepository { public function __construct( @@ -34,7 +33,7 @@ class ArticleRepository În Presenter vom injecta apoi clasa model, iar în metoda render vom cere articolele publicate pe care le vom trece în șablon: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; @@ -53,7 +52,7 @@ class HomePresenter extends Nette\Application\UI\Presenter } ``` -În șablon, ne vom ocupa de redarea unei liste de articole: +Șablonul `default.latte` se va ocupa apoi de listarea articolelor: ```latte {block content} @@ -114,7 +113,7 @@ Următorul pas este să modificăm prezentatorul. Vom transmite numărul paginii De asemenea, extindem metoda de randare pentru a obține instanța Paginator, configurând-o și selectând articolele corecte pentru a fi afișate în șablon. HomePresenter va arăta astfel: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; @@ -190,7 +189,6 @@ namespace App\Model; use Nette; - class ArticleRepository { public function __construct( @@ -210,7 +208,7 @@ class ArticleRepository Nu trebuie să creăm Paginator în Presenter, în schimb vom folosi metoda obiectului `Selection` returnat de depozit: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; diff --git a/best-practices/ru/composer.texy b/best-practices/ru/composer.texy index 276a92c29e..6e77697023 100644 --- a/best-practices/ru/composer.texy +++ b/best-practices/ru/composer.texy @@ -189,7 +189,7 @@ Packagist.org — глобальный репозиторий .[#toc-packagist-o Впоследствии необходимо выполнять команду `composer dumpautoload` при каждом изменении и позволять таблицам автозагрузки регенерироваться. Это крайне неудобно, и гораздо лучше доверить эту задачу [RobotLoader|robot-loader:], который выполняет ту же самую работу автоматически в фоновом режиме и гораздо быстрее. -Второй вариант — следовать [PSR-4 |https://www.php-fig.org/psr/psr-4/]. Проще говоря, это система, в которой пространства имен и имена классов соответствуют структуре каталогов и именам файлов, т. е. `App\Router\RouterFactory` находится в файле `/path/to/App/Router/RouterFactory.php`. Пример конфигурации: +Второй вариант — следовать [PSR-4 |https://www.php-fig.org/psr/psr-4/]. Проще говоря, это система, в которой пространства имен и имена классов соответствуют структуре каталогов и именам файлов, т. е. `App\Core\RouterFactory` находится в файле `/path/to/App/Core/RouterFactory.php`. Пример конфигурации: ```js { diff --git a/best-practices/ru/lets-create-contact-form.texy b/best-practices/ru/lets-create-contact-form.texy index f81335f4ef..bed8cf51df 100644 --- a/best-practices/ru/lets-create-contact-form.texy +++ b/best-practices/ru/lets-create-contact-form.texy @@ -39,7 +39,7 @@ class HomePresenter extends Presenter Но что, если пользователь не заполнит некоторые поля? В этом случае мы должны сообщить ему, что это обязательное поле. Мы сделали это с помощью метода `setRequired()`. Наконец, мы также добавили [событие |nette:glossary#events] `onSuccess`, которое срабатывает в случае успешной отправки формы. В нашем случае оно вызывает метод `contactFormSucceeded`, который обрабатывает отправленную форму. Мы добавим это в код через некоторое время. -Пусть компонент `contantForm` будет отображен в шаблоне `templates/Home/default.latte`: +Пусть компонент `contantForm` будет отображен в шаблоне `Home/default.latte`: ```latte {block content} diff --git a/best-practices/ru/pagination.texy b/best-practices/ru/pagination.texy index 6d384a2ebf..286fc5f76a 100644 --- a/best-practices/ru/pagination.texy +++ b/best-practices/ru/pagination.texy @@ -11,7 +11,6 @@ namespace App\Model; use Nette; - class ArticleRepository { public function __construct( @@ -34,7 +33,7 @@ class ArticleRepository Затем в презентере мы вводим класс модели и в методе `render` запрашиваем опубликованные статьи, которые передаем в шаблон: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; @@ -53,7 +52,7 @@ class HomePresenter extends Nette\Application\UI\Presenter } ``` -В шаблоне мы позаботимся о выводе списка статей: +Шаблон `default.latte` позаботится о перечислении статей: ```latte {block content} @@ -114,7 +113,7 @@ class ArticleRepository Мы также расширяем метод `render` для получения экземпляра Paginator, его настройки и выбора нужных статей для отображения в шаблоне. HomePresenter будет выглядеть следующим образом: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; @@ -190,7 +189,6 @@ namespace App\Model; use Nette; - class ArticleRepository { public function __construct( @@ -210,7 +208,7 @@ class ArticleRepository Нам не нужно создавать Paginator в презентере, вместо этого мы будем использовать метод объекта `Selection`, возвращаемый репозиторием: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; diff --git a/best-practices/sl/composer.texy b/best-practices/sl/composer.texy index 97a8e4ad75..6a3fa3ffdc 100644 --- a/best-practices/sl/composer.texy +++ b/best-practices/sl/composer.texy @@ -189,7 +189,7 @@ Vendar je mogoče Composer uporabiti tudi za nalaganje drugih razredov zunaj map Nato je treba ob vsaki spremembi zagnati ukaz `composer dumpautoload` in pustiti, da se tabele za samodejno nalaganje regenerirajo. To je izredno neprijetno in veliko bolje je to nalogo zaupati programu [RobotLoader |robot-loader:], ki isto dejavnost opravi samodejno v ozadju in veliko hitreje. -Druga možnost je, da sledite [priporočilu PSR-4 |https://www.php-fig.org/psr/psr-4/]. Preprosto povedano, gre za sistem, v katerem imenska območja in imena razredov ustrezajo imeniški strukturi in imenom datotek, tj. `App\Router\RouterFactory` se nahaja v datoteki `/path/to/App/Router/RouterFactory.php`. Primer konfiguracije: +Druga možnost je, da sledite [priporočilu PSR-4 |https://www.php-fig.org/psr/psr-4/]. Preprosto povedano, gre za sistem, v katerem imenska območja in imena razredov ustrezajo imeniški strukturi in imenom datotek, tj. `App\Core\RouterFactory` se nahaja v datoteki `/path/to/App/Core/RouterFactory.php`. Primer konfiguracije: ```js { diff --git a/best-practices/sl/lets-create-contact-form.texy b/best-practices/sl/lets-create-contact-form.texy index feeae86ee8..0fe2c371a9 100644 --- a/best-practices/sl/lets-create-contact-form.texy +++ b/best-practices/sl/lets-create-contact-form.texy @@ -39,7 +39,7 @@ Kot lahko vidite, smo ustvarili dve metodi. Prva metoda `createComponentContactF Kaj pa, če uporabnik ne izpolni nekaterih polj? V tem primeru mu moramo sporočiti, da gre za zahtevano polje. To smo storili z metodo `setRequired()`. Na koncu smo dodali še [dogodek |nette:glossary#events] `onSuccess`, ki se sproži, če je obrazec uspešno oddan. V našem primeru pokliče metodo `contactFormSucceeded`, ki poskrbi za obdelavo oddanega obrazca. To bomo v kodo dodali v naslednjem trenutku. -Naj bo komponenta `contantForm` prikazana v predlogi `templates/Home/default.latte`: +Naj bo komponenta `contantForm` prikazana v predlogi `Home/default.latte`: ```latte {block content} diff --git a/best-practices/sl/pagination.texy b/best-practices/sl/pagination.texy index fff9e4bf1f..cfc943d8ea 100644 --- a/best-practices/sl/pagination.texy +++ b/best-practices/sl/pagination.texy @@ -11,7 +11,6 @@ namespace App\Model; use Nette; - class ArticleRepository { public function __construct( @@ -34,7 +33,7 @@ class ArticleRepository V Presenter nato injiciramo razred model in v metodi render bomo zahtevali objavljene članke, ki jih posredujemo predlogi: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; @@ -53,7 +52,7 @@ class HomePresenter extends Nette\Application\UI\Presenter } ``` -V predlogi bomo poskrbeli za upodobitev seznama člankov: +Predloga `default.latte` bo nato poskrbela za seznam člankov: ```latte {block content} @@ -114,7 +113,7 @@ Naslednji korak je urejanje predstavnika. Številko trenutno prikazane strani bo Metodo upodabljanja razširimo tudi na pridobitev primerka Paginatorja, njegovo nastavitev in izbiro pravilnih člankov za prikaz v predlogi. HomePresenter bo videti takole: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; @@ -190,7 +189,6 @@ namespace App\Model; use Nette; - class ArticleRepository { public function __construct( @@ -210,7 +208,7 @@ class ArticleRepository Namesto tega bomo uporabili metodo predmeta `Selection`, ki ga je vrnil repozitorij: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; diff --git a/best-practices/tr/composer.texy b/best-practices/tr/composer.texy index c16a3f0864..f16faee810 100644 --- a/best-practices/tr/composer.texy +++ b/best-practices/tr/composer.texy @@ -189,7 +189,7 @@ Ancak, Composer'ı `vendor` klasörü dışındaki diğer sınıfları yüklemek Daha sonra, her değişiklikte `composer dumpautoload` komutunu çalıştırmak ve otomatik yükleme tablolarının yeniden oluşturulmasına izin vermek gerekir. Bu son derece zahmetlidir ve bu görevi, aynı etkinliği arka planda otomatik olarak ve çok daha hızlı gerçekleştiren [RobotLoader'a |robot-loader:] emanet etmek çok daha iyidir. -İkinci seçenek [PSR-4'ü |https://www.php-fig.org/psr/psr-4/] takip etmektir. Basitçe söylemek gerekirse, ad alanlarının ve sınıf adlarının dizin yapısına ve dosya adlarına karşılık geldiği bir sistemdir, yani `App\Router\RouterFactory`, `/path/to/App/Router/RouterFactory.php` dosyasında bulunur. Yapılandırma örneği: +İkinci seçenek [PSR-4'ü |https://www.php-fig.org/psr/psr-4/] takip etmektir. Basitçe söylemek gerekirse, ad alanlarının ve sınıf adlarının dizin yapısına ve dosya adlarına karşılık geldiği bir sistemdir, yani `App\Core\RouterFactory`, `/path/to/App/Core/RouterFactory.php` dosyasında bulunur. Yapılandırma örneği: ```js { diff --git a/best-practices/tr/lets-create-contact-form.texy b/best-practices/tr/lets-create-contact-form.texy index 52d307b8bf..306be16c72 100644 --- a/best-practices/tr/lets-create-contact-form.texy +++ b/best-practices/tr/lets-create-contact-form.texy @@ -39,7 +39,7 @@ Gördüğünüz gibi iki metot oluşturduk. İlk yöntem `createComponentContact Peki ya kullanıcı bazı alanları doldurmazsa? Bu durumda, ona bunun gerekli bir alan olduğunu bildirmeliyiz. Bunu `setRequired()` metodu ile yaptık. Son olarak, form başarıyla gönderildiğinde tetiklenen bir `onSuccess`[olayı |nette:glossary#events] da ekledik. Bizim durumumuzda, gönderilen formun işlenmesiyle ilgilenen `contactFormSucceeded` yöntemini çağırır. Bunu birazdan koda ekleyeceğiz. - `contantForm` bileşeninin `templates/Home/default.latte` şablonunda oluşturulmasına izin verin: + `contantForm` bileşeninin `Home/default.latte` şablonunda oluşturulmasına izin verin: ```latte {block content} diff --git a/best-practices/tr/pagination.texy b/best-practices/tr/pagination.texy index 0f0d378bfd..f50fe4725a 100644 --- a/best-practices/tr/pagination.texy +++ b/best-practices/tr/pagination.texy @@ -11,7 +11,6 @@ namespace App\Model; use Nette; - class ArticleRepository { public function __construct( @@ -34,7 +33,7 @@ class ArticleRepository Presenter'da daha sonra model sınıfını enjekte edeceğiz ve render yönteminde şablona aktardığımız yayınlanmış makaleleri isteyeceğiz: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; @@ -53,7 +52,7 @@ class HomePresenter extends Nette\Application\UI\Presenter } ``` -Şablonda, bir makale listesi oluşturmaya özen göstereceğiz: +`default.latte` şablonu daha sonra makaleleri listelemekle ilgilenecektir: ```latte {block content} @@ -114,7 +113,7 @@ Bir sonraki adım sunucuyu düzenlemektir. Şu anda görüntülenen sayfanın nu Ayrıca Paginator örneğini almak, ayarlamak ve şablonda görüntülenecek doğru makaleleri seçmek için render yöntemini genişletiyoruz. HomePresenter şu şekilde görünecektir: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; @@ -190,7 +189,6 @@ namespace App\Model; use Nette; - class ArticleRepository { public function __construct( @@ -210,7 +208,7 @@ class ArticleRepository Presenter'da Paginator oluşturmak zorunda değiliz, bunun yerine repository tarafından döndürülen `Selection` nesnesinin yöntemini kullanacağız: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; diff --git a/best-practices/uk/composer.texy b/best-practices/uk/composer.texy index edca818c9a..e6777c8700 100644 --- a/best-practices/uk/composer.texy +++ b/best-practices/uk/composer.texy @@ -189,7 +189,7 @@ Packagist.org - глобальний репозиторій .[#toc-packagist-org Згодом необхідно виконувати команду `composer dumpautoload` при кожній зміні та дозволяти таблицям автозавантаження регенеруватися. Це вкрай незручно, і набагато краще довірити цю задачу [RobotLoader |robot-loader:], який виконує ту ж саму роботу автоматично у фоновому режимі і набагато швидше. -Другий варіант - слідувати [PSR-4 |https://www.php-fig.org/psr/psr-4/]. Простіше кажучи, це система, в якій простори імен та імена класів відповідають структурі каталогів та іменам файлів, тобто `App\Router\RouterFactory` знаходиться у файлі `/path/to/App/Router/RouterFactory.php`. Приклад конфігурації: +Другий варіант - слідувати [PSR-4 |https://www.php-fig.org/psr/psr-4/]. Простіше кажучи, це система, в якій простори імен та імена класів відповідають структурі каталогів та іменам файлів, тобто `App\Core\RouterFactory` знаходиться у файлі `/path/to/App/Core/RouterFactory.php`. Приклад конфігурації: ```js { diff --git a/best-practices/uk/lets-create-contact-form.texy b/best-practices/uk/lets-create-contact-form.texy index 724f0c58d7..e4cc290b82 100644 --- a/best-practices/uk/lets-create-contact-form.texy +++ b/best-practices/uk/lets-create-contact-form.texy @@ -39,7 +39,7 @@ class HomePresenter extends Presenter Але що, якщо користувач не заповнить деякі поля? У такому випадку ми повинні повідомити йому, що це поле є обов'язковим для заповнення. Ми зробили це за допомогою методу `setRequired()`. Нарешті, ми також додали [подію |nette:glossary#events] `onSuccess`, яка спрацьовує в разі успішного відправлення форми. У нашому випадку вона викликає метод `contactFormSucceeded`, який відповідає за обробку надісланої форми. Ми додамо його до коду за мить. -Нехай компонент `contantForm` рендериться в шаблоні `templates/Home/default.latte`: +Нехай компонент `contantForm` рендериться в шаблоні `Home/default.latte`: ```latte {block content} diff --git a/best-practices/uk/pagination.texy b/best-practices/uk/pagination.texy index 56ddd52028..cb64abb5f1 100644 --- a/best-practices/uk/pagination.texy +++ b/best-practices/uk/pagination.texy @@ -11,7 +11,6 @@ namespace App\Model; use Nette; - class ArticleRepository { public function __construct( @@ -34,7 +33,7 @@ class ArticleRepository Потім у презентері ми вводимо клас моделі і в методі `render` запитуємо опубліковані статті, які передаємо в шаблон: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; @@ -53,7 +52,7 @@ class HomePresenter extends Nette\Application\UI\Presenter } ``` -У шаблоні ми подбаємо про виведення списку статей: +Після цього шаблон `default.latte` подбає про список статей: ```latte {block content} @@ -114,7 +113,7 @@ class ArticleRepository Ми також розширюємо метод `render` для отримання екземпляра Paginator, його налаштування та вибору потрібних статей для відображення в шаблоні. HomePresenter матиме такий вигляд: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; @@ -190,7 +189,6 @@ namespace App\Model; use Nette; - class ArticleRepository { public function __construct( @@ -210,7 +208,7 @@ class ArticleRepository Нам не потрібно створювати Paginator у презентері, натомість ми використовуватимемо метод об'єкта `Selection`, який повертає сховище: ```php -namespace App\Presenters; +namespace App\Presentation\Home; use Nette; use App\Model\ArticleRepository; diff --git a/dependency-injection/bg/configuration.texy b/dependency-injection/bg/configuration.texy index b9ff04bf42..0186b9a79e 100644 --- a/dependency-injection/bg/configuration.texy +++ b/dependency-injection/bg/configuration.texy @@ -67,7 +67,7 @@ parameters: ```neon decorator: # За всички услуги, които са екземпляри на този клас или интерфейс - App\Presenters\BasePresenter: + App\Presentation\BasePresenter: setup: - setProjectId(10) # извикване на този метод - $absoluteUrls = true # и задаване на променлива diff --git a/dependency-injection/bg/factory.texy b/dependency-injection/bg/factory.texy index 43699fde67..b50ea73905 100644 --- a/dependency-injection/bg/factory.texy +++ b/dependency-injection/bg/factory.texy @@ -220,7 +220,7 @@ services: ```neon services: - - App\Router\RouterFactory::createRouter + - App\Core\RouterFactory::createRouter - App\Model\DatabaseAccessor( db1: @database.db1.context ) diff --git a/dependency-injection/cs/configuration.texy b/dependency-injection/cs/configuration.texy index 4b80e78339..292827a620 100644 --- a/dependency-injection/cs/configuration.texy +++ b/dependency-injection/cs/configuration.texy @@ -67,7 +67,7 @@ Jak upravit hromadně všechny služby určitého typu? Třeba zavolat určitou ```neon decorator: # u všech služeb, co jsou instancí této třídy nebo rozhraní - App\Presenters\BasePresenter: + App\Presentation\BasePresenter: setup: - setProjectId(10) # zavolej tuto metodu - $absoluteUrls = true # a nastav proměnnou diff --git a/dependency-injection/cs/factory.texy b/dependency-injection/cs/factory.texy index 082f32d37e..94da4bbd94 100644 --- a/dependency-injection/cs/factory.texy +++ b/dependency-injection/cs/factory.texy @@ -220,7 +220,7 @@ Druhou možností je využít k definici [tagy|services#Tagy]: ```neon services: - - App\Router\RouterFactory::createRouter + - App\Core\RouterFactory::createRouter - App\Model\DatabaseAccessor( db1: @database.db1.explorer ) diff --git a/dependency-injection/de/configuration.texy b/dependency-injection/de/configuration.texy index d8fd5fbb37..1016358612 100644 --- a/dependency-injection/de/configuration.texy +++ b/dependency-injection/de/configuration.texy @@ -67,7 +67,7 @@ Wie kann man alle Dienste eines bestimmten Typs als Ganzes bearbeiten? Müssen S ```neon decorator: # für alle Dienste, die Instanzen dieser Klasse oder Schnittstelle sind - App\Presenters\BasePresenter: + App\Presentation\BasePresenter: setup: - setProjectId(10) # diese Methode aufrufen - $absoluteUrls = true # und setze die Variable diff --git a/dependency-injection/de/factory.texy b/dependency-injection/de/factory.texy index c5ea50f342..2ff999d106 100644 --- a/dependency-injection/de/factory.texy +++ b/dependency-injection/de/factory.texy @@ -220,7 +220,7 @@ Eine weitere Möglichkeit, eine Multifabrik zu definieren, ist die Verwendung vo ```neon services: - - App\Router\RouterFactory::createRouter + - App\Core\RouterFactory::createRouter - App\Model\DatabaseAccessor( db1: @database.db1.explorer ) diff --git a/dependency-injection/el/configuration.texy b/dependency-injection/el/configuration.texy index b99ecbbcf9..bbd63d581e 100644 --- a/dependency-injection/el/configuration.texy +++ b/dependency-injection/el/configuration.texy @@ -67,7 +67,7 @@ parameters: ```neon decorator: # για όλες τις υπηρεσίες που είναι στιγμιότυπα αυτής της κλάσης ή διεπαφής - App\Presenters\BasePresenter: + App\Presentation\BasePresenter: setup: - setProjectId(10) # καλέστε αυτή τη μέθοδο - $absoluteUrls = true # και ορίστε τη μεταβλητή diff --git a/dependency-injection/el/factory.texy b/dependency-injection/el/factory.texy index ae2f1951f0..d6f61b4c87 100644 --- a/dependency-injection/el/factory.texy +++ b/dependency-injection/el/factory.texy @@ -220,7 +220,7 @@ services: ```neon services: - - App\Router\RouterFactory::createRouter + - App\Core\RouterFactory::createRouter - App\Model\DatabaseAccessor( db1: @database.db1.explorer ) diff --git a/dependency-injection/en/configuration.texy b/dependency-injection/en/configuration.texy index 4400910043..ab295aafcd 100644 --- a/dependency-injection/en/configuration.texy +++ b/dependency-injection/en/configuration.texy @@ -67,7 +67,7 @@ How to bulk edit all services of a certain type? Need to call a certain method f ```neon decorator: # for all services that are instances of this class or interface - App\Presenters\BasePresenter: + App\Presentation\BasePresenter: setup: - setProjectId(10) # call this method - $absoluteUrls = true # and set the variable diff --git a/dependency-injection/en/factory.texy b/dependency-injection/en/factory.texy index e96c7c385c..d3cc3a3c6c 100644 --- a/dependency-injection/en/factory.texy +++ b/dependency-injection/en/factory.texy @@ -220,7 +220,7 @@ Another option how to define a multifactory is to use [tags|services#Tags]: ```neon services: - - App\Router\RouterFactory::createRouter + - App\Core\RouterFactory::createRouter - App\Model\DatabaseAccessor( db1: @database.db1.explorer ) diff --git a/dependency-injection/es/configuration.texy b/dependency-injection/es/configuration.texy index ae0b652501..f5531d0021 100644 --- a/dependency-injection/es/configuration.texy +++ b/dependency-injection/es/configuration.texy @@ -67,7 +67,7 @@ Decorador .[#toc-decorator] ```neon decorator: # para todos los servicios que son instancias de esta clase o interfaz - App\Presenters\BasePresenter: + App\Presentation\BasePresenter: setup: - setProjectId(10) # llamar a este método - $absoluteUrls = true # y establecer la variable diff --git a/dependency-injection/es/factory.texy b/dependency-injection/es/factory.texy index 4e6151853f..ef367ff00a 100644 --- a/dependency-injection/es/factory.texy +++ b/dependency-injection/es/factory.texy @@ -220,7 +220,7 @@ Otra opción para definir un multifactory es utilizar [tags|services#Tags]: ```neon services: - - App\Router\RouterFactory::createRouter + - App\Core\RouterFactory::createRouter - App\Model\DatabaseAccessor( db1: @database.db1.explorer ) diff --git a/dependency-injection/fr/configuration.texy b/dependency-injection/fr/configuration.texy index 1970ea21e7..a9929b99b2 100644 --- a/dependency-injection/fr/configuration.texy +++ b/dependency-injection/fr/configuration.texy @@ -67,7 +67,7 @@ Comment modifier en masse tous les services d'un certain type ? Vous avez besoin ```neon decorator: # pour tous les services qui sont des instances de cette classe ou interface - App\Presenters\BasePresenter: + App\Presentation\BasePresenter: setup: - setProjectId(10) # appelle cette méthode - $absoluteUrls = true # et définir la variable diff --git a/dependency-injection/fr/factory.texy b/dependency-injection/fr/factory.texy index 7c49950361..836e6ee438 100644 --- a/dependency-injection/fr/factory.texy +++ b/dependency-injection/fr/factory.texy @@ -220,7 +220,7 @@ Une autre option pour définir un multifactory est d'utiliser des [balises |serv ```neon services: - - App\Router\RouterFactory::createRouter + - App\Core\RouterFactory::createRouter - App\Model\DatabaseAccessor( db1: @database.db1.explorer ) diff --git a/dependency-injection/hu/configuration.texy b/dependency-injection/hu/configuration.texy index ed9aa0144e..bf29935afc 100644 --- a/dependency-injection/hu/configuration.texy +++ b/dependency-injection/hu/configuration.texy @@ -67,7 +67,7 @@ Hogyan lehet egy bizonyos típusú összes szolgáltatást tömegesen szerkeszte ```neon decorator: # minden olyan szolgáltatáshoz, amely ennek az osztálynak vagy interfésznek a példánya. - App\Presenters\BasePresenter: + App\Presentation\BasePresenter: setup: - # hívja meg ezt a metódust - $absoluteUrls = true # és állítsuk be a változót diff --git a/dependency-injection/hu/factory.texy b/dependency-injection/hu/factory.texy index 438effdcc6..5ae2bec739 100644 --- a/dependency-injection/hu/factory.texy +++ b/dependency-injection/hu/factory.texy @@ -220,7 +220,7 @@ Egy másik lehetőség a multifactory definiálására a [címkék |services#Tag ```neon services: - - App\Router\RouterFactory::createRouter + - App\Core\RouterFactory::createRouter - App\Model\DatabaseAccessor( db1: @database.db1.explorer ) diff --git a/dependency-injection/it/configuration.texy b/dependency-injection/it/configuration.texy index 628d6a3bc0..66a67f3e7b 100644 --- a/dependency-injection/it/configuration.texy +++ b/dependency-injection/it/configuration.texy @@ -67,7 +67,7 @@ Come modificare in blocco tutti i servizi di un certo tipo? È necessario chiama ```neon decorator: # per tutti i servizi che sono istanze di questa classe o interfaccia - App\Presenters\BasePresenter: + App\Presentation\BasePresenter: setup: - setProjectId(10) # chiama questo metodo - $absoluteUrls = true # e imposta la variabile diff --git a/dependency-injection/it/factory.texy b/dependency-injection/it/factory.texy index 8eafe7bbc9..5487c86971 100644 --- a/dependency-injection/it/factory.texy +++ b/dependency-injection/it/factory.texy @@ -220,7 +220,7 @@ Un'altra opzione per definire una multifactory è quella di usare i [tag |servic ```neon services: - - App\Router\RouterFactory::createRouter + - App\Core\RouterFactory::createRouter - App\Model\DatabaseAccessor( db1: @database.db1.explorer ) diff --git a/dependency-injection/ja/configuration.texy b/dependency-injection/ja/configuration.texy index a6417023d2..5c6b0b8eae 100644 --- a/dependency-injection/ja/configuration.texy +++ b/dependency-injection/ja/configuration.texy @@ -67,7 +67,7 @@ parameters: ```neon decorator: # for all services that are instances of this class or interface - App\Presenters\BasePresenter: + App\Presentation\BasePresenter: setup: - setProjectId(10) # call this method - $absoluteUrls = true # and set the variable diff --git a/dependency-injection/ja/factory.texy b/dependency-injection/ja/factory.texy index 80d8064a3c..e5e83e538e 100644 --- a/dependency-injection/ja/factory.texy +++ b/dependency-injection/ja/factory.texy @@ -220,7 +220,7 @@ services: ```neon services: - - App\Router\RouterFactory::createRouter + - App\Core\RouterFactory::createRouter - App\Model\DatabaseAccessor( db1: @database.db1.explorer ) diff --git a/dependency-injection/pl/configuration.texy b/dependency-injection/pl/configuration.texy index f3ed899ede..453c0ce5cc 100644 --- a/dependency-injection/pl/configuration.texy +++ b/dependency-injection/pl/configuration.texy @@ -67,7 +67,7 @@ Jak masowo edytować wszystkie usługi danego typu? Na przykład wywołaj okreś ```neon decorator: # dla wszystkich usług, które są instancjami tej klasy lub interfejsu - App\Presenters\BasePresenter: + App\Presentation\BasePresenter: setup: - setProjectId(10) # wywołaj tę metodę - $absoluteUrls = true # i ustawić zmienną diff --git a/dependency-injection/pl/factory.texy b/dependency-injection/pl/factory.texy index 1658beda00..f566dad4ee 100644 --- a/dependency-injection/pl/factory.texy +++ b/dependency-injection/pl/factory.texy @@ -220,7 +220,7 @@ Druga opcja to użycie [tagów |services#Tags] do definicji: ```neon services: - - App\Router\RouterFactory::createRouter + - App\Core\RouterFactory::createRouter - App\Model\DatabaseAccessor( db1: @database.db1.explorer ) diff --git a/dependency-injection/pt/configuration.texy b/dependency-injection/pt/configuration.texy index eab09bb9dc..7c9cbc74d8 100644 --- a/dependency-injection/pt/configuration.texy +++ b/dependency-injection/pt/configuration.texy @@ -67,7 +67,7 @@ Como editar em massa todos os serviços de um determinado tipo? Precisa chamar u ```neon decorator: # para todos os serviços que são instâncias desta classe ou interface - App\Presenters\BasePresenter: + App\Presentation\BasePresenter: setup: - setProjectId(10) # chamar este método - $absoluteUrls = true # e definir a variável diff --git a/dependency-injection/pt/factory.texy b/dependency-injection/pt/factory.texy index 785b1ea569..293f3418b7 100644 --- a/dependency-injection/pt/factory.texy +++ b/dependency-injection/pt/factory.texy @@ -220,7 +220,7 @@ Outra opção para definir uma multifábrica é a utilização de [etiquetas |se ```neon services: - - App\Router\RouterFactory::createRouter + - App\Core\RouterFactory::createRouter - App\Model\DatabaseAccessor( db1: @database.db1.explorer ) diff --git a/dependency-injection/ro/configuration.texy b/dependency-injection/ro/configuration.texy index 92e4c59ecd..be7fa148f3 100644 --- a/dependency-injection/ro/configuration.texy +++ b/dependency-injection/ro/configuration.texy @@ -67,7 +67,7 @@ Cum se pot edita în bloc toate serviciile de un anumit tip? Aveți nevoie să a ```neon decorator: # pentru toate serviciile care sunt instanțe ale acestei clase sau interfețe - App\Presenters\BasePresenter: + App\Presentation\BasePresenter: setup: - setProjectId(10) # apelează această metodă - $absoluteUrls = true # și setează variabila diff --git a/dependency-injection/ro/factory.texy b/dependency-injection/ro/factory.texy index 25a1475f01..d282fe1624 100644 --- a/dependency-injection/ro/factory.texy +++ b/dependency-injection/ro/factory.texy @@ -220,7 +220,7 @@ O altă opțiune de definire a unui multifactorial este utilizarea [etichetelor ```neon services: - - App\Router\RouterFactory::createRouter + - App\Core\RouterFactory::createRouter - App\Model\DatabaseAccessor( db1: @database.db1.explorer ) diff --git a/dependency-injection/ru/configuration.texy b/dependency-injection/ru/configuration.texy index 6fc86f0476..96a42762c8 100644 --- a/dependency-injection/ru/configuration.texy +++ b/dependency-injection/ru/configuration.texy @@ -67,7 +67,7 @@ parameters: ```neon decorator: # Для всех сервисов, являющихся экземплярами этого класса или интерфейса - App\Presenters\BasePresenter: + App\Presentation\BasePresenter: setup: - setProjectId(10) # вызываем этот метод - $absoluteUrls = true # и задаем переменную diff --git a/dependency-injection/ru/factory.texy b/dependency-injection/ru/factory.texy index ebe578c30c..21149c2339 100644 --- a/dependency-injection/ru/factory.texy +++ b/dependency-injection/ru/factory.texy @@ -220,7 +220,7 @@ services: ```neon services: - - App\Router\RouterFactory::createRouter + - App\Core\RouterFactory::createRouter - App\Model\DatabaseAccessor( db1: @database.db1.context ) diff --git a/dependency-injection/sl/configuration.texy b/dependency-injection/sl/configuration.texy index 5ab5cf0e50..d4e9e721b5 100644 --- a/dependency-injection/sl/configuration.texy +++ b/dependency-injection/sl/configuration.texy @@ -67,7 +67,7 @@ Kako množično urediti vse storitve določene vrste? Ali morate poklicati dolo ```neon decorator: # za vse storitve, ki so primerki tega razreda ali vmesnika. - App\Presenters\BasePresenter: + App\Presentation\BasePresenter: setup: - setProjectId(10) # pokliče to metodo - $absoluteUrls = true # in nastavi spremenljivko diff --git a/dependency-injection/sl/factory.texy b/dependency-injection/sl/factory.texy index 9c7a9dcb45..6fba37cb35 100644 --- a/dependency-injection/sl/factory.texy +++ b/dependency-injection/sl/factory.texy @@ -220,7 +220,7 @@ Druga možnost, kako opredeliti večpredstavnostno zbirko, je uporaba [oznak |se ```neon services: - - App\Router\RouterFactory::createRouter + - App\Core\RouterFactory::createRouter - App\Model\DatabaseAccessor( db1: @database.db1.explorer ) diff --git a/dependency-injection/tr/configuration.texy b/dependency-injection/tr/configuration.texy index 03cc7541d7..3952d6e9ac 100644 --- a/dependency-injection/tr/configuration.texy +++ b/dependency-injection/tr/configuration.texy @@ -67,7 +67,7 @@ Belirli bir türdeki tüm hizmetleri toplu olarak nasıl düzenleyebilirim? Beli ```neon decorator: # bu sınıfın veya arayüzün örneği olan tüm hizmetler için - App\Presenters\BasePresenter: + App\Presentation\BasePresenter: setup: - setProjectId(10) # bu yöntemi çağır - $absoluteUrls = true # ve değişkeni ayarlayın diff --git a/dependency-injection/tr/factory.texy b/dependency-injection/tr/factory.texy index 26bd3c9ab1..60de28c2be 100644 --- a/dependency-injection/tr/factory.texy +++ b/dependency-injection/tr/factory.texy @@ -220,7 +220,7 @@ Bir multifactory'nin nasıl tanımlanacağına dair bir başka seçenek de [etik ```neon services: - - App\Router\RouterFactory::createRouter + - App\Core\RouterFactory::createRouter - App\Model\DatabaseAccessor( db1: @database.db1.explorer ) diff --git a/dependency-injection/uk/configuration.texy b/dependency-injection/uk/configuration.texy index 47b57a328e..572ffd0093 100644 --- a/dependency-injection/uk/configuration.texy +++ b/dependency-injection/uk/configuration.texy @@ -67,7 +67,7 @@ parameters: ```neon decorator: # Для всіх сервісів, які є екземплярами цього класу або інтерфейсу - App\Presenters\BasePresenter: + App\Presentation\BasePresenter: setup: - setProjectId(10) # викликаємо цей метод - $absoluteUrls = true # і задаємо змінну diff --git a/dependency-injection/uk/factory.texy b/dependency-injection/uk/factory.texy index b3dd17aa8e..a5c0dc0806 100644 --- a/dependency-injection/uk/factory.texy +++ b/dependency-injection/uk/factory.texy @@ -220,7 +220,7 @@ services: ```neon services: - - App\Router\RouterFactory::createRouter + - App\Core\RouterFactory::createRouter - App\Model\DatabaseAccessor( db1: @database.db1.context ) diff --git a/forms/bg/in-presenter.texy b/forms/bg/in-presenter.texy index 6a96b8e901..8473a143d6 100644 --- a/forms/bg/in-presenter.texy +++ b/forms/bg/in-presenter.texy @@ -30,7 +30,7 @@ $form->onSuccess[] = [$this, 'formSucceeded']; От гледна точка на водещия формулярът е общ компонент. Затова той се третира като компонент и се включва в презентатора чрез [метода factory |application:components#Factory-Methods]. Това ще изглежда по следния начин: -```php .{file:app/Presenters/HomePresenter.php} +```php .{file:app/Presentation/Home/HomePresenter.php} use Nette; use Nette\Application\UI\Form; @@ -59,7 +59,7 @@ class HomePresenter extends Nette\Application\UI\Presenter А визуализирането в шаблона се извършва с помощта на тага `{control}`: -```latte .{file:app/Presenters/templates/Home/default.latte} +```latte .{file:app/Presentation/Home/default.latte}

        Регистрация

        {control registrationForm} diff --git a/forms/cs/in-presenter.texy b/forms/cs/in-presenter.texy index e8d3bddccd..b6b69da76f 100644 --- a/forms/cs/in-presenter.texy +++ b/forms/cs/in-presenter.texy @@ -30,7 +30,7 @@ Formulář v presenteru je objekt třídy `Nette\Application\UI\Form`, její př Z pohledu presenteru je formulář běžná komponenta. Proto se s ním jako s komponentou zachází a začleníme ji do presenteru pomocí [tovární metody |application:components#Tovární metody]. Bude to vypadat takto: -```php .{file:app/Presenters/HomePresenter.php} +```php .{file:app/Presentation/Home/HomePresenter.php} use Nette; use Nette\Application\UI\Form; @@ -59,7 +59,7 @@ class HomePresenter extends Nette\Application\UI\Presenter A v šabloně formulář vykreslíme značkou `{control}`: -```latte .{file:app/Presenters/templates/Home/default.latte} +```latte .{file:app/Presentation/Home/default.latte}

        Registrace

        {control registrationForm} diff --git a/forms/de/in-presenter.texy b/forms/de/in-presenter.texy index 5397143c73..3e8ea79d59 100644 --- a/forms/de/in-presenter.texy +++ b/forms/de/in-presenter.texy @@ -30,7 +30,7 @@ Das Formular im Presenter ist ein Objekt der Klasse `Nette\Application\UI\Form`, Aus der Sicht des Präsentators ist das Formular eine gemeinsame Komponente. Daher wird es als Komponente behandelt und mit der [Factory-Methode |application:components#Factory Methods] in den Presenter eingebunden. Das sieht dann wie folgt aus: -```php .{file:app/Presenters/HomePresenter.php} +```php .{file:app/Presentation/Home/HomePresenter.php} use Nette; use Nette\Application\UI\Form; @@ -59,7 +59,7 @@ class HomePresenter extends Nette\Application\UI\Presenter Und das Rendern in der Vorlage erfolgt mit dem Tag `{control}`: -```latte .{file:app/Presenters/templates/Home/default.latte} +```latte .{file:app/Presentation/Home/default.latte}

        Registration

        {control registrationForm} diff --git a/forms/el/in-presenter.texy b/forms/el/in-presenter.texy index ee4a9f9280..a093a54b35 100644 --- a/forms/el/in-presenter.texy +++ b/forms/el/in-presenter.texy @@ -30,7 +30,7 @@ $form->onSuccess[] = [$this, 'formSucceeded']; Από τη σκοπιά του παρουσιαστή, η φόρμα είναι ένα κοινό συστατικό. Ως εκ τούτου, αντιμετωπίζεται ως συστατικό και ενσωματώνεται στον παρουσιαστή χρησιμοποιώντας τη [μέθοδο factory |application:components#Factory Methods]. Αυτό θα έχει την εξής μορφή: -```php .{file:app/Presenters/HomePresenter.php} +```php .{file:app/Presentation/Home/HomePresenter.php} use Nette; use Nette\Application\UI\Form; @@ -59,7 +59,7 @@ class HomePresenter extends Nette\Application\UI\Presenter Και η απόδοση στο πρότυπο γίνεται με τη χρήση της ετικέτας `{control}`: -```latte .{file:app/Presenters/templates/Home/default.latte} +```latte .{file:app/Presentation/Home/default.latte}

        Registration

        {control registrationForm} diff --git a/forms/en/in-presenter.texy b/forms/en/in-presenter.texy index 5d2fe73214..747d9ee4d5 100644 --- a/forms/en/in-presenter.texy +++ b/forms/en/in-presenter.texy @@ -30,7 +30,7 @@ The form in the presenter is an object of the class `Nette\Application\UI\Form`, From the presenter's point of view, the form is a common component. Therefore, it is treated as a component and incorporated into the presenter using [factory method |application:components#Factory Methods]. It will look like this: -```php .{file:app/Presenters/HomePresenter.php} +```php .{file:app/Presentation/Home/HomePresenter.php} use Nette; use Nette\Application\UI\Form; @@ -59,7 +59,7 @@ class HomePresenter extends Nette\Application\UI\Presenter And render in template is done using `{control}` tag: -```latte .{file:app/Presenters/templates/Home/default.latte} +```latte .{file:app/Presentation/Home/default.latte}

        Registration

        {control registrationForm} diff --git a/forms/es/in-presenter.texy b/forms/es/in-presenter.texy index a6d66ed0e3..23d02181b2 100644 --- a/forms/es/in-presenter.texy +++ b/forms/es/in-presenter.texy @@ -30,7 +30,7 @@ El formulario en el presentador es un objeto de la clase `Nette\Application\UI\F Desde el punto de vista del presentador, el formulario es un componente común. Por lo tanto, se trata como un componente y se incorpora al presentador utilizando [el método factory |application:components#Factory Methods]. Tendrá el siguiente aspecto: -```php .{file:app/Presenters/HomePresenter.php} +```php .{file:app/Presentation/Home/HomePresenter.php} use Nette; use Nette\Application\UI\Form; @@ -59,7 +59,7 @@ class HomePresenter extends Nette\Application\UI\Presenter Y el renderizado en la plantilla se realiza utilizando la etiqueta `{control}`: -```latte .{file:app/Presenters/templates/Home/default.latte} +```latte .{file:app/Presentation/Home/default.latte}

        Registro

        {control registrationForm} diff --git a/forms/fr/in-presenter.texy b/forms/fr/in-presenter.texy index 8f8bcb4739..1c87d106c6 100644 --- a/forms/fr/in-presenter.texy +++ b/forms/fr/in-presenter.texy @@ -30,7 +30,7 @@ Le formulaire dans le présentateur est un objet de la classe `Nette\Application Du point de vue du présentateur, le formulaire est un composant commun. Par conséquent, il est traité comme un composant et incorporé dans le présentateur à l'aide de la [méthode factory |application:components#Factory Methods]. Cela ressemblera à ceci : -```php .{file:app/Presenters/HomePresenter.php} +```php .{file:app/Presentation/Home/HomePresenter.php} use Nette; use Nette\Application\UI\Form; @@ -59,7 +59,7 @@ class HomePresenter extends Nette\Application\UI\Presenter Et le rendu dans le modèle est effectué à l'aide de la balise `{control}`: -```latte .{file:app/Presenters/templates/Home/default.latte} +```latte .{file:app/Presentation/Home/default.latte}

        Registration

        {control registrationForm} diff --git a/forms/hu/in-presenter.texy b/forms/hu/in-presenter.texy index 70f4742247..f52541b274 100644 --- a/forms/hu/in-presenter.texy +++ b/forms/hu/in-presenter.texy @@ -30,7 +30,7 @@ A prezenterben lévő űrlap a `Nette\Application\UI\Form` osztály objektuma, e A bemutató szempontjából az űrlap egy közös komponens. Ezért komponensként kezeljük, és a [factory metódus |application:components#Factory Methods] segítségével beépítjük a prezentálóba. Ez így fog kinézni: -```php .{file:app/Presenters/HomePresenter.php} +```php .{file:app/Presentation/Home/HomePresenter.php} use Nette; use Nette\Application\UI\Form; @@ -59,7 +59,7 @@ class HomePresenter extends Nette\Application\UI\Presenter A sablonban történő megjelenítés pedig a `{control}` tag használatával történik: -```latte .{file:app/Presenters/templates/Home/default.latte} +```latte .{file:app/Presentation/Home/default.latte}

        Registration

        {control registrationForm} diff --git a/forms/it/in-presenter.texy b/forms/it/in-presenter.texy index bf398c453b..3fbcb9e8b0 100644 --- a/forms/it/in-presenter.texy +++ b/forms/it/in-presenter.texy @@ -30,7 +30,7 @@ Il modulo nel presentatore è un oggetto della classe `Nette\Application\UI\Form Dal punto di vista del presentatore, il modulo è un componente comune. Pertanto, viene trattato come un componente e incorporato nel presentatore con il [metodo factory |application:components#Factory Methods]. L'aspetto sarà il seguente: -```php .{file:app/Presenters/HomePresenter.php} +```php .{file:app/Presentation/Home/HomePresenter.php} use Nette; use Nette\Application\UI\Form; @@ -59,7 +59,7 @@ class HomePresenter extends Nette\Application\UI\Presenter E il rendering nel template viene effettuato utilizzando il tag `{control}`: -```latte .{file:app/Presenters/templates/Home/default.latte} +```latte .{file:app/Presentation/Home/default.latte}

        Registration

        {control registrationForm} diff --git a/forms/pl/in-presenter.texy b/forms/pl/in-presenter.texy index afa333ac67..1a853df116 100644 --- a/forms/pl/in-presenter.texy +++ b/forms/pl/in-presenter.texy @@ -30,7 +30,7 @@ Formularz w prezenterze jest obiektem klasy `Nette\Application\UI\Form`, jego po Z punktu widzenia prezentera formularz jest normalnym komponentem. Dlatego traktujemy go jako komponent i włączamy do prezentera za pomocą [metody factory |application:components#Factory-Methods]. Będzie to wyglądało tak: -```php .{file:app/Presenters/HomePresenter.php} +```php .{file:app/Presentation/Home/HomePresenter.php} use Nette; use Nette\Application\UI\Form; @@ -59,7 +59,7 @@ class HomePresenter extends Nette\Application\UI\Presenter A w szablonie renderujemy formularz z tagiem `{control}`: -```latte .{file:app/Presenters/templates/Home/default.latte} +```latte .{file:app/Presentation/Home/default.latte}

        Registrace

        {control registrationForm} diff --git a/forms/pt/in-presenter.texy b/forms/pt/in-presenter.texy index a21a2650d3..3074969f86 100644 --- a/forms/pt/in-presenter.texy +++ b/forms/pt/in-presenter.texy @@ -30,7 +30,7 @@ A forma no apresentador é um objeto da classe `Nette\Application\UI\Form`, seu Do ponto de vista do apresentador, a forma é um componente comum. Portanto, ele é tratado como um componente e incorporado ao apresentador usando [o método de fábrica |application:components#Factory Methods]. Será parecido com isto: -```php .{file:app/Presenters/HomePresenter.php} +```php .{file:app/Presentation/Home/HomePresenter.php} use Nette; use Nette\Application\UI\Form; @@ -59,7 +59,7 @@ class HomePresenter extends Nette\Application\UI\Presenter E a renderização em modelo é feita usando a tag `{control}`: -```latte .{file:app/Presenters/templates/Home/default.latte} +```latte .{file:app/Presentation/Home/default.latte}

        Registration

        {control registrationForm} diff --git a/forms/ro/in-presenter.texy b/forms/ro/in-presenter.texy index 86b61b0e37..f5775f169d 100644 --- a/forms/ro/in-presenter.texy +++ b/forms/ro/in-presenter.texy @@ -30,7 +30,7 @@ Formularul din prezentator este un obiect din clasa `Nette\Application\UI\Form`, Din punctul de vedere al prezentatorului, formularul este o componentă comună. Prin urmare, acesta este tratat ca o componentă și încorporat în prezentator folosind [metoda factory |application:components#Factory Methods]. Acesta va arăta astfel: -```php .{file:app/Presenters/HomePresenter.php} +```php .{file:app/Presentation/Home/HomePresenter.php} use Nette; use Nette\Application\UI\Form; @@ -59,7 +59,7 @@ class HomePresenter extends Nette\Application\UI\Presenter Iar redarea în șablon se face cu ajutorul etichetei `{control}`: -```latte .{file:app/Presenters/templates/Home/default.latte} +```latte .{file:app/Presentation/Home/default.latte}

        Registration

        {control registrationForm} diff --git a/forms/ru/in-presenter.texy b/forms/ru/in-presenter.texy index ff2fa742cf..544b41b99a 100644 --- a/forms/ru/in-presenter.texy +++ b/forms/ru/in-presenter.texy @@ -30,7 +30,7 @@ $form->onSuccess[] = [$this, 'formSucceeded']; С точки зрения презентера форма является общим компонентом. Поэтому она рассматривается как компонент и включается в презентер с помощью [фабричного метода |application:components#Factory-Methods]. Это будет выглядеть следующим образом: -```php .{file:app/Presenters/HomePresenter.php} +```php .{file:app/Presentation/Home/HomePresenter.php} use Nette; use Nette\Application\UI\Form; @@ -59,7 +59,7 @@ class HomePresenter extends Nette\Application\UI\Presenter А рендеринг в шаблоне осуществляется с помощью тега `{control}`: -```latte .{file:app/Presenters/templates/Home/default.latte} +```latte .{file:app/Presentation/Home/default.latte}

        Регистрация

        {control registrationForm} diff --git a/forms/sl/in-presenter.texy b/forms/sl/in-presenter.texy index 807a389a7a..7a3dc4a994 100644 --- a/forms/sl/in-presenter.texy +++ b/forms/sl/in-presenter.texy @@ -30,7 +30,7 @@ Obrazec v predstavitvi je objekt razreda `Nette\Application\UI\Form`, njegov pre Z vidika predstavnika je obrazec skupna komponenta. Zato ga obravnavamo kot komponento in ga vključimo v predstavitveni program z uporabo [tovarniške metode |application:components#Factory Methods]. To bo videti takole: -```php .{file:app/Presenters/HomePresenter.php} +```php .{file:app/Presentation/Home/HomePresenter.php} use Nette; use Nette\Application\UI\Form; @@ -59,7 +59,7 @@ class HomePresenter extends Nette\Application\UI\Presenter Prikaz v predlogi pa se izvede z uporabo oznake `{control}`: -```latte .{file:app/Presenters/templates/Home/default.latte} +```latte .{file:app/Presentation/Home/default.latte}

        Registration

        {control registrationForm} diff --git a/forms/tr/in-presenter.texy b/forms/tr/in-presenter.texy index 09764a3ad0..e6c90c59b2 100644 --- a/forms/tr/in-presenter.texy +++ b/forms/tr/in-presenter.texy @@ -30,7 +30,7 @@ Sunucudaki form `Nette\Application\UI\Form` sınıfının bir nesnesidir, selefi Sunucunun bakış açısından, form ortak bir bileşendir. Bu nedenle, bir bileşen olarak ele alınır ve [fabrika yöntemi |application:components#Factory Methods] kullanılarak sunucuya dahil edilir. Bu şekilde görünecektir: -```php .{file:app/Presenters/HomePresenter.php} +```php .{file:app/Presentation/Home/HomePresenter.php} use Nette; use Nette\Application\UI\Form; @@ -59,7 +59,7 @@ class HomePresenter extends Nette\Application\UI\Presenter Ve şablonda render işlemi `{control}` etiketi kullanılarak yapılır: -```latte .{file:app/Presenters/templates/Home/default.latte} +```latte .{file:app/Presentation/Home/default.latte}

        Registration

        {control registrationForm} diff --git a/forms/uk/in-presenter.texy b/forms/uk/in-presenter.texy index de72fb81d7..b8f078928b 100644 --- a/forms/uk/in-presenter.texy +++ b/forms/uk/in-presenter.texy @@ -30,7 +30,7 @@ $form->onSuccess[] = [$this, 'formSucceeded']; З точки зору презентера форма є загальним компонентом. Тому вона розглядається як компонент і включається в презентер за допомогою [фабричного методу |application:components#Factory-Methods]. Це виглядатиме наступним чином: -```php .{file:app/Presenters/HomePresenter.php} +```php .{file:app/Presentation/Home/HomePresenter.php} use Nette; use Nette\Application\UI\Form; @@ -59,7 +59,7 @@ class HomePresenter extends Nette\Application\UI\Presenter А рендеринг у шаблоні здійснюється за допомогою тега `{control}`: -```latte .{file:app/Presenters/templates/Home/default.latte} +```latte .{file:app/Presentation/Home/default.latte}

        Регистрация

        {control registrationForm} diff --git a/latte/bg/template-inheritance.texy b/latte/bg/template-inheritance.texy index 029d5cf9b3..f25013bc40 100644 --- a/latte/bg/template-inheritance.texy +++ b/latte/bg/template-inheritance.texy @@ -132,7 +132,7 @@ - Ако използвате `{layout}` в шаблон, той трябва да бъде първият таг на шаблона в този шаблон. -- Макетът може да се [търси автоматично |develop#automatic-layout-lookup] (както в [презентаторите |application:templates#search-for-templates]). В този случай, ако шаблонът не трябва да има оформление, той ще посочи това с тага `{layout none}`. +- Макетът може да се [търси автоматично |develop#automatic-layout-lookup] (както в [презентаторите |application:templates#Template Lookup]). В този случай, ако шаблонът не трябва да има оформление, той ще посочи това с тага `{layout none}`. - Тагът `{layout}` има псевдоним `{extends}`. diff --git a/latte/de/template-inheritance.texy b/latte/de/template-inheritance.texy index 1741888e5e..0f57bdd16e 100644 --- a/latte/de/template-inheritance.texy +++ b/latte/de/template-inheritance.texy @@ -132,7 +132,7 @@ Hier finden Sie einige Tipps für die Arbeit mit Layoutvererbung: - Wenn Sie `{layout}` in einer Vorlage verwenden, muss es das erste Vorlagen-Tag in dieser Vorlage sein. -- Das Layout kann [automatisch gesucht |develop#automatic-layout-lookup] werden (wie bei [Präsentationen |application:templates#search-for-templates]). In diesem Fall, wenn die Vorlage kein Layout haben sollte, wird dies mit dem Tag `{layout none}` angezeigt. +- Das Layout kann [automatisch gesucht |develop#automatic-layout-lookup] werden (wie bei [Präsentationen |application:templates#Template Lookup]). In diesem Fall, wenn die Vorlage kein Layout haben sollte, wird dies mit dem Tag `{layout none}` angezeigt. - Das Tag `{layout}` hat den Alias `{extends}`. diff --git a/latte/el/template-inheritance.texy b/latte/el/template-inheritance.texy index 1c544fdb1b..321ee58522 100644 --- a/latte/el/template-inheritance.texy +++ b/latte/el/template-inheritance.texy @@ -132,7 +132,7 @@ - Εάν χρησιμοποιείτε το `{layout}` σε ένα πρότυπο, πρέπει να είναι η πρώτη ετικέτα προτύπου σε αυτό το πρότυπο. -- Η διάταξη μπορεί να [αναζητηθεί αυτόματα |develop#automatic-layout-lookup] (όπως στους [παρουσιαστές |application:templates#search-for-templates]). Σε αυτή την περίπτωση, αν το πρότυπο δεν πρέπει να έχει διάταξη, θα το υποδείξει με την ετικέτα `{layout none}`. +- Η διάταξη μπορεί να [αναζητηθεί αυτόματα |develop#automatic-layout-lookup] (όπως στους [παρουσιαστές |application:templates#Template Lookup]). Σε αυτή την περίπτωση, αν το πρότυπο δεν πρέπει να έχει διάταξη, θα το υποδείξει με την ετικέτα `{layout none}`. - Η ετικέτα `{layout}` έχει ψευδώνυμο `{extends}`. diff --git a/latte/en/template-inheritance.texy b/latte/en/template-inheritance.texy index 5294812f14..9e734e9382 100644 --- a/latte/en/template-inheritance.texy +++ b/latte/en/template-inheritance.texy @@ -132,7 +132,7 @@ Here are some tips for working with layout inheritance: - If you use `{layout}` in a template, it must be the first template tag in that template. -- Layout can be [searched automatically |develop#automatic-layout-lookup] (like in [presenters |application:templates#search-for-templates]). In this case, if the template should not have a layout, it will indicate this with the `{layout none}` tag. +- Layout can be [searched automatically |develop#automatic-layout-lookup] (like in [presenters |application:templates#Template Lookup]). In this case, if the template should not have a layout, it will indicate this with the `{layout none}` tag. - Tag `{layout}` has alias `{extends}`. diff --git a/latte/es/template-inheritance.texy b/latte/es/template-inheritance.texy index 61607723aa..f3d3b430cc 100644 --- a/latte/es/template-inheritance.texy +++ b/latte/es/template-inheritance.texy @@ -132,7 +132,7 @@ Aquí tienes algunos consejos para trabajar con la herencia de diseños: - Si utiliza `{layout}` en una plantilla, debe ser la primera etiqueta de plantilla en esa plantilla. -- La maquetación puede [buscarse automáticamente |develop#automatic-layout-lookup] (como en [los presentadores |application:templates#search-for-templates]). En este caso, si la plantilla no debe tener un diseño, lo indicará con la etiqueta `{layout none}`. +- La maquetación puede [buscarse automáticamente |develop#automatic-layout-lookup] (como en [los presentadores |application:templates#Template Lookup]). En este caso, si la plantilla no debe tener un diseño, lo indicará con la etiqueta `{layout none}`. - La etiqueta `{layout}` tiene el alias `{extends}`. diff --git a/latte/fr/template-inheritance.texy b/latte/fr/template-inheritance.texy index d0b17c5615..f8dbf93934 100644 --- a/latte/fr/template-inheritance.texy +++ b/latte/fr/template-inheritance.texy @@ -132,7 +132,7 @@ Voici quelques conseils pour travailler avec l'héritage de mise en page : - Si vous utilisez `{layout}` dans un modèle, il doit s'agir de la première balise de modèle de ce modèle. -- La mise en page peut être [recherchée automatiquement |develop#automatic-layout-lookup] (comme dans les [présentateurs |application:templates#search-for-templates]). Dans ce cas, si le modèle ne doit pas avoir de mise en page, il l'indiquera avec la balise `{layout none}`. +- La mise en page peut être [recherchée automatiquement |develop#automatic-layout-lookup] (comme dans les [présentateurs |application:templates#Template Lookup]). Dans ce cas, si le modèle ne doit pas avoir de mise en page, il l'indiquera avec la balise `{layout none}`. - La balise `{layout}` a un alias `{extends}`. diff --git a/latte/hu/template-inheritance.texy b/latte/hu/template-inheritance.texy index eee1de2384..561a7bae06 100644 --- a/latte/hu/template-inheritance.texy +++ b/latte/hu/template-inheritance.texy @@ -132,7 +132,7 @@ Tippek .[#toc-tips] - Ha a `{layout}` címet használja egy sablonban, akkor annak a sablonban az első sabloncímkének kell lennie. -- Az elrendezés [automatikusan kereshető |develop#automatic-layout-lookup] (mint [az előadókban |application:templates#search-for-templates]). Ebben az esetben, ha a sablonban nem kell elrendezés, akkor ezt a `{layout none}` címkével jelzi. +- Az elrendezés [automatikusan kereshető |develop#automatic-layout-lookup] (mint [az előadókban |application:templates#Template Lookup]). Ebben az esetben, ha a sablonban nem kell elrendezés, akkor ezt a `{layout none}` címkével jelzi. - A `{layout}` címkének a `{extends}` aliasával rendelkezik. diff --git a/latte/it/template-inheritance.texy b/latte/it/template-inheritance.texy index ede86caa3c..be6be739eb 100644 --- a/latte/it/template-inheritance.texy +++ b/latte/it/template-inheritance.texy @@ -132,7 +132,7 @@ Ecco alcuni suggerimenti per lavorare con l'ereditarietà dei layout: - Se si usa `{layout}` in un modello, deve essere il primo tag del modello in quel modello. -- Il layout può essere [cercato automaticamente |develop#automatic-layout-lookup] (come nei [presentatori |application:templates#search-for-templates]). In questo caso, se il modello non deve avere un layout, lo indicherà con il tag `{layout none}`. +- Il layout può essere [cercato automaticamente |develop#automatic-layout-lookup] (come nei [presentatori |application:templates#Template Lookup]). In questo caso, se il modello non deve avere un layout, lo indicherà con il tag `{layout none}`. - Il tag `{layout}` ha l'alias `{extends}`. diff --git a/latte/ja/template-inheritance.texy b/latte/ja/template-inheritance.texy index a1fb0e9823..6ed251797f 100644 --- a/latte/ja/template-inheritance.texy +++ b/latte/ja/template-inheritance.texy @@ -132,7 +132,7 @@ Latteのテンプレート継承のコンセプトは、PHPのクラス継承に - テンプレート内で`{layout}` を使用する場合、そのテンプレート内の最初のテンプレートタグでなければなりません。 -- レイアウトは[自動的に検索 |develop#automatic-layout-lookup]することができます([プレゼンターの |application:en:templates#search-for-templates]ように)。この場合、テンプレートがレイアウトを持つべきではない場合は、`{layout none}` タグでその旨を表示します。 +- レイアウトは[自動的に検索 |develop#automatic-layout-lookup]することができます([プレゼンターの |application:en:templates#Template Lookup]ように)。この場合、テンプレートがレイアウトを持つべきではない場合は、`{layout none}` タグでその旨を表示します。 - タグ`{layout}` はエイリアス`{extends}` を持ちます。 diff --git a/latte/pl/template-inheritance.texy b/latte/pl/template-inheritance.texy index 2488266e2b..25483c9fab 100644 --- a/latte/pl/template-inheritance.texy +++ b/latte/pl/template-inheritance.texy @@ -132,7 +132,7 @@ Oto kilka wskazówek dotyczących pracy z dziedziczeniem układów: - Jeśli używasz `{layout}` w szablonie , musi to być pierwszy tag szablonu w tym szablonie. -- Układ może być [wyszukiwany automatycznie |develop#automatic-layout-lookup] (jak w [prezenterach |application:templates#search-for-templates]). W takim przypadku, jeśli szablon nie powinien mieć układu, wskaże to za pomocą znacznika `{layout none}`. +- Układ może być [wyszukiwany automatycznie |develop#automatic-layout-lookup] (jak w [prezenterach |application:templates#Template Lookup]). W takim przypadku, jeśli szablon nie powinien mieć układu, wskaże to za pomocą znacznika `{layout none}`. - Znacznik `{layout}` ma alias `{extends}`. diff --git a/latte/pt/template-inheritance.texy b/latte/pt/template-inheritance.texy index 2a426f0cd7..daf38bde1b 100644 --- a/latte/pt/template-inheritance.texy +++ b/latte/pt/template-inheritance.texy @@ -132,7 +132,7 @@ Aqui estão algumas dicas para trabalhar com a herança de layout: - Se você usar `{layout}` em um template, ele deve ser a primeira etiqueta do template nesse template. -- O layout pode ser [pesquisado automaticamente |develop#automatic-layout-lookup] (como nos [apresentadores |application:templates#search-for-templates]). Nesse caso, se o modelo não tiver um layout, ele indicará isso com a tag `{layout none}`. +- O layout pode ser [pesquisado automaticamente |develop#automatic-layout-lookup] (como nos [apresentadores |application:templates#Template Lookup]). Nesse caso, se o modelo não tiver um layout, ele indicará isso com a tag `{layout none}`. - A tag `{layout}` tem o pseudônimo `{extends}`. diff --git a/latte/ro/template-inheritance.texy b/latte/ro/template-inheritance.texy index 77075ed241..4b8ffe5bdc 100644 --- a/latte/ro/template-inheritance.texy +++ b/latte/ro/template-inheritance.texy @@ -132,7 +132,7 @@ Iată câteva sfaturi pentru a lucra cu moștenirea aspectului: - Dacă utilizați `{layout}` într-un șablon, trebuie să fie prima etichetă de șablon din șablonul respectiv. -- Layout-ul poate fi [căutat în mod automat |develop#automatic-layout-lookup] (la fel ca în [prezentări |application:templates#search-for-templates]). În acest caz, dacă șablonul nu ar trebui să aibă un layout, se va indica acest lucru cu eticheta `{layout none}`. +- Layout-ul poate fi [căutat în mod automat |develop#automatic-layout-lookup] (la fel ca în [prezentări |application:templates#Template Lookup]). În acest caz, dacă șablonul nu ar trebui să aibă un layout, se va indica acest lucru cu eticheta `{layout none}`. - Eticheta `{layout}` are aliasul `{extends}`. diff --git a/latte/ru/template-inheritance.texy b/latte/ru/template-inheritance.texy index bc728af54a..362f08b420 100644 --- a/latte/ru/template-inheritance.texy +++ b/latte/ru/template-inheritance.texy @@ -132,7 +132,7 @@ - Если вы используете `{layout}` в шаблоне, он должен быть первым тегом шаблона в этом шаблоне. -- Макет может [искаться автоматически |develop#automatic-layout-lookup] (как в [презентаторах |application:templates#search-for-templates]). В этом случае, если шаблон не должен иметь макета, он укажет на это с помощью тега `{layout none}`. +- Макет может [искаться автоматически |develop#automatic-layout-lookup] (как в [презентаторах |application:templates#Template Lookup]). В этом случае, если шаблон не должен иметь макета, он укажет на это с помощью тега `{layout none}`. - Тег `{layout}` имеет псевдоним `{extends}`. diff --git a/latte/sl/template-inheritance.texy b/latte/sl/template-inheritance.texy index e5b6da9144..d749775406 100644 --- a/latte/sl/template-inheritance.texy +++ b/latte/sl/template-inheritance.texy @@ -132,7 +132,7 @@ Tukaj je nekaj nasvetov za delo z dedovanjem postavitve: - Če v predlogi uporabite `{layout}`, mora biti to prva oznaka v predlogi. -- Postavitev lahko [iščete samodejno |develop#automatic-layout-lookup] (kot v [predstavitvah |application:templates#search-for-templates]). Če v tem primeru predloga ne sme imeti postavitve, se to označi z oznako `{layout none}`. +- Postavitev lahko [iščete samodejno |develop#automatic-layout-lookup] (kot v [predstavitvah |application:templates#Template Lookup]). Če v tem primeru predloga ne sme imeti postavitve, se to označi z oznako `{layout none}`. - Oznaka `{layout}` ima vzdevek `{extends}`. diff --git a/latte/tr/template-inheritance.texy b/latte/tr/template-inheritance.texy index 92db9e8c6c..b681815e53 100644 --- a/latte/tr/template-inheritance.texy +++ b/latte/tr/template-inheritance.texy @@ -132,7 +132,7 @@ Düzen kalıtımı ile çalışmak için bazı ipuçları: - Bir şablonda `{layout}` kullanıyorsanız, bu şablondaki ilk şablon etiketi olmalıdır. -- Düzen [otomatik olarak aranabilir |develop#automatic-layout-lookup] ( [sunumlarda |application:templates#search-for-templates] olduğu gibi). Bu durumda, şablonun bir düzene sahip olmaması gerekiyorsa, bunu `{layout none}` etiketi ile belirtecektir. +- Düzen [otomatik olarak aranabilir |develop#automatic-layout-lookup] ( [sunumlarda |application:templates#Template Lookup] olduğu gibi). Bu durumda, şablonun bir düzene sahip olmaması gerekiyorsa, bunu `{layout none}` etiketi ile belirtecektir. - `{layout}` etiketinin `{extends}` takma adı vardır. diff --git a/latte/uk/template-inheritance.texy b/latte/uk/template-inheritance.texy index 0db6e1062e..c4fd39ba89 100644 --- a/latte/uk/template-inheritance.texy +++ b/latte/uk/template-inheritance.texy @@ -132,7 +132,7 @@ - Якщо ви використовуєте `{layout}` у шаблоні, він має бути першим тегом шаблону в цьому шаблоні. -- Макет можна [шукати автоматично |develop#automatic-layout-lookup] (як у [презентаторах |application:templates#search-for-templates]). У цьому випадку, якщо шаблон не повинен мати макет, він вкаже на це тегом `{layout none}`. +- Макет можна [шукати автоматично |develop#automatic-layout-lookup] (як у [презентаторах |application:templates#Template Lookup]). У цьому випадку, якщо шаблон не повинен мати макет, він вкаже на це тегом `{layout none}`. - Тег `{layout}` має псевдонім `{extends}`. diff --git a/quickstart/bg/@home.texy b/quickstart/bg/@home.texy index 6a69c02c80..802e6dba2b 100644 --- a/quickstart/bg/@home.texy +++ b/quickstart/bg/@home.texy @@ -45,9 +45,9 @@ http://localhost/nette-blog/www/ /--pre nette-blog/ ├── app/ ← каталог приложения -│ ├── Presenters/ ← классы презентеров -│ │ └── templates/← шаблоны -│ ├── Router/ ← конфигурация адресов URL +│ ├── Core/ ← основни необходими класове +│ ├── Presentation/ ← презентатори, шаблони и др. +│ │ └── Home/ ← Каталог на водещите │ └── Bootstrap.php ← загрузочный класс Bootstrap ├── bin/ ← скрипты для командной строки ├── config/ ← конфигурационные файлы @@ -67,7 +67,7 @@ http://localhost/nette-blog/www/ Почистване .[#toc-cleanup] ========================== -Уеб проектът съдържа начална страница, която можем да премахнем - не се колебайте да замените съдържанието на файла `app/Presenters/templates/Home/default.latte` с текста `Hello world!`. +Уеб проектът съдържа начална страница, която можем да премахнем - не се колебайте да замените съдържанието на файла `app/Presentation/Home/default.latte` с текста `Hello world!`. [* qs-hello.webp .{url:-} *] @@ -76,9 +76,9 @@ http://localhost/nette-blog/www/ Tracy (дебъгер) .[#toc-tracy-debugger] ====================================== -Изключително важен инструмент за разработка е [дебъгер, наречен Tracy. |tracy:] Опитайте се да направите някои грешки във вашия файл `app/Presenters/HomePresenter.php` (например да премахнете къдравата скоба от дефиницията на класа HomePresenter) и вижте какво ще се случи. Ще се появи страница с червен екран и разбираемо описание на грешката. +Изключително важен инструмент за разработка е [дебъгер, наречен Tracy. |tracy:] Опитайте се да направите някои грешки във вашия файл `app/Presentation/Home/HomePresenter.php` (например да премахнете къдравата скоба от дефиницията на класа HomePresenter) и вижте какво ще се случи. Ще се появи страница с червен екран и разбираемо описание на грешката. -[* qs-tracy.webp .{url:-}(debugger screen) *] +[* qs-tracy.avif .{url:-}(debugger screen) *] Трейси ще ви помогне значително да откриете грешките. Обърнете внимание и на плаващата лента Tracy Bar в долния десен ъгъл, която ви информира за важни данни по време на работа. diff --git a/quickstart/bg/authentication.texy b/quickstart/bg/authentication.texy index 4950637a2b..6dcc3dc766 100644 --- a/quickstart/bg/authentication.texy +++ b/quickstart/bg/authentication.texy @@ -28,9 +28,9 @@ Nette автоматично ще създаде услуга в контейн Нека започнем с формата за вход. Вече знаете как работят формулярите в програмата Presenter. Създайте `SignPresenter` и метод `createComponentSignInForm`. Това трябва да изглежда по следния начин: -```php .{file:app/Presenters/SignPresenter.php} +```php .{file:app/Presentation/Sign/SignPresenter.php} Войти @@ -77,7 +77,7 @@ final class SignPresenter extends Nette\Application\UI\Presenter Обслужващият модул просто взема потребителското име и паролата, които потребителят е въвел, и ги предава на удостоверителя. След като влезете в системата, ще ви пренасочим към началната страница: -```php .{file:app/Presenters/SignPresenter.php} +```php .{file:app/Presentation/Sign/SignPresenter.php} private function signInFormSucceeded(Form $form, \stdClass $data): void { try { @@ -102,7 +102,7 @@ private function signInFormSucceeded(Form $form, \stdClass $data): void Ще създадем метод `startup()`, който се изпълнява веднага в началото на [жизнения цикъл на презентатора |application:presenters#Life-Cycle-of-Presenter]. Това пренасочва нерегистрираните потребители към формата за вход. -```php .{file:app/Presenters/EditPresenter.php} +```php .{file:app/Presentation/Edit/EditPresenter.php} public function startup(): void { parent::startup(); @@ -117,7 +117,7 @@ public function startup(): void Скриване на връзки .[#toc-hide-links] ------------------------------------- -Неоторизиран потребител вече не може да вижда страниците за създаване и редактиране, но все още може да вижда връзките, които сочат към тях. Нека скрием и тях. Една такава връзка се намира на адрес `app/Presenters/templates/Home/default.latte`, като тя трябва да бъде видима само ако потребителят е влязъл в системата. +Неоторизиран потребител вече не може да вижда страниците за създаване и редактиране, но все още може да вижда връзките, които сочат към тях. Нека скрием и тях. Една такава връзка се намира на адрес `app/Presentation/Home/default.latte`, като тя трябва да бъде видима само ако потребителят е влязъл в системата. Можем да го скрием, като използваме *n:атрибута*, наречен `n:if`. Ако изявлението в него е `false`, тогава целият таг `` и съдържанието му няма да бъде показано: @@ -131,15 +131,15 @@ public function startup(): void {if $user->isLoggedIn()}Создать пост{/if} ``` -По същия начин скрийте връзката за редактиране, намираща се на адрес `app/Presenters/templates/Post/show.latte`. +По същия начин скрийте връзката за редактиране, намираща се на адрес `app/Presentation/Post/show.latte`. Връзка към формуляра за влизане .[#toc-login-form-link] ======================================================= -Здравейте, но как да стигнем до страницата за вход? Няма връзка, която да сочи към него. Нека да го добавим към файла с шаблона `app/Presenters/templates/@layout.latte`. Опитайте се да намерите добро място, може да е всяко място, което ви харесва най-много. +Здравейте, но как да стигнем до страницата за вход? Няма връзка, която да сочи към него. Нека да го добавим към файла с шаблона `app/Presentation/@layout.latte`. Опитайте се да намерите добро място, може да е всяко място, което ви харесва най-много. -```latte .{file:app/Presenters/templates/@layout.latte} +```latte .{file:app/Presentation/@layout.latte} ...