From 50766d0a92dad29cf7111ae9883db22b7ce530f2 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 15 Apr 2024 19:37:06 +0200 Subject: [PATCH] new directory structure [WIP] --- application/cs/how-it-works.texy | 14 +++---- application/cs/modules.texy | 45 +++++++++++----------- application/cs/routing.texy | 10 ++--- application/cs/templates.texy | 6 +-- best-practices/cs/composer.texy | 2 +- best-practices/cs/pagination.texy | 10 ++--- dependency-injection/cs/configuration.texy | 2 +- dependency-injection/cs/factory.texy | 2 +- forms/cs/in-presenter.texy | 4 +- quickstart/cs/authentication.texy | 14 +++---- quickstart/cs/comments.texy | 10 ++--- quickstart/cs/creating-posts.texy | 16 ++++---- quickstart/cs/home-page.texy | 16 ++++---- quickstart/cs/model.texy | 4 +- quickstart/cs/single-post.texy | 14 +++---- robot-loader/cs/@home.texy | 2 +- tracy/cs/guide.texy | 6 +-- 17 files changed, 88 insertions(+), 89 deletions(-) diff --git a/application/cs/how-it-works.texy b/application/cs/how-it-works.texy index 92ff5e9d9b..4d29e63861 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í systémové třídy +│ │ └── RouterFactory.php ← konfigurace URL adres +│ ├── UI/ ← presentery, šablony a pomocné třídy +│ │ ├── @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 diff --git a/application/cs/modules.texy b/application/cs/modules.texy index dd58b910d4..8a962c762d 100644 --- a/application/cs/modules.texy +++ b/application/cs/modules.texy @@ -10,21 +10,22 @@ Zapomeňme tedy na jednu složku pro presentery a šablony a místo toho vytvoř /--pre app/ -├── Presenters/ -├── Modules/ ← adresář s moduly +├── UI/ ← presentery, šablony a pomocné třídy +│ ├── @layout.latte ← šablona layoutu │ ├── Admin/ ← modul Admin -│ │ ├── Presenters/ ← jeho presentery -│ │ │ ├── DashboardPresenter.php -│ │ │ └── templates/ -│ └── Front/ ← modul Front -│ └── Presenters/ ← jeho presentery +│ │ │ ├── Dashboard/ +│ │ │ │ └── DashboardPresenter.php +│ ├── Front/ ← modul Front +│ │ ├── Home/ ← adresář presenteru Home +│ │ │ ├── HomePresenter.php ← třída presenteru Home +│ │ │ └── default.latte ← šablona akce 'default' │ └── ... \-- -Tuto adresářovou strukturu budou reflektovat jmenné prostory tříd, takže třeba `DashboardPresenter` bude v prostoru `App\Modules\Admin\Presenters`: +Tuto adresářovou strukturu budou reflektovat jmenné prostory tříd, takže třeba `DashboardPresenter` bude v prostoru `App\UI\Admin`: ```php -namespace App\Modules\Admin\Presenters; +namespace App\UI\Admin\Dashboard; class DashboardPresenter extends Nette\Application\UI\Presenter { @@ -33,7 +34,7 @@ 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. +A jak Nette vlastní ví, že `Admin:Dashboard` představuje třídu `App\UI\Admin\Dashboard\DashboardPresenter`? To mu řekneme pomocí [#mapování] v konfiguraci. Tedy uvedená struktura není pevná a můžete si ji upravit podle potřeb. Moduly mohou kromě presenterů a šablon samozřejmě obsahovat všechny další součásti, jako jsou třeba komponenty, modelové třídy, atd. @@ -46,19 +47,19 @@ Moduly nemusí tvořit jen plochou strukturu, lze vytvářet i submoduly, např /--pre app/ -├── Modules/ ← adresář s moduly +├── UI/ ← presentery, šablony a pomocné třídy │ ├── Blog/ ← modul Blog │ │ ├── Admin/ ← submodul Admin -│ │ │ ├── Presenters/ +│ │ │ ├── Dashboard/ │ │ │ └── ... │ │ └── Front/ ← submodul Front -│ │ ├── Presenters/ +│ │ ├── Home/ │ │ └── ... │ ├── 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`. +Tedy modul `Blog` je rozdělen do submodulů `Admin` a `Front`. A opět se to odrazí na jmenných prostorech, které budou `App\UI\Blog\Admin\...` apod. Na presenter `Dashboard` uvnitř submodulu se odkazujeme jako `Blog:Admin:Dashboard`. Zanořování může pokračovat libovolně hluboko, lze tedy vytvářet sub-submoduly. @@ -104,11 +105,11 @@ 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`. -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í: +Začněme ukázkou, která moduly nepoužívá. Budeme jen chtít, aby třídy presenterů měly jmenný prostor `App\UI`. Tedy aby se presenter například `Home` mapoval na třídu `App\UI\HomePresenter`. Toho lze docílit následující konfigurací: ```neon application: - mapping: App\Presenters\*Presenter + mapping: App\UI\*Presenter ``` Název presenteru se nahradí za hvezdičku v masce třídy a výsledkem je název třídy. Snadné! @@ -118,30 +119,30 @@ Pokud presentery členíme do modulů, můžeme pro každý modul mít vlastní ```neon application: mapping: - Front: App\Modules\Front\Presenters\*Presenter - Admin: App\Modules\Admin\Presenters\*Presenter + Front: App\UI\Front\*Presenter + Admin: App\UI\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`. +Nyní se presenter `Front:Home` mapuje na třídu `App\UI\Front\HomePresenter` a presenter `Admin:Dashboard` na třídu `App\UI\Admin\DashboardPresenter`. 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: ```neon application: mapping: - *: App\Modules\*\Presenters\*Presenter + *: App\UI\*\*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`. +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\UI\Admin\User\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] ``` Výchozí hodnotou je `*Module\*Presenter`. diff --git a/application/cs/routing.texy b/application/cs/routing.texy index 3f58166681..0c04944a28 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/cs/templates.texy b/application/cs/templates.texy index 5d0de8dc1a..2a7d61caf8 100644 --- a/application/cs/templates.texy +++ b/application/cs/templates.texy @@ -104,7 +104,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\UI\Article\ArticleTemplate} ... ``` @@ -176,7 +176,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\UI\Accessory; final class LatteExtension extends Latte\Extension { @@ -214,7 +214,7 @@ Zaregistrujeme ji pomocí [konfigurace |configuration#Šablony Latte]: ```neon latte: extensions: - - App\Templating\LatteExtension + - App\UI\Accessory\LatteExtension ``` 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/pagination.texy b/best-practices/cs/pagination.texy index bf7d18a418..8a558bb0b7 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\UI\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\UI\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\UI\Home; use Nette; use App\Model\ArticleRepository; diff --git a/dependency-injection/cs/configuration.texy b/dependency-injection/cs/configuration.texy index 4b80e78339..0ae0adcd06 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\UI\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/forms/cs/in-presenter.texy b/forms/cs/in-presenter.texy index e8d3bddccd..807bdb1822 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/UI/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/UI/Home/default.latte}

Registrace

{control registrationForm} diff --git a/quickstart/cs/authentication.texy b/quickstart/cs/authentication.texy index 82dd6e5861..39dae88c16 100644 --- a/quickstart/cs/authentication.texy +++ b/quickstart/cs/authentication.texy @@ -28,9 +28,9 @@ Nyní máme autentifikaci připravenu a musíme připravit uživatelské rozhran Začneme s přihlašovacím formulářem. Již víme, jak formuláře v presenterech fungují. Vytvoříme si tedy presenter `SignPresenter` a zapíšeme metodu `createComponentSignInForm`. Měl by vypadat nějak takto: -```php .{file:app/Presenters/SignPresenter.php} +```php .{file:app/UI/Sign/SignPresenter.php} Přihlášení @@ -77,7 +77,7 @@ Dále doplníme callback pro přihlášení uživatele, který bude volán hned Callback pouze převezme uživatelské jméno a heslo, které uživatel vyplnil a předá je authenticatoru. Po přihlášení přesměrujeme na úvodní stránku. -```php .{file:app/Presenters/SignPresenter.php} +```php .{file:app/UI/Sign/SignPresenter.php} private function signInFormSucceeded(Form $form, \stdClass $data): void { try { @@ -102,7 +102,7 @@ Zabezpečíme formulář pro přidávání a editování příspěvků. Ten je d Vytvoříme metodu `startup()`, která se spouští ihned na začátku [životního cyklu presenteru|application:presenters#zivotni-cyklus-presenteru]. Ta přesměruje nepřihlášené uživatele na formulář s přihlášením. -```php .{file:app/Presenters/EditPresenter.php} +```php .{file:app/UI/Edit/EditPresenter.php} public function startup(): void { parent::startup(); @@ -139,7 +139,7 @@ Odkaz na přihlášení Jak se vlastně dostaneme na přihlašovací stránku? Není zde žádný odkaz, který by na ni vedl. Tak si ho tedy přidáme do šablony `@layout.latte`. Pokuste se najít vhodné místo - může to být téměř kdekoliv. -```latte .{file:app/Presenters/templates/@layout.latte} +```latte .{file:app/UI/@layout.latte} ...