Tworzenie linków URL
Tworzenie linków w Nette jest proste jak wskazywanie palcem. Wystarczy tylko wycelować, a framework już za Ciebie wykona całą pracę. Pokażemy:
- jak tworzyć linki w szablonach i gdzie indziej
- jak odróżnić link do aktualnej strony
- co z nieprawidłowymi linkami
Dzięki dwukierunkowemu routingowi nigdy nie będziesz musiał w szablonach czy kodzie zapisywać na sztywno adresów URL Twojej aplikacji, które mogą się później zmienić, lub skomplikowanie je składać. W linku wystarczy podać presenter i akcję, przekazać ewentualne parametry, a framework już sam wygeneruje URL. Właściwie jest to bardzo podobne do wywoływania funkcji. Spodoba Ci się to.
W szablonie presentera
Najczęściej tworzymy linki w szablonach, a świetnym pomocnikiem jest atrybut n:href
:
<a n:href="Product:show">szczegóły</a>
Zauważ, że zamiast atrybutu HTML href
użyliśmy n:atrybutu n:href
. Jego wartością nie jest URL, jak by
to było w przypadku atrybutu href
, ale nazwa presentera i akcji.
Kliknięcie na link jest, upraszczając, czymś w rodzaju wywołania metody ProductPresenter::renderShow()
.
A jeśli ma w swojej sygnaturze parametry, możemy ją wywołać z argumentami:
<a n:href="Product:show $product->id, $product->slug">szczegóły produktu</a>
Możliwe jest również przekazywanie parametrów nazwanych. Poniższy link przekazuje parametr lang
o wartości
cs
:
<a n:href="Product:show $product->id, lang: cs">szczegóły produktu</a>
Jeśli metoda ProductPresenter::renderShow()
nie ma $lang
w swojej sygnaturze, może uzyskać
wartość parametru za pomocą $lang = $this->getParameter('lang')
lub z właściwości.
Jeśli parametry są przechowywane w tablicy, można je rozwinąć operatorem ...
(w Latte 2.x operatorem
(expand)
):
{var $args = [$product->id, lang => cs]}
<a n:href="Product:show ...$args">szczegóły produktu</a>
W linkach automatycznie przekazywane są również tzw. parametry persistentne.
Atrybut n:href
jest bardzo przydatny dla znaczników HTML <a>
. Jeśli chcemy wypisać link
gdzie indziej, na przykład w tekście, użyjemy {link}
:
Adres to: {link Home:default}
W kodzie
Do tworzenia linku w presenterze służy metoda link()
:
$url = $this->link('Product:show', $product->id);
Parametry można przekazać również za pomocą tablicy, gdzie można podać również parametry nazwane:
$url = $this->link('Product:show', [$product->id, 'lang' => 'cs']);
Linki można tworzyć również bez presentera, do tego służy LinkGenerator i jego metoda
link()
.
Linki do presentera
Jeśli celem linku jest presenter i akcja, ma on następującą składnię:
[//] [[[[:]module:]presenter:]action | this] [#fragment]
Format ten obsługują wszystkie znaczniki Latte i wszystkie metody presentera, które pracują z linkami, czyli
n:href
, {link}
, {plink}
, link()
, lazyLink()
,
isLinkCurrent()
, redirect()
, redirectPermanent()
, forward()
,
canonicalize()
oraz LinkGenerator. Więc nawet jeśli w przykładach użyto
n:href
, mogłaby tam być dowolna z tych funkcji.
Podstawową formą jest więc Presenter:action
:
<a n:href="Home:default">strona główna</a>
Jeśli linkujemy do akcji aktualnego presentera, możemy pominąć jego nazwę:
<a n:href="default">strona główna</a>
Jeśli celem jest akcja default
, możemy ją pominąć, ale dwukropek musi pozostać:
<a n:href="Home:">strona główna</a>
Linki mogą również prowadzić do innych modułów. Tutaj linki dzielą się
na względne do zagnieżdżonego podmodułu lub absolutne. Zasada jest analogiczna do ścieżek na dysku, tylko zamiast
ukośników są dwukropki. Załóżmy, że aktualny presenter jest częścią modułu Front
, wtedy zapiszemy:
<a n:href="Shop:Product:show">link do Front:Shop:Product:show</a>
<a n:href=":Admin:Product:show">link do Admin:Product:show</a>
Specjalnym przypadkiem jest link do siebie samego, gdy jako cel podamy
this
.
<a n:href="this">odśwież</a>
Możemy linkować do określonej części strony za pomocą tzw. fragmentu za znakiem kratki #
:
<a n:href="Home:#main">link do Home:default i fragmentu #main</a>
Ścieżki absolutne
Linki generowane za pomocą link()
lub n:href
są zawsze ścieżkami absolutnymi (tj. zaczynają się
znakiem /
), ale nie są absolutnymi URL z protokołem i domeną, jak https://domain
.
Aby wygenerować absolutny URL, dodaj na początku dwie ukośniki (np. n:href="//Home:"
). Lub można przełączyć
presenter, aby generował tylko linki absolutne, ustawiając $this->absoluteUrls = true
.
Link do aktualnej strony
Cel this
tworzy link do aktualnej strony:
<a n:href="this">odśwież</a>
Jednocześnie przekazywane są wszystkie parametry podane w sygnaturze metody action<Action>()
lub
render<View>()
, jeśli action<Action>()
nie jest zdefiniowana. Więc jeśli jesteśmy na
stronie Product:show
i id: 123
, link do this
przekaże również ten parametr.
Oczywiście można parametry specyfikować bezpośrednio:
<a n:href="this refresh: 1">odśwież</a>
Funkcja isLinkCurrent()
sprawdza, czy cel linku jest zgodny z aktualną stroną. Można tego użyć na przykład
w szablonie do odróżnienia linków itp.
Parametry są takie same jak w metodzie link()
, dodatkowo jednak można zamiast konkretnej akcji podać symbol
wieloznaczny *
, który oznacza dowolną akcję danego presentera.
{if !isLinkCurrent('Admin:login')}
<a n:href="Admin:login">Zaloguj się</a>
{/if}
<li n:class="isLinkCurrent('Product:*') ? active">
<a n:href="Product:">...</a>
</li>
W połączeniu z n:href
w jednym elemencie można użyć skróconej formy:
<a n:class="isLinkCurrent() ? active" n:href="Home:">...</a>
Symbol wieloznaczny *
można użyć tylko zamiast akcji, a nie presentera.
Aby sprawdzić, czy jesteśmy w określonym module lub jego podmodule, użyjemy metody
isModuleCurrent(moduleName)
.
<li n:class="isModuleCurrent('Forum:Users') ? active">
<a n:href="Product:">...</a>
</li>
Linki do sygnału
Celem linku nie musi być tylko presenter i akcja, ale także sygnał (wywołują metodę
handle<Signal>()
). Wtedy składnia jest następująca:
[//] [sub-component:]signal! [#fragment]
Sygnał odróżnia więc wykrzyknik:
<a n:href="click!">sygnał</a>
Można również utworzyć link do sygnału podkomponentu (lub pod-podkomponentu):
<a n:href="componentName:click!">sygnał</a>
Linki w komponencie
Ponieważ komponenty są samodzielnymi jednostkami wielokrotnego
użytku, które nie powinny mieć żadnych powiązań z otaczającymi presenterami, linki działają tu trochę inaczej. Atrybut
Latte n:href
i znacznik {link}
oraz metody komponentu takie jak link()
i inne uważają
cel linku zawsze za nazwę sygnału. Dlatego nie jest nawet konieczne podawanie wykrzyknika:
<a n:href="click">sygnał, a nie akcja</a>
Jeśli chcielibyśmy w szablonie komponentu linkować do presenterów, użyjemy do tego znacznika {plink}
:
<a href={plink Home:default}>główna</a>
lub w kodzie
$this->getPresenter()->link('Home:default')
Aliasy
Czasami może się przydać przypisanie parze Presenter:akcja łatwo zapamiętywalnego aliasu. Na przykład stronę główną
Front:Home:default
nazwać po prostu home
lub Admin:Dashboard:default
jako
admin
.
Aliasy definiuje się w konfiguracji pod kluczem
application › aliases
:
application:
aliases:
home: Front:Home:default
admin: Admin:Dashboard:default
sign: Front:Sign:in
W linkach zapisuje się je za pomocą znaku @, na przykład:
<a n:href="@admin">administracja</a>
Są one obsługiwane również we wszystkich metodach pracujących z linkami, takich jak redirect()
i podobnych.
Nieprawidłowe linki
Może się zdarzyć, że utworzymy nieprawidłowy link – albo dlatego, że prowadzi do nieistniejącego presentera, albo
dlatego, że przekazuje więcej parametrów, niż akceptuje metoda docelowa w swojej sygnaturze, albo gdy dla akcji docelowej nie
można wygenerować URL. Sposób postępowania z nieprawidłowymi linkami określa zmienna statyczna
Presenter::$invalidLinkMode
. Może ona przyjmować kombinację tych wartości (stałych):
Presenter::InvalidLinkSilent
– tryb cichy, jako URL zwracany jest znak #Presenter::InvalidLinkWarning
– zgłaszane jest ostrzeżenie E_USER_WARNING, które w trybie produkcyjnym zostanie zalogowane, ale nie spowoduje przerwania działania skryptuPresenter::InvalidLinkTextual
– ostrzeżenie wizualne, wypisuje błąd bezpośrednio w linkuPresenter::InvalidLinkException
– rzucany jest wyjątek InvalidLinkException
Domyślne ustawienie to InvalidLinkWarning
w trybie produkcyjnym i
InvalidLinkWarning | InvalidLinkTextual
w trybie deweloperskim. InvalidLinkWarning
w środowisku
produkcyjnym nie powoduje przerwania skryptu, ale ostrzeżenie zostanie zalogowane. W środowisku deweloperskim zostanie
przechwycone przez Tracy i wyświetli bluescreen. InvalidLinkTextual
działa tak, że jako URL zwraca komunikat błędu zaczynający się od znaków #error:
. Aby takie linki były od
razu widoczne, dodajmy do CSS:
a[href^="#error:"] {
background: red;
color: white;
}
Jeśli nie chcemy, aby w środowisku deweloperskim generowane były ostrzeżenia, możemy ustawić tryb cichy bezpośrednio w konfiguracji.
application:
silentLinks: true
LinkGenerator
Jak tworzyć linki z podobnym komfortem jak metoda link()
, ale bez obecności presentera? Do tego służy Nette\Application\LinkGenerator.
LinkGenerator to usługa, którą można sobie przekazać przez konstruktor, a następnie tworzyć linki za pomocą jej metody
link()
.
W porównaniu do presenterów jest tu różnica. LinkGenerator tworzy wszystkie linki od razu jako absolutne URL. Ponadto nie
istnieje żaden “aktualny presenter”, więc nie można jako celu podać tylko nazwy akcji link('default')
ani
podawać ścieżek względnych do modułów.
Nieprawidłowe linki zawsze rzucają Nette\Application\UI\InvalidLinkException
.