Moduły
W Nette moduły reprezentują logiczne jednostki, które tworzą aplikację. Należą do nich prezentery, szablony, ewentualnie komponenty i klasy modeli.
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
.
app/ ├──Presenters/├── Modules/ ← adresář s moduly │ ├── Admin/ ← modul Admin │ │ ├── Presenters/ ← jeho presentery │ │ │ ├── DashboardPresenter.php │ │ │ └── templates/ │ └── Front/ ← modul Front │ └── Presenters/ ← jeho presentery │ └── ...
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
:
namespace App\Modules\Admin\Presenters;
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 w
konfiguracji. Tak więc podana struktura nie jest stała i można ją modyfikować według potrzeb.
Moduły mogą oczywiście zawierać wszystkie inne części oprócz prezenterów i szablonów, jak komponenty, klasy modeli itp.
Moduły zagnieżdżone
Moduły nie muszą tworzyć tylko płaskiej struktury, można też tworzyć np. submoduły:
app/ ├── Modules/ ← adresář s moduly │ ├── Blog/ ← modul Blog │ │ ├── Admin/ ← submodul Admin │ │ │ ├── Presenters/ │ │ │ └── ... │ │ └── Front/ ← submodul Front │ │ ├── Presenters/ │ │ └── ... │ ├── Forum/ ← modul Forum │ │ └── ...
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
.
Rozgałęzienie może iść tak głęboko, jak chcesz, więc możesz tworzyć podmoduły.
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
Określa zasady, według których nazwa klasy jest wyprowadzana z nazwy prezentera. Zapisujemy je w konfiguracji pod kluczem application › mapping
.
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:
application:
mapping:
*: App\Presenters\*Presenter
Zastąp nazwę prezentera gwiazdką w masce klasy, a wynikiem będzie nazwa klasy. Spokojnie!
Jeśli złamiemy prezenterów na moduły, możemy mieć niestandardowe mapowanie dla każdego modułu:
application:
mapping:
Front: App\Modules\Front\Presenters\*Presenter
Admin: App\Modules\Admin\Presenters\*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
.
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:
application:
mapping:
*: App\Modules\*\Presenters\*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
.
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ą:
application:
mapping:
*: [App\Modules, *, Presenters\*Presenter]
Wartość domyślna to *: *Module\*Presenter
.