Moduły
Moduły zapewniają przejrzystość aplikacji Nette, ułatwiając podział na logiczne jednostki.
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:
app/ ├── UI/ │ ├── Admin/ ← Admin module │ │ ├── @layout.latte │ │ ├── Dashboard/ │ │ │ ├── DashboardPresenter.php │ │ │ └── default.latte │ │ └── ... │ ├── Front/ ← Front module │ │ ├── @layout.latte │ │ ├── Home/ │ │ │ ├── HomePresenter.php │ │ │ └── default.latte │ │ └── ...
Ta struktura katalogów jest odzwierciedlona w przestrzeniach nazw klas, więc na przykład DashboardPresenter
znajduje się w przestrzeni nazw App\UI\Admin\Dashboard
:
namespace App\UI\Admin\Dashboard;
class DashboardPresenter extends Nette\Application\UI\Presenter
{
// ...
}
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
.
Przedstawiona struktura nie jest sztywna; można ją w pełni dostosować do własnych potrzeb w konfiguracji.
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
:
app/ ├── UI/ │ ├── Admin/ │ │ ├── Accessory/ │ │ │ ├── FormFactory.php │ │ │ └── AdminLayout.php │ │ ├── Dashboard/ │ │ └── ...
Moduły zagnieżdżone
Moduły mogą mieć wiele poziomów zagnieżdżenia, podobnie jak struktura katalogów na dysku:
app/ ├── UI/ │ ├── Blog/ ← Blog module │ │ ├── Admin/ ← Admin submodule │ │ │ ├── Dashboard/ │ │ │ └── ... │ │ ├── Front/ ← Front submodule │ │ │ ├── @layout.latte │ │ │ ├── Home/ │ │ │ └── ... │ ├── Forum/ ← Forum module │ │ └── ...
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\UI\Blog\Admin
i podobnie. Aby
odnieść się do prezentera Dashboard
w podmodule Admin
, odnosimy się do niego jako
Blog:Admin:Dashboard
.
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
Linki w szablonach prezenterów są względne do bieżącego modułu. Tak więc link Foo:default
prowadzi do
prezentera Foo
w tym samym module co aktualny prezenter. Na przykład, jeśli bieżący moduł to Front
,
to link idzie tak:
<a n:href="Product:show">odkaz na Front:Product:show</a>
Link jest względny, nawet jeśli nazwa modułu jest jego częścią, jest wtedy uważany za submoduł:
<a n:href="Shop:Product:show">odkaz na Front:Shop:Product:show</a>
Odwołania bezwzględne są zapisywane analogicznie do ścieżek bezwzględnych na dysku, ale z dwukropkami zamiast ukośników. Tak więc link bezwzględny zaczyna się od dwukropka:
<a n:href=":Admin:Product:show">odkaz na Admin:Product:show</a>
Aby dowiedzieć się, czy jesteśmy w danym module lub submodule, korzystamy z funkcji
isModuleCurrent(moduleName)
.
<li n:class="isModuleCurrent('Forum:Users') ? active">
<a n:href="Product:">...</a>
</li>
Routing
Patrz rozdział dotyczący routingu.
Mapowanie
Mapowanie definiuje zasady wyprowadzania nazwy klasy z nazwy prezentera. Reguły te są określone w konfiguracji pod kluczem application › mapping
.
Struktury katalogów wspomniane wcześniej na tej stronie są oparte na następującym mapowaniu:
application:
mapping: App\UI\*\**Presenter
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\UI\HomePresenter
. Można to osiągnąć za pomocą tej konfiguracji:
application:
mapping: App\UI\*Presenter
Mapowanie to polega na zastąpieniu gwiazdki w masce App\UI\*Presenter
nazwą prezentera Home
, co
daje końcową nazwę klasy App\UI\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\UI\Home\HomePresenter
. Osiąga się to poprzez
podwojenie gwiazdki (wymaga Nette Application 3.2):
application:
mapping: App\UI\**Presenter
Przejdźmy teraz do mapowania prezenterów na moduły. Możemy zdefiniować konkretne mapowania dla każdego modułu:
application:
mapping:
Front: App\UI\Front\**Presenter
Admin: App\UI\Admin\**Presenter
Api: App\Api\*Presenter
Zgodnie z tą konfiguracją, prezenter Front:Home
mapuje się do klasy
App\UI\Front\Home\HomePresenter
, podczas gdy prezenter Api:OAuth
mapuje się do klasy
App\Api\OAuthPresenter
.
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:
application:
mapping:
*: App\UI\*\**Presenter
Api: App\Api\*Presenter
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\UI\Admin\User\Edit\EditPresenter
.
Alternatywnym zapisem jest użycie tablicy złożonej z trzech segmentów zamiast łańcucha. Ta notacja jest równoważna poprzedniej:
application:
mapping:
*: [App\UI, *, **Presenter]
Api: [App\Api, '', *Presenter]
Jeśli mamy tylko jedną regułę w konfiguracji, tę ogólną, możemy napisać krótko:
application:
mapping: App\UI\*\**Presenter