Vytváření odkazů URL
Tvořit odkazy v Nette je jednoduché, jako ukazovat prstem. Stačí jen namířit a framework už za vás všechnu práci udělá. Ukážeme si:
- jak vytvářet odkazy v šablonách i jinde
- jak odlišit odkaz na aktuální stránku
- co s neplatnými odkazy
Díky obousměrnému routování nebudete nikdy muset do šablon či kódu zapisovat navrdo URL adresy vaší aplikace, které se mohou později měnit, nebo je komplikovaně skládat. V odkazu stačí uvést presenter a akci, předat případné parametry a framework už URL vygeneruje sám. Vlastně je to velice podobné, jako když voláte funkci. To se vám bude líbit.
V šabloně presenteru
Nejčastěji vytváříme odkazy v šablonách a skvělým pomocníkem je atribut n:href
:
<a n:href="Product:show">detail</a>
Všimněte si, že místo HTML atributu href
jsme použili n:atribut n:href
. Jeho hodnotou pak není URL, jak by
tomu bylo v případě atributu href
, ale název presenteru a akce.
Kliknutí na odkaz je, zjednodušeně řečeno, něco jako zavolání metody ProductPresenter::renderShow()
.
A pokud má ve své signatuře parametry, můžeme ji volat s argumenty:
<a n:href="Product:show $product->id, $product->slug">detail produktu</a>
Je možné předávat i pojmenované parametry. Následující odkaz předává parametr lang
s hodnotou
cs
:
<a n:href="Product:show $product->id, lang: cs">detail produktu</a>
Pokud metoda ProductPresenter::renderShow()
nemá $lang
ve své signatuře, může si hodnotu
parametru zjistit pomocí $lang = $this->getParameter('lang')
nebo z property.
Pokud jsou parametry uložené v poli, lze je rozvinout operátorem ...
(v Latte 2.x operátorem
(expand)
):
{var $args = [$product->id, lang => cs]}
<a n:href="Product:show ...$args">detail produktu</a>
V odkazech se také automaticky předávají tzv. persistentní parametry.
Atribut n:href
je velmi šikovný pro HTML značky <a>
. Chceme-li odkaz vypsat jinde,
například v textu, použijeme {link}
:
Adresa je: {link Home:default}
V kódu
K vytvoření odkazu v presenteru slouží metoda link()
:
$url = $this->link('Product:show', $product->id);
Parametry lze předat také pomocí pole, kde lze uvést i pojmenované parametry:
$url = $this->link('Product:show', [$product->id, 'lang' => 'cs']);
Odkazy lze vytvářet i bez presenteru, od toho je tu LinkGenerator a jeho metoda
link()
.
Odkazy na presenter
Pokud je cílem odkazu presenter a akce, má tuto syntaxi:
[//] [[[[:]module:]presenter:]action | this] [#fragment]
Formát podporují všechny značky Latte a všechny metody presenteru, které s odkazy pracují, tedy n:href
,
{link}
, {plink}
, link()
, lazyLink()
, isLinkCurrent()
,
redirect()
, redirectPermanent()
, forward()
, canonicalize()
a také LinkGenerator. Takže i když je v příkladech použit n:href
, mohla by tam být
kterákoliv z funkcí.
Základním tvarem je tedy Presenter:action
:
<a n:href="Home:default">úvodní stránka</a>
Pokud odkazujeme na akci aktuálního presenteru, můžeme jeho název vynechat:
<a n:href="default">úvodní stránka</a>
Pokud je cílem akce default
, můžeme ji vynechat, ale dvojtečka musí zůstat:
<a n:href="Home:">úvodní stránka</a>
Odkazy mohou také směřovat do jiných modulů. Zde se odkazy
rozlišují na relativní do zanořeného submodulu, nebo absolutní. Princip je analogický k cestám na disku, jen místo
lomítek jsou dvojtečky. Předpokládejme, že aktuální presenter je součástí modulu Front
, potom
zapíšeme:
<a n:href="Shop:Product:show">odkaz na Front:Shop:Product:show</a>
<a n:href=":Admin:Product:show">odkaz na Admin:Product:show</a>
Speciálním případem je odkaz na sebe sama, kdy jako cíl uvedeme
this
.
<a n:href="this">refresh</a>
Odkazovat můžeme na určitou část stránky přes tzv. fragment za znakem mřížky #
:
<a n:href="Home:#main">odkaz na Home:default a fragment #main</a>
Absolutní cesty
Odkazy generované pomocí link()
nebo n:href
jsou vždy absolutní cesty (tj. začínají znakem
/
), ale nikoliv absolutní URL s protokolem a doménou jako https://domain
.
Pro vygenerování absolutní URL přidejte na začátek dvě lomítka (např. n:href="//Home:"
). Nebo lze
přepnout presenter, aby generoval jen absolutní odkazy nastavením $this->absoluteUrls = true
.
Odkaz na aktuální stránku
Cíl this
vytvoří odkaz na aktuální stránku:
<a n:href="this">refresh</a>
Zároveň se přenáší i všechny parametry uvedené v signatuře metody action<Action>()
nebo
render<View>()
, pokud není action<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:
<a n:href="this refresh: 1">refresh</a>
Funkce isLinkCurrent()
zjišťuje, zda je cíl odkazu shodný s aktuální stránkou. Toho lze využít
například v šabloně k odlišení odkazů apod.
Parametry jsou stejné jako u metody link()
, navíc je však možné místo konkrétní akce uvést zástupný
znak *
, který znamená jakoukoliv akci daného presenteru.
{if !isLinkCurrent('Admin:login')}
<a n:href="Admin:login">Přihlaste se</a>
{/if}
<li n:class="isLinkCurrent('Product:*') ? active">
<a n:href="Product:">...</a>
</li>
V kombinaci s n:href
v jednom elementu se dá použít zkrácená podoba:
<a n:class="isLinkCurrent() ? active" n:href="Home:">...</a>
Zástupný znak *
lze použít pouze místo akce, nikoliv presenteru.
Pro zjištění, zda jsme v určitém modulu nebo jeho submodulu, použijeme metodu
isModuleCurrent(moduleName)
.
<li n:class="isModuleCurrent('Forum:Users') ? active">
<a n:href="Product:">...</a>
</li>
Odkazy na signál
Cílem odkazu nemusí být jen presenter a akce, ale také signál (volají metodu
handle<Signal>()
). Pak je syntaxe následující:
[//] [sub-component:]signal! [#fragment]
Signál tedy odlišuje vykřičník:
<a n:href="click!">signal</a>
Lze vytvořit i odkaz na signál subkomponenty (nebo sub-subkomponenty):
<a n:href="componentName:click!">signal</a>
Odkazy v komponentě
Protože komponenty jsou samostatné znovupoužitelné celky,
které by neměly mít žádné vazby na okolní presentery, fungují tu odkazy trošku jinak. Atribut Latte n:href
a
značka {link}
i metody komponent jako je link()
a další považují cíl odkazu vždy za název
signálu. Proto není nutné ani uvádět vykřičník:
<a n:href="click">signál, nikoliv akce</a>
Pokud bychom chtěli v šabloně komponenty odkazovat na presentery, použijeme k tomu značku {plink}
:
<a href={plink Home:default}>úvod</a>
nebo v kódu
$this->getPresenter()->link('Home:default')
Aliasy
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 pod klíčem
application › aliases
:
application:
aliases:
home: Front:Home:default
admin: Admin:Dashboard:default
sign: Front:Sign:in
V odkazech se pak zapisují pomocí zavináče, například:
<a n:href="@admin">administrace</a>
Podporované jsou i ve všech metodách pracujících s odkazy, jako je redirect()
a podobně.
Neplatné odkazy
Může se stát, že vytvoříme neplatný odkaz – buď proto, že vede na neexistující presenter, nebo proto, že
předává víc parametrů, než které cílová metoda přijímá ve své signatuře, nebo když pro cílovou akci nelze
vygenerovat URL. Jak naložit s neplatnými odkazy určuje statická proměnná Presenter::$invalidLinkMode
. Ta
může nabývat kombinaci těchto hodnot (konstant):
Presenter::InvalidLinkSilent
– tichý režim, jako URL se vrátí znak #Presenter::InvalidLinkWarning
– vyhodí se varování E_USER_WARNING, které bude v produkčním režimu zalogováno, ale nezpůsobí přerušení běhu skriptuPresenter::InvalidLinkTextual
– vizuální varování, vypíše chybu přímo do odkazuPresenter::InvalidLinkException
– vyhodí se výjimka InvalidLinkException
Výchozí nastavení je InvalidLinkWarning
v produkčním režimu a
InvalidLinkWarning | InvalidLinkTextual
ve vývojovém. InvalidLinkWarning
v produkčním prostředí
nezpůsobí přerušení skriptu, ale varování bude zalogováno. Ve vývojovém prostředí ho zachytí Tracy a zobrazí bluescreen. InvalidLinkTextual
pracuje tak, že jako URL
vrátí chybovou zprávu, která začíná znaky #error:
. Aby takové odkazy byly na první pohled patrné, doplníme
si do CSS:
a[href^="#error:"] {
background: red;
color: white;
}
Pokud nechceme, aby se ve vývojovém prostředí produkovala varování, můžeme nastavit tichý režim přímo v konfiguraci.
application:
silentLinks: true
LinkGenerator
Jak vytvářet odkazy s podobným komfortem jako má metoda link()
, ale bez přítomnosti presenteru? Od toho je
tu Nette\Application\LinkGenerator.
LinkGenerátor je služba, kterou si můžete nechat předat přes konstruktor a poté vytvářet odkazy jeho metodou
link()
.
Oproti presenterům je tu rozdíl. LinkGenerator vytváří všechny odkazy rovnou jako absolutní URL. A dále neexistuje
žádný „aktuální presenter“, takže nelze jako cíl uvést jen název akce link('default')
nebo uvádět
relativní cesty k modulům.
Neplatné odkazy vždy vyhazují Nette\Application\UI\InvalidLinkException
.