Vytváření odkazů URL
Vytvoření odkazů patří mezi nejsilnější místa Nette Frameworku. Díky obousměrnému routování není potřeba do šablon či kódu natvrdo zapisovat URL nebo je komplikovaně skládat. Stačí se odkazovat na akce presenterů, předávat jim parametry a framework už URL vygeneruje sám. Vytvořit odkaz je pak stejně snadné, jako zavolat funkci. To se vám bude tuze líbit!
Během programování a vytváření šablon nás nemusí zajímat tvar URL adres, budeme se totiž odkazovat přímo na akci
presenteru, tj. například na již zmíněnou Product:show
.
Odkazy v šablonách
Nejčastěji vytváříme odkazy v šablonách. Aby to bylo co nejjednodušší, nabízí nám framework hned tři makra.
Nejšikovnější z nich je makro n:href
<a n:href="Product:show $productId">detail produktu</a>
Všimněte si, že místo HTML atributu href
jsme použili n:makro n:href
. Jeho hodnotou pak není URL, jak by tomu
bylo v případě atributu href
, ale rovnou akce presenteru. Tam má tvar
[Presenter:]action [,] [arg1] [, arg2] [, ...]
Po kliknutí na odkaz se dostane ke slovu metoda ProductPresenter::renderShow()
a jako parametr $id
ji bude předána hodnota proměnné $productId
. Parametrů bychom mohli předat i víc, stejně jako když voláme
metodu. Mohlo by to být snad jednodušší?
Doporučuje se dodržovat konvenci velkého prvního písmenka pro název presenteru a malého pro akci. Jako oddělovač slouží právě jedna dvojtečka.
Kromě toho 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 $productId, lang => cs">detail produktu</a>
Ačkoliv metoda renderShow
nemá $lang
ve své hlavičce, může hodnotu parametru zjistit voláním
$lang = $this->getParameter('lang')
.
Máme-li všechny parametry v poli, můžeme jej rozvinout operátorem (expand)
:
{var $args = [$productId, lang => cs]}
<a n:href="Product:show (expand) $args">detail produktu</a>
Pokud je šablona, ve které vytváříme odkaz, také součástí Product
presenteru, můžeme název presenteru
vynechat a psát přímo n:href="show $productId"
. Nebo obráceně, vede-li odkaz na akci nazvanou
default
, lze tuto vynechat a napsat n:href="Product: $id"
(nezapomeňte na dvojtečku).
Odkazy mohou také směřovat do jiných modulů. Zde se rozlišuje, zda se odkazujeme
„relativně“ do zanořeného submodulu, nebo „absolutně“ do jiného modulu – pak cesta začne dvojtečkou. Pro ukázku
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
.
Vygenerovaný odkaz má podobu relativní cesty. Pokud potřebujeme absolutní odkaz včetně domény, přidáme na
začátek dvě lomítka (např. n:href="//show $productId"
). Pokud nastavíme v presenteru proměnnou $absoluteUrls na TRUE
, budou
všechny od té chvíle generované odkazy absolutní.
Odkazovat můžeme na určitou část na stránce přes tzv. fragment za znakem křížky #
:
<a n:href="show#comments">odkaz na Product:show a fragment #comments</a>
Atribut n:href
je velmi šikovný, pokud vytváříme HTML značku <a>
. Chceme-li odkaz vypsat
jinde, například v textu šablony, použijeme {link}
se stejnou vnitřní syntaxí:
Adresa je: {link Product:show $productId}
Blok uvnitř {ifCurrent $link}...{/ifCurrent}
se vykoná, pokud je cíl odkazu shodný s aktuální stránkou.
Makro je vhodné použít například pokud chceme aktivnímu odkazu přidat CSS třídu.
<!-- příklady použití -->
<a href="{link edit, 10}">edituj</a>
<ul class="menu">
<li><a href="{link Default:default}">...</a></li>
<li><a href="{link}">...</a></li>
...
<li {ifCurrent Default:default}class="active"{/ifCurrent}><a href="{link Default:default}">...</a></li>
<!-- rozšíření scope -->
<li {ifCurrent Default:*}class="active"{/ifCurrent}><a href="{link Default:default}">...</a></li>
</ul>
<!-- znegování -->
{ifCurrent Admin:login}{else}<a href="{link Admin:login}">Přihlašte se!</a>{/ifCurrent}
Ternární operátor ?: vypíše první hodnotu, pokud je podmínka splněna. V opačném případě vypíše hodnotu druhou. Lze použít i ve zkrácené podobě, kdy se za chybějící hodnotu doplní NULL – tj. nevypíše se nic.
Přečtěte si další podrobnosti o syntaxi Latte šablon.
Odkazování v presenteru
Presenter a komponenta disponují metodou
link()
, pomocí které lze vytvářet odkazy podobně jako v šabloně. Prvním parametrem je cílová akce
presenteru, následují předávané argumenty:
$url = $this->link(destination [,arg [,arg ...]]);
Ty lze předat také pomocí pole. Příklady:
$url = $this->link('Product:show', $productId);
$url = $this->link('Product:show', array($productId, 'lang' => 'cs'));
Pokud při generování odkazu předáte parametru metody hodnotu FALSE
, do odkazu se vůbec
nepřidá. Řešením je definovat pro parametr výchozí hodnotu TRUE
nebo FALSE
. Nette pak pochopí,
že je typu boolean, a předávanou hodnotu změní na 1 nebo 0 a následně při zpracování requestu je presenter převede
zpět na boolean.
Neplatné odkazy
Může se stát, že vytvoříme neplatný odkaz – buď proto, že vede na neexistující presenter, proto, že předává
víc parametrů, než které cílová metoda přijímá ve své definici, 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::INVALID_LINK_SILENT
– tichý režim, jako URL se vrátí znak #Presenter::INVALID_LINK_WARNING
– 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::INVALID_LINK_TEXTUAL
– vizuální varování, vypíše chybu přímo do odkazuPresenter::INVALID_LINK_EXCEPTION
– vyhodí se výjimka InvalidLinkException
Výchozí nastavení je INVALID_LINK_WARNING
v produkčním režimu a
INVALID_LINK_WARNING | INVALID_LINK_TEXTUAL
ve vývojovém. INVALID_LINK_WARNING
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. INVALID_LINK_TEXTUAL
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: yes