Nette Documentation Preview

syntax
Creazione di link URL
*********************

<div class=perex>

Creare link in Nette è semplice come puntare il dito. Basta mirare e il framework farà tutto il lavoro per voi. Vi mostreremo:

- come creare link nei template e altrove
- come riconoscere un link alla pagina corrente
- cosa fare con i link non validi

</div>


Grazie al [routing bidirezionale |routing] non dovrete mai scrivere a mano nei template o nel codice gli URL della vostra applicazione, che potrebbero cambiare in seguito o essere complicati da comporre. Nel link basta indicare il presenter e l'azione, passare eventuali parametri, e il framework genererà l'URL da sé. In realtà è molto simile a chiamare una funzione. Vi piacerà.


Nel template del presenter
==========================

Il più delle volte creiamo i link nei template, e l'attributo `n:href` è un ottimo aiuto:

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

Notate che al posto dell'attributo HTML `href` abbiamo usato l'[n:attributo |latte:syntax#n:attributi] `n:href`. Il suo valore non è un URL, come sarebbe per l'attributo `href`, ma il nome del presenter e dell'azione.

Cliccare su un link è, detta semplicemente, un po' come chiamare il metodo `ProductPresenter::renderShow()`. E se questo ha dei parametri nella propria firma, possiamo chiamarlo con degli argomenti:

```latte
<a n:href="Product:show $product->id, $product->slug">dettaglio del prodotto</a>
```

È possibile passare anche parametri nominali. Il link seguente passa il parametro `lang` con il valore `en`:

```latte
<a n:href="Product:show $product->id, lang: en">dettaglio del prodotto</a>
```

Se il metodo `ProductPresenter::renderShow()` non ha `$lang` nella propria firma, può ottenere il valore del parametro con `$lang = $this->getParameter('lang')` oppure da una [proprietà |presenters#Parametri della richiesta].

Se i parametri sono salvati in un array, si possono espandere con l'operatore `...`:

```latte
{var $args = [$product->id, lang => en]}
<a n:href="Product:show, ...$args">dettaglio del prodotto</a>
```

Nei link vengono passati automaticamente anche i cosiddetti [parametri persistenti |presenters#Parametri persistenti].

L'attributo `n:href` è molto comodo per i tag HTML `<a>`. Se vogliamo stampare il link altrove, per esempio nel testo, usiamo `{link}`:

```latte
L'URL è: {link Home:default}
```


Nel codice
==========

Per creare un link nel presenter si usa il metodo `link()`:

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

I parametri si possono passare anche come array, in cui si possono indicare anche parametri nominali:

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

I link si possono creare anche senza un presenter, con il [#LinkGenerator] e il suo metodo `link()`.

A volte vi serve creare un link subito, ma generare l'URL vero e proprio solo più tardi. A questo serve il metodo `lazyLink()`, che restituisce un oggetto `Nette\Application\UI\Link`. Il vantaggio è che potete passare questo oggetto, per esempio a un template, e prima che venga disegnato potete ancora modificarne i parametri con il metodo `setParameter()`. L'URL viene composto solo quando l'oggetto viene convertito in stringa:

```php
$link = $this->lazyLink('Product:show', $id);
// ...
echo $link; // l'URL viene generato solo qui
```


Link a un presenter
===================

Se la destinazione del link è un presenter con un'azione, la sintassi è questa:

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

Questo formato è supportato da tutti i tag di Latte e da tutti i metodi del presenter che lavorano con i link, cioè `n:href`, `{link}`, `{plink}`, `link()`, `lazyLink()`, `isLinkCurrent()`, `redirect()`, `redirectPermanent()`, `forward()`, `canonicalize()` e anche dal [#LinkGenerator]. Quindi, anche se negli esempi si usa `n:href`, al suo posto potrebbe esserci una qualsiasi di queste funzioni.

La forma di base è dunque `Presenter:azione`:

```latte
<a n:href="Home:default">home page</a>
```

Se colleghiamo a un'azione del presenter corrente, possiamo ometterne il nome:

```latte
<a n:href="default">home page</a>
```

Se l'azione di destinazione è `default`, possiamo ometterla, ma i due punti devono restare:

```latte
<a n:href="Home:">home page</a>
```

I link possono puntare anche ad altri [moduli |directory-structure#Presenter e template]. Qui si distingue tra link relativi a un sottomodulo annidato e link assoluti. Il principio è analogo a quello dei percorsi su disco, solo che al posto delle barre si usano i due punti. Supponendo che il presenter corrente faccia parte del modulo `Front`, scriveremmo:

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

Un caso particolare è il link [a sé stessi |#Link alla pagina corrente], dove indichiamo come destinazione `this`.

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

Possiamo collegare a una parte precisa della pagina tramite il cosiddetto frammento dopo il cancelletto `#`:

```latte
<a n:href="Home:#main">link a Home:default e al frammento #main</a>
```

.{data-version:3.3.0}
Il frammento si può impostare anche dinamicamente, come argomento con la chiave `#`. Il suo valore viene codificato automaticamente e ha la precedenza sul frammento indicato nella destinazione:

```php
$this->link('Home:default', ['#' => $fragment]);
```


Percorsi assoluti
=================

I link generati con `link()` o `n:href` sono sempre percorsi assoluti (cioè iniziano con `/`), ma non URL assoluti con protocollo e dominio, come `https://domain`.

Per generare un URL assoluto aggiungete due barre all'inizio (per esempio `n:href="//Home:"`). In alternativa potete far generare al presenter solo link assoluti impostando `$this->absoluteUrls = true`.

Nel template si può usare anche il filtro `|absoluteUrl` per convertire un percorso relativo in uno assoluto.


Link alla pagina corrente
=========================

La destinazione `this` crea un link alla pagina corrente:

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

Allo stesso tempo vengono trasferiti tutti i parametri indicati nella firma del metodo `action<Azione>()` o `render<Vista>()` (se `action<Azione>()` non è definito). Se quindi ci troviamo sulla pagina `Product:show` con `id: 123`, anche il link a `this` passerà questo parametro.

Naturalmente è possibile indicare i parametri direttamente:

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

La funzione `isLinkCurrent()` controlla se la destinazione del link coincide con la pagina corrente. Si può usare per esempio in un template per distinguere i link e simili.

I parametri sono gli stessi del metodo `link()`, ma al posto di un'azione specifica si può usare anche il carattere jolly `*`, che indica una qualsiasi azione del presenter indicato.

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

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

In combinazione con `n:href` su un unico elemento si può usare una forma abbreviata:

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

Il carattere jolly `*` si può usare solo al posto dell'azione, non del presenter.

Per stabilire se ci troviamo in un determinato modulo o in un suo sottomodulo, usate il metodo `isModuleCurrent(moduleName)`.

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


Cambiare la base dei link .{data-version:3.2.7}
===============================================

Per impostazione predefinita i link relativi sono derivati dal presenter corrente. Lo si può cambiare con `{linkBase}`:

```latte
{linkBase Admin:Dashboard}
<a n:href="Product:show">dettaglio del prodotto</a>
```

Il link porterà a `Admin:Dashboard:Product:show`. Ne sono interessati solo i link relativi: i link assoluti che iniziano con i due punti e i link al presenter corrente (`this`, `show`) restano invariati.

`{linkBase}` vale per l'intero template ed è particolarmente utile nei template di layout, dove garantisce link coerenti indipendentemente dal presenter chiamante.
Il tag va collocato all'inizio del template, altrimenti solleva una `CompileException`.


Link a un segnale
=================

La destinazione di un link non deve essere per forza un presenter con un'azione: può essere anche un [segnale |components#Segnale] (che chiama il metodo `handle<Segnale>()`). La sintassi è allora questa:

```
[//] [sotto-componente:]segnale! [#fragment]
```

Il segnale si distingue quindi per il punto esclamativo:

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

Potete creare anche un link a un segnale di un sottocomponente (o di un sotto-sottocomponente):

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


Link in un componente
=====================

Poiché i [componenti|components] sono unità riutilizzabili autonome, che non dovrebbero avere alcun legame con i presenter circostanti, qui i link funzionano in modo un po' diverso. L'attributo Latte `n:href` e il tag `{link}`, così come i metodi del componente come `link()` e altri, **considerano sempre la destinazione del link come il nome di un segnale**. Non è quindi nemmeno necessario indicare il punto esclamativo:

```latte
<a n:href="click">segnale, non un'azione</a>
```

Se volessimo collegare ai presenter nel template di un componente, useremmo il tag `{plink}`:

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

oppure nel codice

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


Alias .{data-version:3.2.3}
===========================

A volte può essere utile assegnare a una coppia Presenter:azione un alias facile da ricordare. Per esempio chiamare la home page `Front:Home:default` semplicemente `home`, oppure `Admin:Dashboard:default` come `admin`.

Gli alias si definiscono nella [configurazione|configuration], sotto la chiave `application › aliases`:

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

Nei link si scrivono poi con la chiocciola, per esempio:

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

Sono supportati anche in tutti i metodi che lavorano con i link, come `redirect()` e simili.


Link non validi
===============

Può capitare di creare un link non valido: perché porta a un presenter inesistente, perché passa più parametri di quanti ne accetti il metodo di destinazione nella propria firma, oppure perché per l'azione di destinazione non è possibile generare un URL. Come gestire i link non validi si imposta nel presenter con `$this->invalidLinkMode`. Può assumere una combinazione di questi valori (costanti):

- `Presenter::InvalidLinkSilent` - modalità silenziosa, restituisce come URL il carattere #
- `Presenter::InvalidLinkWarning` - viene emesso un avviso E_USER_WARNING, che in modalità di produzione verrà registrato nel log ma non interromperà l'esecuzione dello script
- `Presenter::InvalidLinkTextual` - avviso visivo, stampa l'errore direttamente nel link
- `Presenter::InvalidLinkException` - solleva InvalidLinkException

L'impostazione predefinita è `InvalidLinkWarning` in modalità di produzione e `InvalidLinkWarning | InvalidLinkTextual` in modalità di sviluppo. In ambiente di produzione `InvalidLinkWarning` non provoca l'interruzione dello script, ma l'avviso verrà registrato nel log. In ambiente di sviluppo lo intercetta [Tracy |tracy:] e mostra una schermata blu. `InvalidLinkTextual` funziona restituendo come URL un messaggio di errore che inizia con i caratteri `#error:`. Perché link del genere si notino a colpo d'occhio, aggiungete al vostro CSS:

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

Se non vogliamo che in ambiente di sviluppo vengano emessi avvisi, possiamo silenziarli direttamente nella [configurazione|configuration].

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


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

Come creare link con la stessa comodità del metodo `link()`, ma senza la presenza di un presenter? A questo serve [api:Nette\Application\LinkGenerator].

LinkGenerator è un servizio che potete farvi passare tramite il costruttore e con cui potete poi creare link usandone il metodo `link()`.

C'è una differenza rispetto ai presenter. LinkGenerator crea tutti i link direttamente come URL assoluti. Inoltre non esiste un "presenter corrente", quindi non è possibile indicare come destinazione solo il nome dell'azione, `link('default')`, né usare percorsi relativi ai moduli.

I link non validi sollevano sempre `Nette\Application\UI\InvalidLinkException`.

Creazione di link URL

Creare link in Nette è semplice come puntare il dito. Basta mirare e il framework farà tutto il lavoro per voi. Vi mostreremo:

  • come creare link nei template e altrove
  • come riconoscere un link alla pagina corrente
  • cosa fare con i link non validi

Grazie al routing bidirezionale non dovrete mai scrivere a mano nei template o nel codice gli URL della vostra applicazione, che potrebbero cambiare in seguito o essere complicati da comporre. Nel link basta indicare il presenter e l'azione, passare eventuali parametri, e il framework genererà l'URL da sé. In realtà è molto simile a chiamare una funzione. Vi piacerà.

Nel template del presenter

Il più delle volte creiamo i link nei template, e l'attributo n:href è un ottimo aiuto:

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

Notate che al posto dell'attributo HTML href abbiamo usato l'n:attributo n:href. Il suo valore non è un URL, come sarebbe per l'attributo href, ma il nome del presenter e dell'azione.

Cliccare su un link è, detta semplicemente, un po' come chiamare il metodo ProductPresenter::renderShow(). E se questo ha dei parametri nella propria firma, possiamo chiamarlo con degli argomenti:

<a n:href="Product:show $product->id, $product->slug">dettaglio del prodotto</a>

È possibile passare anche parametri nominali. Il link seguente passa il parametro lang con il valore en:

<a n:href="Product:show $product->id, lang: en">dettaglio del prodotto</a>

Se il metodo ProductPresenter::renderShow() non ha $lang nella propria firma, può ottenere il valore del parametro con $lang = $this->getParameter('lang') oppure da una proprietà.

Se i parametri sono salvati in un array, si possono espandere con l'operatore ...:

{var $args = [$product->id, lang => en]}
<a n:href="Product:show, ...$args">dettaglio del prodotto</a>

Nei link vengono passati automaticamente anche i cosiddetti parametri persistenti.

L'attributo n:href è molto comodo per i tag HTML <a>. Se vogliamo stampare il link altrove, per esempio nel testo, usiamo {link}:

L'URL è: {link Home:default}

Nel codice

Per creare un link nel presenter si usa il metodo link():

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

I parametri si possono passare anche come array, in cui si possono indicare anche parametri nominali:

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

I link si possono creare anche senza un presenter, con il LinkGenerator e il suo metodo link().

A volte vi serve creare un link subito, ma generare l'URL vero e proprio solo più tardi. A questo serve il metodo lazyLink(), che restituisce un oggetto Nette\Application\UI\Link. Il vantaggio è che potete passare questo oggetto, per esempio a un template, e prima che venga disegnato potete ancora modificarne i parametri con il metodo setParameter(). L'URL viene composto solo quando l'oggetto viene convertito in stringa:

$link = $this->lazyLink('Product:show', $id);
// ...
echo $link; // l'URL viene generato solo qui

Se la destinazione del link è un presenter con un'azione, la sintassi è questa:

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

Questo formato è supportato da tutti i tag di Latte e da tutti i metodi del presenter che lavorano con i link, cioè n:href, {link}, {plink}, link(), lazyLink(), isLinkCurrent(), redirect(), redirectPermanent(), forward(), canonicalize() e anche dal LinkGenerator. Quindi, anche se negli esempi si usa n:href, al suo posto potrebbe esserci una qualsiasi di queste funzioni.

La forma di base è dunque Presenter:azione:

<a n:href="Home:default">home page</a>

Se colleghiamo a un'azione del presenter corrente, possiamo ometterne il nome:

<a n:href="default">home page</a>

Se l'azione di destinazione è default, possiamo ometterla, ma i due punti devono restare:

<a n:href="Home:">home page</a>

I link possono puntare anche ad altri moduli. Qui si distingue tra link relativi a un sottomodulo annidato e link assoluti. Il principio è analogo a quello dei percorsi su disco, solo che al posto delle barre si usano i due punti. Supponendo che il presenter corrente faccia parte del modulo Front, scriveremmo:

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

Un caso particolare è il link a sé stessi, dove indichiamo come destinazione this.

<a n:href="this">aggiorna</a>

Possiamo collegare a una parte precisa della pagina tramite il cosiddetto frammento dopo il cancelletto #:

<a n:href="Home:#main">link a Home:default e al frammento #main</a>

Il frammento si può impostare anche dinamicamente, come argomento con la chiave #. Il suo valore viene codificato automaticamente e ha la precedenza sul frammento indicato nella destinazione:

$this->link('Home:default', ['#' => $fragment]);

Percorsi assoluti

I link generati con link() o n:href sono sempre percorsi assoluti (cioè iniziano con /), ma non URL assoluti con protocollo e dominio, come https://domain.

Per generare un URL assoluto aggiungete due barre all'inizio (per esempio n:href="//Home:"). In alternativa potete far generare al presenter solo link assoluti impostando $this->absoluteUrls = true.

Nel template si può usare anche il filtro |absoluteUrl per convertire un percorso relativo in uno assoluto.

La destinazione this crea un link alla pagina corrente:

<a n:href="this">aggiorna</a>

Allo stesso tempo vengono trasferiti tutti i parametri indicati nella firma del metodo action<Azione>() o render<Vista>() (se action<Azione>() non è definito). Se quindi ci troviamo sulla pagina Product:show con id: 123, anche il link a this passerà questo parametro.

Naturalmente è possibile indicare i parametri direttamente:

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

La funzione isLinkCurrent() controlla se la destinazione del link coincide con la pagina corrente. Si può usare per esempio in un template per distinguere i link e simili.

I parametri sono gli stessi del metodo link(), ma al posto di un'azione specifica si può usare anche il carattere jolly *, che indica una qualsiasi azione del presenter indicato.

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

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

In combinazione con n:href su un unico elemento si può usare una forma abbreviata:

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

Il carattere jolly * si può usare solo al posto dell'azione, non del presenter.

Per stabilire se ci troviamo in un determinato modulo o in un suo sottomodulo, usate il metodo isModuleCurrent(moduleName).

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

Per impostazione predefinita i link relativi sono derivati dal presenter corrente. Lo si può cambiare con {linkBase}:

{linkBase Admin:Dashboard}
<a n:href="Product:show">dettaglio del prodotto</a>

Il link porterà a Admin:Dashboard:Product:show. Ne sono interessati solo i link relativi: i link assoluti che iniziano con i due punti e i link al presenter corrente (this, show) restano invariati.

{linkBase} vale per l'intero template ed è particolarmente utile nei template di layout, dove garantisce link coerenti indipendentemente dal presenter chiamante. Il tag va collocato all'inizio del template, altrimenti solleva una CompileException.

La destinazione di un link non deve essere per forza un presenter con un'azione: può essere anche un segnale (che chiama il metodo handle<Segnale>()). La sintassi è allora questa:

[//] [sotto-componente:]segnale! [#fragment]

Il segnale si distingue quindi per il punto esclamativo:

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

Potete creare anche un link a un segnale di un sottocomponente (o di un sotto-sottocomponente):

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

Poiché i componenti sono unità riutilizzabili autonome, che non dovrebbero avere alcun legame con i presenter circostanti, qui i link funzionano in modo un po' diverso. L'attributo Latte n:href e il tag {link}, così come i metodi del componente come link() e altri, considerano sempre la destinazione del link come il nome di un segnale. Non è quindi nemmeno necessario indicare il punto esclamativo:

<a n:href="click">segnale, non un'azione</a>

Se volessimo collegare ai presenter nel template di un componente, useremmo il tag {plink}:

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

oppure nel codice

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

Alias

A volte può essere utile assegnare a una coppia Presenter:azione un alias facile da ricordare. Per esempio chiamare la home page Front:Home:default semplicemente home, oppure Admin:Dashboard:default come admin.

Gli alias si definiscono nella configurazione, sotto la chiave application › aliases:

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

Nei link si scrivono poi con la chiocciola, per esempio:

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

Sono supportati anche in tutti i metodi che lavorano con i link, come redirect() e simili.

Può capitare di creare un link non valido: perché porta a un presenter inesistente, perché passa più parametri di quanti ne accetti il metodo di destinazione nella propria firma, oppure perché per l'azione di destinazione non è possibile generare un URL. Come gestire i link non validi si imposta nel presenter con $this->invalidLinkMode. Può assumere una combinazione di questi valori (costanti):

  • Presenter::InvalidLinkSilent – modalità silenziosa, restituisce come URL il carattere #
  • Presenter::InvalidLinkWarning – viene emesso un avviso E_USER_WARNING, che in modalità di produzione verrà registrato nel log ma non interromperà l'esecuzione dello script
  • Presenter::InvalidLinkTextual – avviso visivo, stampa l'errore direttamente nel link
  • Presenter::InvalidLinkException – solleva InvalidLinkException

L'impostazione predefinita è InvalidLinkWarning in modalità di produzione e InvalidLinkWarning | InvalidLinkTextual in modalità di sviluppo. In ambiente di produzione InvalidLinkWarning non provoca l'interruzione dello script, ma l'avviso verrà registrato nel log. In ambiente di sviluppo lo intercetta Tracy e mostra una schermata blu. InvalidLinkTextual funziona restituendo come URL un messaggio di errore che inizia con i caratteri #error:. Perché link del genere si notino a colpo d'occhio, aggiungete al vostro CSS:

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

Se non vogliamo che in ambiente di sviluppo vengano emessi avvisi, possiamo silenziarli direttamente nella configurazione.

application:
	silentLinks: true

LinkGenerator

Come creare link con la stessa comodità del metodo link(), ma senza la presenza di un presenter? A questo serve Nette\Application\LinkGenerator.

LinkGenerator è un servizio che potete farvi passare tramite il costruttore e con cui potete poi creare link usandone il metodo link().

C'è una differenza rispetto ai presenter. LinkGenerator crea tutti i link direttamente come URL assoluti. Inoltre non esiste un „presenter corrente“, quindi non è possibile indicare come destinazione solo il nome dell'azione, link('default'), né usare percorsi relativi ai moduli.

I link non validi sollevano sempre Nette\Application\UI\InvalidLinkException.