Nette Documentation Preview

syntax
Vytváření odkazů URL
********************

<div class=perex>

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

</div>


Díky [obousměrnému routování |routing] 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`:

```latte
<a n:href="Product:show">detail</a>
```

Všimněte si, že místo HTML atributu `href` jsme použili [n:atribut |latte:syntax#n-atributy] `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:

```latte
<a n:href="Product:show $product->id, $product->slug">detail produktu</a>
```

Na rozdíl od PHP je možné předávat i pojmenované parametry. Následující odkaz předává parametr `lang` s hodnotou `cs`:

```latte
<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')`.

Pokud jsou parametry uložené v poli, lze je rozvinout operátorem `(expand)` (něco jako `...` operátor v PHP, ale funguje s asociativními poli):

```latte
{var $args = [$product->id, lang => cs]}
<a n:href="Product:show (expand) $args">detail produktu</a>
```

V odkazech se také automaticky předávají tzv. [persistentní parametry|presenters#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}`:

```latte
Adresa je: {link Homepage:default}
```


V kódu
======

K vytvoření odkazu v presenteru slouží metoda `link()`:

```php
$url = $this->link('Product:show', $product->id);
```

Parametry lze předat také pomocí pole, kde lze uvést i pojmenované parametry:

```php
$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`:

```latte
<a n:href="Homepage:default">úvodní stránka</a>
```

Pokud odkazujeme na akci aktuálního presenteru, můžeme jeho název vynechat:

```latte
<a n:href="default">úvodní stránka</a>
```

Pokud je cílem akce `default`, můžeme ji vynechat, ale dvojtečka musí zůstat:

```latte
<a n:href="Homepage:">úvodní stránka</a>
```

Odkazy mohou také směřovat do jiných [modulů |modules]. 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:

```latte
<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|#Odkaz na aktuální stránku], kdy jako cíl uvedeme `this`.

```latte
<a n:href="this">refresh</a>
```

Odkazovat můžeme na určitou část stránky přes tzv. fragment za znakem mřížky `#`:

```latte
<a n:href="Homepage:#main">odkaz na Homepage: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="//Homepage:"`). 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:

```latte
<a n:href="this">refresh</a>
```

Zároveň se přenáší i všechny parametry uvedené v signatuře `render<View>()` nebo `action<Action>()` metody. 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:

```latte
<a n:href="this refresh: 1">refresh</a>
```

Metoda presenteru `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.

```latte
{if !$presenter->isLinkCurrent('Admin:login')}
	<a n:href="Admin:login">Přihlaste se</a>
{/if}

<li n:class="$presenter->isLinkCurrent('Product:*') ? active">
	<a n:href="Product:">...</a>
</li>
```

V kombinaci s `n:href` v jednom elementu se dá použít zkrácená podoba:

```latte
<a n:class="$presenter->isLinkCurrent() ? active" n:href="Homepage:">...</a>
```


Odkazy na signál
================

Cílem odkazu nemusí být jen presenter a akce, ale také [signál|components#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:

```latte
<a n:href="click!">signal</a>
```

Lze vytvořit i odkaz na signál subkomponenty (nebo sub-subkomponenty):

```latte
<a n:href="componentName:click!">signal</a>
```


Odkazy v komponentě
===================

Protože [komponenty|components] 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:

```latte
<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}`:

```latte
<a href="{plink Homepage:default}">úvod</a>
```

nebo v kódu

```php
$this->getPresenter()->link('Homepage:default')
```


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::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 skriptu
- `Presenter::INVALID_LINK_TEXTUAL` - vizuální varování, vypíše chybu přímo do odkazu
- `Presenter::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 |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:

```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|configuration].

```neon
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 [api: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 |modules].

Neplatné odkazy vždy vyhazují `Nette\Application\UI\InvalidLinkException`.

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>

Na rozdíl od PHP 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').

Pokud jsou parametry uložené v poli, lze je rozvinout operátorem (expand) (něco jako ... operátor v PHP, ale funguje s asociativními poli):

{var $args = [$product->id, lang => cs]}
<a n:href="Product:show (expand) $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 Homepage: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="Homepage: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="Homepage:">ú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="Homepage:#main">odkaz na Homepage: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="//Homepage:"). 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 render<View>() nebo action<Action>() metody. 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>

Metoda presenteru 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 !$presenter->isLinkCurrent('Admin:login')}
	<a n:href="Admin:login">Přihlaste se</a>
{/if}

<li n:class="$presenter->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="$presenter->isLinkCurrent() ? active" n:href="Homepage:">...</a>

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 Homepage:default}">úvod</a>

nebo v kódu

$this->getPresenter()->link('Homepage:default')

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::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 skriptu
  • Presenter::INVALID_LINK_TEXTUAL – vizuální varování, vypíše chybu přímo do odkazu
  • Presenter::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: 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.