Crearea linkurilor URL

Crearea linkurilor în Nette este simplă, ca și cum ai arăta cu degetul. Trebuie doar să țintești și framework-ul va face toată munca pentru tine. Vom arăta:

  • cum să creezi linkuri în șabloane și în altă parte
  • cum să distingi un link către pagina curentă
  • ce să faci cu linkurile invalide

Datorită rutării bidirecționale, nu va trebui niciodată să scrieți manual adresele URL ale aplicației dvs. în șabloane sau cod, adrese care s-ar putea schimba ulterior, sau să le compuneți complicat. În link este suficient să specificați presenterul și acțiunea, să transmiteți eventualii parametri și framework-ul va genera URL-ul singur. De fapt, este foarte asemănător cu apelarea unei funcții. Acest lucru vă va plăcea.

În șablonul presenterului

Cel mai adesea creăm linkuri în șabloane, iar un ajutor excelent este atributul n:href:

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

Observați că în loc de atributul HTML href, am folosit n:atributul n:href. Valoarea sa nu este apoi URL-ul, așa cum ar fi în cazul atributului href, ci numele presenterului și al acțiunii.

Click-ul pe link este, simplificat spus, ceva asemănător cu apelarea metodei ProductPresenter::renderShow(). Și dacă are parametri în semnătura sa, o putem apela cu argumente:

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

Este posibil să se transmită și parametri numiți. Următorul link transmite parametrul lang cu valoarea cs:

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

Dacă metoda ProductPresenter::renderShow() nu are $lang în semnătura sa, poate afla valoarea parametrului folosind $lang = $this->getParameter('lang') sau din proprietate.

Dacă parametrii sunt stocați într-un array, aceștia pot fi expandați cu operatorul ... (în Latte 2.x cu operatorul (expand)):

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

În linkuri se transmit automat și așa-numiții parametri persistenți.

Atributul n:href este foarte util pentru tag-urile HTML <a>. Dacă dorim să afișăm linkul în altă parte, de exemplu în text, folosim {link}:

Adresa este: {link Home:default}

În cod

Pentru a crea un link în presenter se folosește metoda link():

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

Parametrii pot fi transmiși și printr-un array, unde se pot specifica și parametri numiți:

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

Linkurile pot fi create și fără presenter, pentru asta există LinkGenerator și metoda sa link().

Linkuri către presenter

Dacă ținta linkului este un presenter și o acțiune, are această sintaxă:

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

Formatul este suportat de toate tag-urile Latte și toate metodele presenterului care lucrează cu linkuri, adică n:href, {link}, {plink}, link(), lazyLink(), isLinkCurrent(), redirect(), redirectPermanent(), forward(), canonicalize() și, de asemenea, LinkGenerator. Deci, chiar dacă în exemple este folosit n:href, ar putea fi oricare dintre funcții.

Forma de bază este deci Presenter:action:

<a n:href="Home:default">pagina principală</a>

Dacă facem referire la acțiunea presenterului curent, putem omite numele acestuia:

<a n:href="default">pagina principală</a>

Dacă ținta este acțiunea default, o putem omite, dar două puncte trebuie să rămână:

<a n:href="Home:">pagina principală</a>

Linkurile pot, de asemenea, să direcționeze către alte module. Aici, linkurile se disting între cele relative către un submodul imbricat și cele absolute. Principiul este analog cu căile de pe disc, doar că în loc de slash-uri sunt două puncte. Presupunem că presenterul curent face parte din modulul Front, atunci scriem:

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

Un caz special este linkul către sine însuși, când specificăm this ca țintă.

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

Putem face referire la o anumită parte a paginii prin așa-numitul fragment după semnul diez #:

<a n:href="Home:#main">link către Home:default și fragmentul #main</a>

Căi absolute

Linkurile generate folosind link() sau n:href sunt întotdeauna căi absolute (adică încep cu caracterul /), dar nu URL-uri absolute cu protocol și domeniu precum https://domain.

Pentru a genera un URL absolut, adăugați două slash-uri la început (de ex. n:href="//Home:"). Sau puteți comuta presenterul să genereze doar linkuri absolute setând $this->absoluteUrls = true.

Ținta this creează un link către pagina curentă:

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

În același timp, se transmit și toți parametrii specificați în semnătura metodei action<Action>() sau render<View>(), dacă action<Action>() nu este definită. Deci, dacă suntem pe pagina Product:show și id: 123, linkul către this va transmite și acest parametru.

Desigur, este posibil să specificați parametrii direct:

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

Funcția isLinkCurrent() verifică dacă ținta linkului este identică cu pagina curentă. Acest lucru poate fi utilizat, de exemplu, în șablon pentru a distinge linkurile etc.

Parametrii sunt aceiași ca la metoda link(), dar în plus este posibil să se specifice un wildcard * în loc de o acțiune specifică, ceea ce înseamnă orice acțiune a presenterului respectiv.

{if !isLinkCurrent('Admin:login')}
	<a n:href="Admin:login">Conectați-vă</a>
{/if}

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

În combinație cu n:href într-un singur element, se poate folosi o formă prescurtată:

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

Wildcard-ul * poate fi folosit doar în locul acțiunii, nu și al presenterului.

Pentru a verifica dacă ne aflăm într-un anumit modul sau submodul al acestuia, folosim metoda isModuleCurrent(moduleName).

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

Linkuri către semnal

Ținta linkului nu trebuie să fie doar un presenter și o acțiune, ci și un semnal (apelează metoda handle<Signal>()). Atunci sintaxa este următoarea:

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

Semnalul este deci distins prin semnul exclamării:

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

Se poate crea și un link către semnalul unei subcomponente (sau sub-subcomponente):

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

Linkuri în componentă

Deoarece componentele sunt unități separate, reutilizabile, care nu ar trebui să aibă nicio legătură cu presenterele din jur, linkurile funcționează aici puțin diferit. Atributul Latte n:href și tag-ul {link}, precum și metodele componentei precum link() și altele consideră ținta linkului întotdeauna ca fiind numele semnalului. De aceea, nu este necesar nici măcar să se specifice semnul exclamării:

<a n:href="click">semnal, nu acțiune</a>

Dacă am dori să facem referire la presentere în șablonul componentei, folosim tag-ul {plink}:

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

sau în cod

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

Aliasuri

Uneori poate fi util să atribuiți perechii Presenter:acțiune un alias ușor de reținut. De exemplu, pagina de start Front:Home:default să o numiți simplu home sau Admin:Dashboard:default ca admin.

Aliasurile se definesc în configurație sub cheia application › aliases:

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

În linkuri se scriu apoi folosind arondul, de exemplu:

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

Sunt suportate și în toate metodele care lucrează cu linkuri, cum ar fi redirect() și altele asemenea.

Linkuri invalide

Se poate întâmpla să creăm un link invalid – fie pentru că duce la un presenter inexistent, fie pentru că transmite mai mulți parametri decât acceptă metoda țintă în semnătura sa, sau când nu se poate genera un URL pentru acțiunea țintă. Cum să tratăm linkurile invalide este determinat de variabila statică Presenter::$invalidLinkMode. Aceasta poate lua o combinație a acestor valori (constante):

  • Presenter::InvalidLinkSilent – mod silențios, ca URL se returnează caracterul #
  • Presenter::InvalidLinkWarning – se aruncă o avertizare E_USER_WARNING, care va fi înregistrată în modul de producție, dar nu va cauza întreruperea execuției scriptului
  • Presenter::InvalidLinkTextual – avertizare vizuală, afișează eroarea direct în link
  • Presenter::InvalidLinkException – se aruncă excepția InvalidLinkException

Setarea implicită este InvalidLinkWarning în modul de producție și InvalidLinkWarning | InvalidLinkTextual în modul de dezvoltare. InvalidLinkWarning în mediul de producție nu cauzează întreruperea scriptului, dar avertizarea va fi înregistrată. În mediul de dezvoltare, Tracy o va captura și va afișa un bluescreen. InvalidLinkTextual funcționează astfel încât returnează ca URL un mesaj de eroare care începe cu caracterele #error:. Pentru ca astfel de linkuri să fie vizibile la prima vedere, adăugăm în CSS:

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

Dacă nu dorim să se producă avertizări în mediul de dezvoltare, putem seta modul silențios direct în configurație.

application:
	silentLinks: true

LinkGenerator

Cum să creăm linkuri cu un confort similar cu cel al metodei link(), dar fără prezența unui presenter? Pentru asta există Nette\Application\LinkGenerator.

LinkGenerator este un serviciu pe care îl puteți primi prin constructor și apoi crea linkuri folosind metoda sa link().

Spre deosebire de presentere, există o diferență. LinkGenerator creează toate linkurile direct ca URL-uri absolute. Și, în plus, nu există niciun “presenter curent”, deci nu se poate specifica doar numele acțiunii link('default') ca țintă sau specifica căi relative către module.

Linkurile invalide aruncă întotdeauna Nette\Application\UI\InvalidLinkException.

versiune: 4.0