Nette Documentation Preview

syntax
Ustvarjanje URL povezav
***********************

<div class=perex>

Ustvarjanje povezav v Nette je preprosto, kot kazanje s prstom. Dovolj je le nameriti in ogrodje bo že samo opravilo vse delo. Pokazali si bomo:

- kako ustvarjati povezave v predlogah in drugje
- kako razlikovati povezavo na trenutno stran
- kaj storiti z neveljavnimi povezavami

</div>


Zahvaljujoč [dvosmernemu usmerjanju |routing] vam nikoli ne bo treba v predloge ali kodo trdo kodirati URL naslovov vaše aplikacije, ki se lahko kasneje spremenijo, ali jih zapleteno sestavljati. V povezavi je dovolj navesti presenter in akcijo, posredovati morebitne parametre in ogrodje bo že samo generiralo URL. Pravzaprav je to zelo podobno, kot ko kličete funkcijo. To vam bo všeč.


V predlogi presenterja
======================

Najpogosteje ustvarjamo povezave v predlogah in odličen pomočnik je atribut `n:href`:

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

Opazite, da smo namesto HTML atributa `href` uporabili [n:atribut |latte:syntax#n:atributi] `n:href`. Njegova vrednost potem ni URL, kot bi bilo v primeru atributa `href`, ampak ime presenterja in akcije.

Klik na povezavo je, poenostavljeno rečeno, nekaj takega kot klicanje metode `ProductPresenter::renderShow()`. In če ima v svoji signaturi parametre, jo lahko kličemo z argumenti:

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

Možno je posredovati tudi imenovane parametre. Naslednja povezava posreduje parameter `lang` z vrednostjo `cs`:

```latte
<a n:href="Product:show $product->id, lang: cs">podrobnosti izdelka</a>
```

Če metoda `ProductPresenter::renderShow()` nima `$lang` v svoji signaturi, lahko vrednost parametra ugotovi s pomočjo `$lang = $this->getParameter('lang')` ali iz [lastnosti |presenters#Parametri zahtevka].

Če so parametri shranjeni v polju, jih lahko razvijemo z operatorjem `...` (v Latte 2.x z operatorjem `(expand)`):

```latte
{var $args = [$product->id, lang => cs]}
<a n:href="Product:show ...$args">podrobnosti izdelka</a>
```

V povezavah se samodejno prenašajo tudi t.i. [persistentni parametri |presenters#Persistentni parametri].

Atribut `n:href` je zelo priročen za HTML značke `<a>`. Če želimo povezavo izpisati drugje, na primer v besedilu, uporabimo `{link}`:

```latte
Naslov je: {link Home:default}
```


V kodi
======

Za ustvarjanje povezave v presenterju služi metoda `link()`:

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

Parametre lahko posredujemo tudi s pomočjo polja, kjer lahko navedemo tudi imenovane parametre:

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

Povezave lahko ustvarjamo tudi brez presenterja, za to je tu [##LinkGenerator] in njegova metoda `link()`.


Povezave na presenter
=====================

Če je cilj povezave presenter in akcija, ima to sintakso:

```
[//] [[[[:]module:]presenter:]action | this] [#fragment]
```

Format podpirajo vse značke Latte in vse metode presenterja, ki delajo s povezavami, torej `n:href`, `{link}`, `{plink}`, `link()`, `lazyLink()`, `isLinkCurrent()`, `redirect()`, `redirectPermanent()`, `forward()`, `canonicalize()` in tudi [##LinkGenerator]. Torej, čeprav je v primerih uporabljen `n:href`, bi lahko bila tam katerakoli od funkcij.

Osnovna oblika je torej `Presenter:action`:

```latte
<a n:href="Home:default">domača stran</a>
```

Če povezujemo na akcijo trenutnega presenterja, lahko njegovo ime izpustimo:

```latte
<a n:href="default">domača stran</a>
```

Če je cilj akcija `default`, jo lahko izpustimo, vendar dvopičje mora ostati:

```latte
<a n:href="Home:">domača stran</a>
```

Povezave lahko vodijo tudi v druge [module |directory-structure#Presenterji in predloge]. Tukaj se povezave razlikujejo na relativne v ugnezden podmodul ali absolutne. Princip je analogen potem na disku, le da so namesto poševnic dvopičja. Predpostavimo, da je trenutni presenter del modula `Front`, potem zapišemo:

```latte
<a n:href="Shop:Product:show">povezava na Front:Shop:Product:show</a>
<a n:href=":Admin:Product:show">povezava na Admin:Product:show</a>
```

Poseben primer je povezava [nase |#Povezava na trenutno stran], ko kot cilj navedemo `this`.

```latte
<a n:href="this">osveži</a>
```

Povezovati lahko na določen del strani prek t.i. fragmenta za znakom lojtre `#`:

```latte
<a n:href="Home:#main">povezava na Home:default in fragment #main</a>
```


Absolutne poti
==============

Povezave, generirane s pomočjo `link()` ali `n:href`, so vedno absolutne poti (tj. začnejo se z znakom `/`), vendar ne absolutni URL-ji s protokolom in domeno kot `https://domain`.

Za generiranje absolutnega URL-ja dodajte na začetek dve poševnici (npr. `n:href="//Home:"`). Ali pa lahko preklopite presenter, da generira samo absolutne povezave z nastavitvijo `$this->absoluteUrls = true`.


Povezava na trenutno stran
==========================

Cilj `this` ustvari povezavo na trenutno stran:

```latte
<a n:href="this">osveži</a>
```

Hkrati se prenašajo tudi vsi parametri, navedeni v signaturi metode `action<Action>()` ali `render<View>()`, če `action<Action>()` ni definirana. Torej, če smo na strani `Product:show` in `id: 123`, povezava na `this` prenese tudi ta parameter.

Seveda je mogoče parametre specificirati neposredno:

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

Funkcija `isLinkCurrent()` ugotavlja, ali je cilj povezave enak trenutni strani. To lahko uporabimo na primer v predlogi za razlikovanje povezav ipd.

Parametri so enaki kot pri metodi `link()`, poleg tega pa je mogoče namesto konkretne akcije navesti nadomestni znak `*`, ki pomeni katerokoli akcijo danega presenterja.

```latte
{if !isLinkCurrent('Admin:login')}
	<a n:href="Admin:login">Prijavite se</a>
{/if}

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

V kombinaciji z `n:href` v enem elementu se da uporabiti skrajšana oblika:

```latte
<a n:class="isLinkCurrent() ? active" n:href="Home:">...</a>
```

Nadomestni znak `*` lahko uporabimo samo namesto akcije, ne pa presenterja.

Za ugotavljanje, ali smo v določenem modulu ali njegovem podmodulu, uporabimo metodo `isModuleCurrent(moduleName)`.

```latte
<li n:class="isModuleCurrent('Forum:Users') ? active">
	<a n:href="Product:">...</a>
</li>
```


Povezave na signal
==================

Cilj povezave ni nujno samo presenter in akcija, ampak tudi [signal |components#Signal] (kličejo metodo `handle<Signal>()`). Potem je sintaksa naslednja:

```
[//] [sub-component:]signal! [#fragment]
```

Signal torej loči klicaj:

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

Lahko ustvarimo tudi povezavo na signal podkomponente (ali pod-podkomponente):

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


Povezave v komponenti
=====================

Ker so [komponente|components] samostojne ponovno uporabne enote, ki ne bi smele imeti nobenih povezav z okoliškimi presenterji, tukaj povezave delujejo nekoliko drugače. Atribut Latte `n:href` in značka `{link}` ter metode komponent, kot je `link()` in druge, obravnavajo cilj povezave **vedno kot ime signala**. Zato ni treba niti navajati klicaja:

```latte
<a n:href="click">signal, ne akcija</a>
```

Če bi želeli v predlogi komponente povezovati na presenterje, uporabimo za to značko `{plink}`:

```latte
<a href={plink Home:default}>domov</a>
```

ali v kodi

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


Aliasi .{data-version:v3.2.2}
=============================

Včasih se lahko zgodi, da je koristno paru Presenter:akcija dodeliti lahko zapomnljiv alias. Na primer, domačo stran `Front:Home:default` poimenovati preprosto kot `home` ali `Admin:Dashboard:default` kot `admin`.

Aliasi se definirajo v [konfiguraciji|configuration] pod ključem `application › aliases`:

```neon
application:
    aliases:
        home: Front:Home:default
        admin: Admin:Dashboard:default
        sign: Front:Sign:in
```

V povezavah se nato zapisujejo s pomočjo afne, na primer:

```latte
<a n:href="@admin">administracija</a>
```

Podprti so tudi v vseh metodah, ki delajo s povezavami, kot je `redirect()` in podobno.


Neveljavne povezave
===================

Lahko se zgodi, da ustvarimo neveljavno povezavo - bodisi zato, ker vodi na neobstoječ presenter, ali zato, ker posreduje več parametrov, kot jih ciljna metoda sprejema v svoji signaturi, ali ko za ciljno akcijo ni mogoče generirati URL-ja. Kako ravnati z neveljavnimi povezavami, določa statična spremenljivka `Presenter::$invalidLinkMode`. Ta lahko prevzame kombinacijo teh vrednosti (konstant):

- `Presenter::InvalidLinkSilent` - tihi način, kot URL se vrne znak #
- `Presenter::InvalidLinkWarning` - sproži se opozorilo E_USER_WARNING, ki bo v produkcijskem načinu zabeleženo, vendar ne bo povzročilo prekinitve izvajanja skripta
- `Presenter::InvalidLinkTextual` - vizualno opozorilo, napako izpiše neposredno v povezavo
- `Presenter::InvalidLinkException` - sproži se izjema InvalidLinkException

Privzeta nastavitev je `InvalidLinkWarning` v produkcijskem načinu in `InvalidLinkWarning | InvalidLinkTextual` v razvojnem. `InvalidLinkWarning` v produkcijskem okolju ne povzroči prekinitve skripta, vendar bo opozorilo zabeleženo. V razvojnem okolju ga ujame [Tracy |tracy:] in prikaže bluescreen. `InvalidLinkTextual` deluje tako, da kot URL vrne sporočilo o napaki, ki se začne z znaki `#error:`. Da bi bile takšne povezave na prvi pogled očitne, si dodamo v CSS:

```css
a[href^="#error:"] {
	background: red;
	color: white;
}
```

Če ne želimo, da se v razvojnem okolju producirajo opozorila, lahko nastavimo tihi način neposredno v [konfiguraciji|configuration].

```neon
application:
	silentLinks: true
```


LinkGenerator
=============

Kako ustvarjati povezave s podobnim udobjem kot ima metoda `link()`, vendar brez prisotnosti presenterja? Za to je tu [api:Nette\Application\LinkGenerator].

LinkGenerator je storitev, ki si jo lahko pustite posredovati prek konstruktorja in nato ustvarjate povezave z njegovo metodo `link()`.

V primerjavi s presenterji je tu razlika. LinkGenerator ustvarja vse povezave takoj kot absolutne URL-je. In nadalje ne obstaja noben "trenutni presenter", zato ni mogoče kot cilj navesti samo ime akcije `link('default')` ali navajati relativne poti do modulov.

Neveljavne povezave vedno sprožijo `Nette\Application\UI\InvalidLinkException`.

Ustvarjanje URL povezav

Ustvarjanje povezav v Nette je preprosto, kot kazanje s prstom. Dovolj je le nameriti in ogrodje bo že samo opravilo vse delo. Pokazali si bomo:

  • kako ustvarjati povezave v predlogah in drugje
  • kako razlikovati povezavo na trenutno stran
  • kaj storiti z neveljavnimi povezavami

Zahvaljujoč dvosmernemu usmerjanju vam nikoli ne bo treba v predloge ali kodo trdo kodirati URL naslovov vaše aplikacije, ki se lahko kasneje spremenijo, ali jih zapleteno sestavljati. V povezavi je dovolj navesti presenter in akcijo, posredovati morebitne parametre in ogrodje bo že samo generiralo URL. Pravzaprav je to zelo podobno, kot ko kličete funkcijo. To vam bo všeč.

V predlogi presenterja

Najpogosteje ustvarjamo povezave v predlogah in odličen pomočnik je atribut n:href:

<a n:href="Product:show">podrobnosti</a>

Opazite, da smo namesto HTML atributa href uporabili n:atribut n:href. Njegova vrednost potem ni URL, kot bi bilo v primeru atributa href, ampak ime presenterja in akcije.

Klik na povezavo je, poenostavljeno rečeno, nekaj takega kot klicanje metode ProductPresenter::renderShow(). In če ima v svoji signaturi parametre, jo lahko kličemo z argumenti:

<a n:href="Product:show $product->id, $product->slug">podrobnosti izdelka</a>

Možno je posredovati tudi imenovane parametre. Naslednja povezava posreduje parameter lang z vrednostjo cs:

<a n:href="Product:show $product->id, lang: cs">podrobnosti izdelka</a>

Če metoda ProductPresenter::renderShow() nima $lang v svoji signaturi, lahko vrednost parametra ugotovi s pomočjo $lang = $this->getParameter('lang') ali iz lastnosti.

Če so parametri shranjeni v polju, jih lahko razvijemo z operatorjem ... (v Latte 2.x z operatorjem (expand)):

{var $args = [$product->id, lang => cs]}
<a n:href="Product:show ...$args">podrobnosti izdelka</a>

V povezavah se samodejno prenašajo tudi t.i. persistentni parametri.

Atribut n:href je zelo priročen za HTML značke <a>. Če želimo povezavo izpisati drugje, na primer v besedilu, uporabimo {link}:

Naslov je: {link Home:default}

V kodi

Za ustvarjanje povezave v presenterju služi metoda link():

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

Parametre lahko posredujemo tudi s pomočjo polja, kjer lahko navedemo tudi imenovane parametre:

$url = $this->link('Product:show', [$product->id, 'lang' => 'cs']);

Povezave lahko ustvarjamo tudi brez presenterja, za to je tu LinkGenerator in njegova metoda link().

Povezave na presenter

Če je cilj povezave presenter in akcija, ima to sintakso:

[//] [[[[:]module:]presenter:]action | this] [#fragment]

Format podpirajo vse značke Latte in vse metode presenterja, ki delajo s povezavami, torej n:href, {link}, {plink}, link(), lazyLink(), isLinkCurrent(), redirect(), redirectPermanent(), forward(), canonicalize() in tudi LinkGenerator. Torej, čeprav je v primerih uporabljen n:href, bi lahko bila tam katerakoli od funkcij.

Osnovna oblika je torej Presenter:action:

<a n:href="Home:default">domača stran</a>

Če povezujemo na akcijo trenutnega presenterja, lahko njegovo ime izpustimo:

<a n:href="default">domača stran</a>

Če je cilj akcija default, jo lahko izpustimo, vendar dvopičje mora ostati:

<a n:href="Home:">domača stran</a>

Povezave lahko vodijo tudi v druge module. Tukaj se povezave razlikujejo na relativne v ugnezden podmodul ali absolutne. Princip je analogen potem na disku, le da so namesto poševnic dvopičja. Predpostavimo, da je trenutni presenter del modula Front, potem zapišemo:

<a n:href="Shop:Product:show">povezava na Front:Shop:Product:show</a>
<a n:href=":Admin:Product:show">povezava na Admin:Product:show</a>

Poseben primer je povezava nase, ko kot cilj navedemo this.

<a n:href="this">osveži</a>

Povezovati lahko na določen del strani prek t.i. fragmenta za znakom lojtre #:

<a n:href="Home:#main">povezava na Home:default in fragment #main</a>

Absolutne poti

Povezave, generirane s pomočjo link() ali n:href, so vedno absolutne poti (tj. začnejo se z znakom /), vendar ne absolutni URL-ji s protokolom in domeno kot https://domain.

Za generiranje absolutnega URL-ja dodajte na začetek dve poševnici (npr. n:href="//Home:"). Ali pa lahko preklopite presenter, da generira samo absolutne povezave z nastavitvijo $this->absoluteUrls = true.

Povezava na trenutno stran

Cilj this ustvari povezavo na trenutno stran:

<a n:href="this">osveži</a>

Hkrati se prenašajo tudi vsi parametri, navedeni v signaturi metode action<Action>() ali render<View>(), če action<Action>() ni definirana. Torej, če smo na strani Product:show in id: 123, povezava na this prenese tudi ta parameter.

Seveda je mogoče parametre specificirati neposredno:

<a n:href="this refresh: 1">osveži</a>

Funkcija isLinkCurrent() ugotavlja, ali je cilj povezave enak trenutni strani. To lahko uporabimo na primer v predlogi za razlikovanje povezav ipd.

Parametri so enaki kot pri metodi link(), poleg tega pa je mogoče namesto konkretne akcije navesti nadomestni znak *, ki pomeni katerokoli akcijo danega presenterja.

{if !isLinkCurrent('Admin:login')}
	<a n:href="Admin:login">Prijavite se</a>
{/if}

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

V kombinaciji z n:href v enem elementu se da uporabiti skrajšana oblika:

<a n:class="isLinkCurrent() ? active" n:href="Home:">...</a>

Nadomestni znak * lahko uporabimo samo namesto akcije, ne pa presenterja.

Za ugotavljanje, ali smo v določenem modulu ali njegovem podmodulu, uporabimo metodo isModuleCurrent(moduleName).

<li n:class="isModuleCurrent('Forum:Users') ? active">
	<a n:href="Product:">...</a>
</li>

Povezave na signal

Cilj povezave ni nujno samo presenter in akcija, ampak tudi signal (kličejo metodo handle<Signal>()). Potem je sintaksa naslednja:

[//] [sub-component:]signal! [#fragment]

Signal torej loči klicaj:

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

Lahko ustvarimo tudi povezavo na signal podkomponente (ali pod-podkomponente):

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

Povezave v komponenti

Ker so komponente samostojne ponovno uporabne enote, ki ne bi smele imeti nobenih povezav z okoliškimi presenterji, tukaj povezave delujejo nekoliko drugače. Atribut Latte n:href in značka {link} ter metode komponent, kot je link() in druge, obravnavajo cilj povezave vedno kot ime signala. Zato ni treba niti navajati klicaja:

<a n:href="click">signal, ne akcija</a>

Če bi želeli v predlogi komponente povezovati na presenterje, uporabimo za to značko {plink}:

<a href={plink Home:default}>domov</a>

ali v kodi

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

Aliasi

Včasih se lahko zgodi, da je koristno paru Presenter:akcija dodeliti lahko zapomnljiv alias. Na primer, domačo stran Front:Home:default poimenovati preprosto kot home ali Admin:Dashboard:default kot admin.

Aliasi se definirajo v konfiguraciji pod ključem application › aliases:

application:
    aliases:
        home: Front:Home:default
        admin: Admin:Dashboard:default
        sign: Front:Sign:in

V povezavah se nato zapisujejo s pomočjo afne, na primer:

<a n:href="@admin">administracija</a>

Podprti so tudi v vseh metodah, ki delajo s povezavami, kot je redirect() in podobno.

Neveljavne povezave

Lahko se zgodi, da ustvarimo neveljavno povezavo – bodisi zato, ker vodi na neobstoječ presenter, ali zato, ker posreduje več parametrov, kot jih ciljna metoda sprejema v svoji signaturi, ali ko za ciljno akcijo ni mogoče generirati URL-ja. Kako ravnati z neveljavnimi povezavami, določa statična spremenljivka Presenter::$invalidLinkMode. Ta lahko prevzame kombinacijo teh vrednosti (konstant):

  • Presenter::InvalidLinkSilent – tihi način, kot URL se vrne znak #
  • Presenter::InvalidLinkWarning – sproži se opozorilo E_USER_WARNING, ki bo v produkcijskem načinu zabeleženo, vendar ne bo povzročilo prekinitve izvajanja skripta
  • Presenter::InvalidLinkTextual – vizualno opozorilo, napako izpiše neposredno v povezavo
  • Presenter::InvalidLinkException – sproži se izjema InvalidLinkException

Privzeta nastavitev je InvalidLinkWarning v produkcijskem načinu in InvalidLinkWarning | InvalidLinkTextual v razvojnem. InvalidLinkWarning v produkcijskem okolju ne povzroči prekinitve skripta, vendar bo opozorilo zabeleženo. V razvojnem okolju ga ujame Tracy in prikaže bluescreen. InvalidLinkTextual deluje tako, da kot URL vrne sporočilo o napaki, ki se začne z znaki #error:. Da bi bile takšne povezave na prvi pogled očitne, si dodamo v CSS:

a[href^="#error:"] {
	background: red;
	color: white;
}

Če ne želimo, da se v razvojnem okolju producirajo opozorila, lahko nastavimo tihi način neposredno v konfiguraciji.

application:
	silentLinks: true

LinkGenerator

Kako ustvarjati povezave s podobnim udobjem kot ima metoda link(), vendar brez prisotnosti presenterja? Za to je tu Nette\Application\LinkGenerator.

LinkGenerator je storitev, ki si jo lahko pustite posredovati prek konstruktorja in nato ustvarjate povezave z njegovo metodo link().

V primerjavi s presenterji je tu razlika. LinkGenerator ustvarja vse povezave takoj kot absolutne URL-je. In nadalje ne obstaja noben „trenutni presenter“, zato ni mogoče kot cilj navesti samo ime akcije link('default') ali navajati relativne poti do modulov.

Neveljavne povezave vedno sprožijo Nette\Application\UI\InvalidLinkException.