Creazione di collegamenti URL

Creare collegamenti in Nette è facile come puntare un dito. Basta indicare e il framework farà tutto il lavoro per voi. Vi mostreremo:

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

Grazie al routing bidirezionale, non dovrete mai codificare gli URL delle applicazioni nei template o nel codice, che potrebbero cambiare in seguito o essere complicati da comporre. Basta specificare il presentatore e l'azione nel link, passare eventuali parametri e il framework genererà da solo l'URL. In effetti, è molto simile alla chiamata di una funzione. Vi piacerà.

Nel modello del presentatore

Il più delle volte creiamo collegamenti nei modelli e un grande aiuto è l'attributo n:href:

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

Si noti che al posto dell'attributo HTML href abbiamo usato n:attributo n:href. Il suo valore non è un URL, come si è abituati a vedere con l'attributo href, ma il nome del presentatore e l'azione.

Cliccare su un link è, in parole povere, come chiamare un metodo ProductPresenter::renderShow(). E se ha dei parametri nella sua firma, possiamo chiamarlo con degli argomenti:

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

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

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

Se il metodo ProductPresenter::renderShow() non ha $lang nella sua firma, può recuperare il valore del parametro usando $lang = $this->getParameter('lang') o dalla proprietà.

Se i parametri sono memorizzati in un array, possono essere espansi con l'operatore ... (o (expand) in Latte 2.x):

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

Anche i cosiddetti parametri persistenti vengono passati automaticamente nei collegamenti.

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

URL is: {link Home:default}

Nel codice

Il metodo link() viene utilizzato per creare un collegamento nel presentatore:

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

I parametri possono essere passati anche come array in cui possono essere specificati anche parametri denominati:

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

I collegamenti possono essere creati anche senza presentatore, utilizzando il LinkGenerator e il suo metodo link().

Se l'obiettivo del collegamento è il presentatore e l'azione, la sintassi è questa:

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

Il formato è supportato da tutti i tag Latte e da tutti i metodi del presentatore che funzionano con i collegamenti, cioè n:href, {link}, {plink}, link(), lazyLink(), isLinkCurrent(), redirect(), redirectPermanent(), forward(), canonicalize() e anche LinkGenerator. Quindi, anche se negli esempi viene utilizzato n:href, potrebbe essere presente una qualsiasi delle funzioni.

La forma base è quindi Presenter:action:

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

Se ci si collega all'azione del presentatore corrente, si può omettere il suo nome:

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

Se l'azione è default, possiamo ometterlo, ma i due punti devono rimanere:

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

I collegamenti possono anche puntare ad altri moduli. In questo caso, i collegamenti si distinguono in relativi ai sottomoduli o assoluti. Il principio è analogo a quello dei percorsi su disco, solo che al posto degli slash ci sono i punti. Supponiamo che il presentatore attuale faccia parte del modulo Front, quindi scriveremo:

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

Un caso particolare è il collegamento a se stesso. Qui scriveremo this come target.

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

Possiamo collegarci a una determinata parte della pagina HTML tramite un cosiddetto frammento dopo il simbolo hash #:

<a n:href="Home:#main">link to Home:default and fragment #main</a>

Percorsi assoluti

I link generati da 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, aggiungere due barre all'inizio (ad esempio, n:href="//Home:"). Oppure si può impostare il presentatore in modo che generi solo collegamenti assoluti, impostando $this->absoluteUrls = true.

Il target this creerà un collegamento alla pagina corrente:

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

Allo stesso tempo, tutti i parametri specificati nella firma dell'elemento action<Action>() o render<View>() se il metodo action<Action>() non è definito, vengono trasferiti. Quindi, se ci troviamo nelle pagine Product:show e id:123, il collegamento a this passerà anche questo parametro.

Naturalmente, è possibile specificare direttamente i parametri:

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

La funzione isLinkCurrent() determina se la destinazione del link è la stessa della pagina corrente. Questo può essere utilizzato, ad esempio, in un modello per differenziare i collegamenti, ecc.

I parametri sono gli stessi del metodo link(), ma è anche possibile utilizzare il carattere jolly * al posto di un'azione specifica, ovvero qualsiasi azione del presentatore.

{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>

Una forma abbreviata può essere usata in combinazione con n:href in un singolo elemento:

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

Il carattere jolly * sostituisce solo l'azione del presentatore, non il presentatore stesso.

Per sapere se ci troviamo in un certo modulo o in un suo sottomodulo, possiamo usare la funzione isModuleCurrent(moduleName).

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

Il target del collegamento può essere non solo il presentatore e l'azione, ma anche il segnale (chiamano il metodo handle<Signal>()). La sintassi è la seguente:

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

Il segnale è quindi contraddistinto dal punto esclamativo:

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

È inoltre possibile creare un collegamento al segnale del sottocomponente (o del sottocomponente):

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

Poiché i componenti sono unità riutilizzabili separate che non dovrebbero avere relazioni con i presentatori circostanti, i collegamenti funzionano in modo leggermente diverso. L'attributo Latte n:href e il tag {link} e i metodi dei componenti come link() e altri considerano sempre la destinazione come il nome del segnale. Pertanto non è necessario utilizzare un punto esclamativo:

<a n:href="click">signal, not an action</a>

Se vogliamo collegarci ai presentatori nel modello del componente, usiamo il tag {plink}:

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

o nel codice

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

Può capitare di creare un collegamento non valido, sia perché fa riferimento a un presentatore inesistente, sia perché passa più parametri di quelli che il metodo di destinazione riceve nella sua firma, sia quando non è possibile generare un URL per l'azione mirata. Cosa fare con i collegamenti non validi è determinato dalla variabile statica Presenter::$invalidLinkMode. Essa può avere uno dei seguenti valori (costanti):

  • Presenter::InvalidLinkSilent – modalità silenziosa, restituisce il simbolo # come URL
  • Presenter::InvalidLinkWarning – verrà prodotto E_USER_WARNING
  • Presenter::InvalidLinkTextual – avviso visivo, il testo dell'errore viene visualizzato nel link
  • Presenter::InvalidLinkException – Viene lanciata l'eccezione InvalidLinkException.

L'impostazione predefinita in modalità di produzione è InvalidLinkWarning e in modalità di sviluppo è InvalidLinkWarning | InvalidLinkTextual. InvalidLinkWarning non uccide lo script nell'ambiente di produzione, ma l'avviso viene registrato. Nell'ambiente di sviluppo, Tracy intercetta l'avviso e visualizza la schermata di errore. Se InvalidLinkTextual è impostato, il presentatore e i componenti restituiscono il messaggio di errore come URL che inizia con #error:. Per rendere visibili tali collegamenti, possiamo aggiungere una regola CSS al nostro foglio di stile:

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

Se non vogliamo che vengano prodotti avvisi nell'ambiente di sviluppo, possiamo attivare la modalità silenziosa di collegamento non valido nella configurazione.

application:
	silentLinks: true

Generatore di collegamenti

Come creare link con il metodo link(), ma senza la presenza di un presentatore? Ecco perché Nette\Application\LinkGenerator.

LinkGenerator è un servizio che si può far passare attraverso il costruttore e poi creare link con il suo metodo link().

C'è una differenza rispetto ai presentatori. LinkGenerator crea tutti i collegamenti come URL assoluti. Inoltre, non esiste un “presentatore corrente”, quindi non è possibile specificare solo il nome dell'azione link('default') o i percorsi relativi ai moduli.

I collegamenti non validi lanciano sempre Nette\Application\UI\InvalidLinkException.

versione: 4.0