Rutarea
Routerul este responsabil pentru tot ceea ce ține de URL-uri, astfel încât nu mai trebuie să vă gândiți la ele. Vom arăta:
- cum să configurați routerul astfel încât URL-urile să arate așa cum doriți.
- câteva note despre redirecționarea SEO
- și vă vom arăta cum să vă scrieți propriul router
URL-urile mai umane (sau URL-urile cool sau frumoase) sunt mai ușor de utilizat, mai ușor de memorat și contribuie pozitiv la SEO. Nette are în vedere acest lucru și satisface pe deplin dorințele dezvoltatorilor. Puteți proiecta structura URL pentru aplicația dumneavoastră exact așa cum doriți. O puteți proiecta chiar și după ce aplicația este gata, deoarece se poate face fără modificări de cod sau de șablon. Aceasta este definită într-un mod elegant într-un singur loc, în router, și nu este împrăștiată sub formă de adnotări în toate prezentatoarele.
Routerul din Nette este special pentru că este bidirecțional, poate atât decoda URL-uri de cerere HTTP, cât și să creeze legături. Astfel, acesta joacă un rol vital în aplicația Nette, deoarece decide ce prezentator și ce acțiune va executa cererea curentă și este, de asemenea, utilizat pentru generarea de URL-uri în șablon etc.
Cu toate acestea, routerul nu se limitează la această utilizare, îl puteți utiliza în aplicații în care nu se folosesc deloc prezentatorii, pentru API-uri REST etc. Mai multe în secțiunea utilizare separată.
Colecția de rute
Cel mai plăcut mod de a defini adresele URL în aplicație este prin intermediul clasei Nette\Application\Routers\RouteList. Definiția constă într-o listă de așa-numite rute, adică măști de adrese URL și prezentatorii și acțiunile asociate acestora, folosind un API simplu. Nu trebuie să denumim rutele.
$router = new Nette\Application\Routers\RouteList;
$router->addRoute('rss.xml', 'Feed:rss');
$router->addRoute('article/<id>', 'Article:view');
// ...
Exemplul spune că, dacă deschidem https://any-domain.com/rss.xml
cu acțiunea rss
, dacă
https://domain.com/article/12
cu acțiunea view
etc. Dacă nu se găsește nicio rută potrivită,
aplicația Nette răspunde prin aruncarea unei excepții BadRequestException, care apare
utilizatorului ca o pagină de eroare 404 Not Found.
Ordinea rutelor
Ordinea în care sunt enumerate rutele este foarte importantă, deoarece acestea sunt evaluate secvențial, de sus în jos. Regula este că declarăm rutele de la specific la general:
// GREȘIT: "rss.xml" se potrivește cu prima rută și înțelege greșit acest lucru ca fiind <slug>
$router->addRoute('<slug>', 'Article:view');
$router->addRoute('rss.xml', 'Feed:rss');
// BUNĂ
$router->addRoute('rss.xml', 'Feed:rss');
$router->addRoute('<slug>', 'Article:view');
Rutele sunt, de asemenea, evaluate de sus în jos atunci când se generează legături:
// WRONG: generează un link către 'Feed:rss' ca 'admin/feed/rss'
$router->addRoute('admin/<presenter>/<action>', 'Admin:default');
$router->addRoute('rss.xml', 'Feed:rss');
// BUNĂ
$router->addRoute('rss.xml', 'Feed:rss');
$router->addRoute('admin/<presenter>/<action>', 'Admin:default');
Nu vă vom ascunde că este nevoie de o anumită îndemânare pentru a construi o listă în mod corect. Până când vă veți familiariza cu ea, panoul de rutare va fi un instrument util.
Mască și parametri
Masca descrie calea relativă bazată pe rădăcina site-ului. Cea mai simplă mască este un URL static:
$router->addRoute('products', 'Products:default');
Adesea, măștile conțin așa-numiții parametri. Aceștia sunt incluși între paranteze unghiulare (de ex.
<year>
) și sunt transmise prezentatorului țintă, de exemplu, metodei renderShow(int $year)
sau
parametrului persistent $year
:
$router->addRoute('chronicle/<year>', 'History:show');
Exemplul spune că, dacă deschidem https://any-domain.com/chronicle/2020
și acțiunea show
cu
parametrul year: 2020
.
Putem specifica o valoare implicită pentru parametrii direct în mască și, astfel, aceasta devine opțională:
$router->addRoute('chronicle/<year=2020>', 'History:show');
Ruta va accepta acum URL-ul https://any-domain.com/chronicle/
cu parametrul year: 2020
.
Bineînțeles, numele prezentatorului și al acțiunii pot fi, de asemenea, un parametru. De exemplu:
$router->addRoute('<presenter>/<action>', 'Home:default');
Această rută acceptă, de exemplu, un URL de forma /article/edit
resp. /catalog/list
și le traduce
în prezentatorii și acțiunile Article:edit
resp. Catalog:list
.
De asemenea, oferă parametrilor presenter
și action
valori impliciteHome
și
default
și, prin urmare, aceștia sunt opționali. Astfel, ruta acceptă și un URL /article
și îl
traduce ca Article:default
. Sau invers, un link către Product:default
generează o cale
/product
, un link către Home:default
implicit generează o cale /
.
Masca poate descrie nu numai calea relativă bazată pe rădăcina site-ului, ci și calea absolută atunci când începe cu o bară oblică, sau chiar întregul URL absolut atunci când începe cu două bare oblice:
// calea relativă către rădăcina documentului aplicației
$router->addRoute('<presenter>/<action>', /* ... */);
// cale absolută, relativă la numele de gazdă al serverului
$router->addRoute('/<presenter>/<action>', /* ... */);
// URL absolut, inclusiv numele de gazdă (dar relativ la schemă)
$router->addRoute('//<lang>.example.com/<presenter>/<action>', /* ... */);
// URL absolut, inclusiv schema
$router->addRoute('https://<lang>.example.com/<presenter>/<action>', /* ... */);
Expresii de validare
Se poate specifica o condiție de validare pentru fiecare parametru folosind expresii regulate. De exemplu, să setați
id
să fie doar numeric, folosind \d+
regexp:
$router->addRoute('<presenter>/<action>[/<id \d+>]', /* ... */);
Expresia regulată implicită pentru toți parametrii este [^/]+
, adică totul cu excepția slash-ului. Dacă un
parametru trebuie să se potrivească și cu o bară oblică, setează expresia regulată la .+
.
// acceptă https://example.com/a/b/c, calea este 'a/b/c'
$router->addRoute('<path .+>', /* ... */);
Secvențe opționale
Parantezele pătrate denotă părțile opționale ale măștii. Orice parte a măștii poate fi stabilită ca opțională, inclusiv cele care conțin parametri:
$router->addRoute('[<lang [a-z]{2}>/]<name>', /* ... */);
// URL-uri acceptate: Parametrii:
// /en/download lang => en, name => download
// /download lang => null, name => download
Bineînțeles, atunci când un parametru face parte dintr-o secvență opțională, acesta devine, de asemenea, opțional. Dacă nu are o valoare implicită, acesta va fi nul.
Secțiunile opționale pot fi, de asemenea, în domeniu:
$router->addRoute('//[<lang=en>.]example.com/<presenter>/<action>', /* ... */);
Secvențele pot fi liber imbricate și combinate:
$router->addRoute(
'[<lang [a-z]{2}>[-<sublang>]/]<name>[/page-<page=0>]',
'Home:default',
);
// URL-uri acceptate:
// /en/hello
// /en-us/hello
// /hello
// /hello/hello/page-12
Generatorul de URL-uri încearcă să mențină URL-ul cât mai scurt posibil, astfel încât ceea ce poate fi omis este omis.
Prin urmare, de exemplu, o rută index[.html]
generează o cale /index
. Puteți inversa acest
comportament scriind un semn de exclamare după paranteza pătrată din stânga:
// acceptă atât /hello cât și /hello.html, generează /hello
$router->addRoute('<name>[.html]', /* ... */);
// acceptă atât /hello cât și /hello.html, generează /hello.html
$router->addRoute('<name>[!.html]', /* ... */);
Parametrii opționali (adică parametrii cu valoare implicită) fără paranteze pătrate se comportă ca și cum ar fi înfășurați astfel:
$router->addRoute('<presenter=Home>/<action=default>/<id=>', /* ... */);
// este egal cu:
$router->addRoute('[<presenter=Home>/[<action=default>/[<id>]]]', /* ... */);
Pentru a schimba modul în care este generată cea mai din dreapta bară oblică, adică în loc de /home/
obțineți un /home
, ajustați traseul în acest fel:
$router->addRoute('[<presenter=Home>[/<action=default>[/<id>]]]', /* ... */);
Wildcards
În masca de cale absolută, putem utiliza următoarele caractere wildcards pentru a evita, de exemplu, necesitatea de a scrie un domeniu în mască, care poate fi diferit în mediul de dezvoltare și în cel de producție:
%tld%
= domeniu de nivel superior, de exemplu,com
sauorg
%sld%
= domeniu de al doilea nivel, de exempluexample
%domain%
= domeniu fără subdomenii, de ex.example.com
%host%
= întreaga gazdă, de ex.www.example.com
%basePath%
= calea către directorul rădăcină
$router->addRoute('//www.%domain%/%basePath%/<presenter>/<action>', /* ... */);
$router->addRoute('//www.%sld%.%tld%/%basePath%/<presenter>/<action', /* ... */);
Notație avansată
Ținta unei rute, scrisă de obicei sub forma Presenter:action
, poate fi exprimată, de asemenea, cu ajutorul unei
matrice care definește parametrii individuali și valorile lor implicite:
$router->addRoute('<presenter>/<action>[/<id \d+>]', [
'presenter' => 'Home',
'action' => 'default',
]);
Pentru o specificație mai detaliată, se poate utiliza o formă și mai extinsă, în care, pe lângă valorile implicite,
pot fi stabilite și alte proprietăți ale parametrilor, cum ar fi o expresie regulată de validare (a se vedea parametrul
id
):
use Nette\Routing\Route;
$router->addRoute('<presenter>/<action>[/<id>]', [
'presenter' => [
Route::Value => 'Home',
],
'action' => [
Route::Value => 'default',
],
'id' => [
Route::Pattern => '\d+',
],
]);
Este important de reținut faptul că, dacă parametrii definiți în matrice nu sunt incluși în masca de cale, valorile lor nu pot fi modificate, nici măcar folosind parametrii de interogare specificați după un semn de întrebare în URL.
Filtre și traduceri
Este o bună practică să scrieți codul sursă în limba engleză, dar ce se întâmplă dacă aveți nevoie ca site-ul dvs. să aibă URL-ul tradus în altă limbă? Rute simple, cum ar fi:
$router->addRoute('<presenter>/<action>', 'Home:default');
va genera URL-uri în limba engleză, cum ar fi /product/123
sau /cart
. Dacă dorim ca prezentatorii
și acțiunile din URL să fie traduse în limba germană (de exemplu, /produkt/123
sau /einkaufswagen
),
putem utiliza un dicționar de traducere. Pentru a-l adăuga, avem deja nevoie de o variantă “mai vorbăreață” a celui
de-al doilea parametru:
use Nette\Routing\Route;
$router->addRoute('<presenter>/<action>', [
'presenter' => [
Route::Value => 'Home',
Route::FilterTable => [
// șir de caractere în URL => prezentator
'produkt' => 'Product',
'einkaufswagen' => 'Cart',
'katalog' => 'Catalog',
],
],
'action' => [
Route::Value => 'default',
Route::FilterTable => [
'liste' => 'list',
],
],
]);
Se pot utiliza mai multe chei de dicționar pentru același prezentator. Acestea vor crea diverse alias-uri pentru acesta. Ultima cheie este considerată a fi varianta canonică (adică cea care se va regăsi în URL-ul generat).
Tabelul de traducere poate fi aplicat în acest mod oricărui parametru. Cu toate acestea, dacă traducerea nu există, se ia
valoarea originală. Putem schimba acest comportament adăugând Route::FilterStrict => true
, iar ruta va respinge
atunci URL-ul dacă valoarea nu se află în dicționar.
În plus față de dicționarul de traduceri sub forma unui array, este posibil să setați propriile funcții de traducere:
use Nette\Routing\Route;
$router->addRoute('<presenter>/<action>/<id>', [
'presenter' => [
Route::Value => 'Home',
Route::FilterIn => function (string $s): string { /* ... */ },
Route::FilterOut => function (string $s): string { /* ... */ },
],
'action' => 'default',
'id' => null,
]);
Funcția Route::FilterIn
face conversia între parametrul din URL și șirul de caractere, care este apoi transmis
către prezentator, funcția FilterOut
asigură conversia în sens invers.
Parametrii presenter
, action
și module
au deja filtre predefinite care convertesc
între stilul PascalCase resp. camelCase și kebab-case utilizat în URL. Valoarea implicită a parametrilor este deja scrisă în
forma transformată, astfel încât, de exemplu, în cazul unui prezentator, se scrie <presenter=ProductEdit>
în loc de <presenter=product-edit>
.
Filtre generale
În afară de filtrele pentru parametri specifici, puteți defini, de asemenea, filtre generale care primesc un tablou
asociativ al tuturor parametrilor pe care îi pot modifica în orice mod și pe care apoi îi pot returna. Filtrele generale se
definesc sub tasta null
.
use Nette\Routing\Route;
$router->addRoute('<presenter>/<action>', [
'presenter' => 'Home',
'action' => 'default',
null => [
Route::FilterIn => function (array $params): array { /* ... */ },
Route::FilterOut => function (array $params): array { /* ... */ },
],
]);
Filtrele generale vă oferă posibilitatea de a ajusta comportamentul traseului în absolut orice mod. Le putem folosi, de
exemplu, pentru a modifica parametrii pe baza altor parametri. De exemplu, traducerea <presenter>
și
<action>
pe baza valorii curente a parametrului <lang>
.
În cazul în care un parametru are definit un filtru personalizat și există în același timp un filtru general, filtrul
personalizat FilterIn
este executat înaintea celui general și, invers, filtrul general FilterOut
este
executat înaintea celui personalizat. Astfel, în interiorul filtrului general se află valorile parametrilor
presenter
și action
scrise în stilul PascalCase și respectiv camelCase.
Indicator unidirecțional
Rutele unidirecționale sunt utilizate pentru a păstra funcționalitatea vechilor URL-uri pe care aplicația nu le mai
generează, dar pe care le acceptă în continuare. Le marcăm cu OneWay
:
// vechiul URL /product-info?id=123
$router->addRoute('product-info', 'Product:detail', $router::ONE_WAY);
// noul URL /product/123
$router->addRoute('product/<id>', 'Product:detail');
La accesarea vechiului URL, prezentatorul redirecționează automat către noul URL, astfel încât motoarele de căutare să nu indexeze aceste pagini de două ori (a se vedea SEO și canonizarea).
Rutarea dinamică cu callback-uri
Rutarea dinamică cu callback-uri vă permite să atribuiți direct funcții (callback-uri) la rute, care vor fi executate atunci când este vizitată calea specificată. Această funcție flexibilă vă permite să creați rapid și eficient diverse puncte finale pentru aplicația dumneavoastră:
$router->addRoute('test', function () {
echo 'You are at the /test address';
});
De asemenea, puteți defini parametri în mască, care vor fi trecuți automat către callback-ul dumneavoastră:
$router->addRoute('<lang cs|en>', function (string $lang) {
echo match ($lang) {
'cs' => 'Welcome to the Czech version of our website!',
'en' => 'Welcome to the English version of our website!',
};
});
Module
Dacă avem mai multe rute care aparțin unui singur modul, putem
folosi withModule()
pentru a le grupa:
$router = new RouteList;
$router->withModule('Forum') // următoarele routere fac parte din modulul Forum
->addRoute('rss', 'Feed:rss') // prezentatorul este Forum:Feed
->addRoute('<presenter>/<action>')
->withModule('Admin') // următoarele routere fac parte din modulul Forum:Admin
->addRoute('sign:in', 'Sign:in');
O alternativă este utilizarea parametrului module
:
// URL manage/dashboard/default se referă la prezentator Admin:Dashboard
$router->addRoute('manage/<presenter>/<action>', [
'module' => 'Admin',
]);
Subdomenii
Colecțiile de rute pot fi grupate pe subdomenii:
$router = new RouteList;
$router->withDomain('example.com')
->addRoute('rss', 'Feed:rss')
->addRoute('<presenter>/<action>');
De asemenea, puteți utiliza caractere sălbatice în numele de domeniu:
$router = new RouteList;
$router->withDomain('example.%tld%')
// ...
Prefix de cale
Colecțiile de rute pot fi grupate în funcție de calea din URL:
$router = new RouteList;
$router->withPath('eshop')
->addRoute('rss', 'Feed:rss') // se potrivește cu URL /eshop/rss
->addRoute('<presenter>/<action>'); // se potrivește cu URL-ul /eshop/<presenter>/<action>
Combinații
Utilizarea de mai sus poate fi combinată:
$router = (new RouteList)
->withDomain('admin.example.com')
->withModule('Admin')
->addRoute(/* ... */)
->addRoute(/* ... */)
->end()
->withModule('Images')
->addRoute(/* ... */)
->end()
->end()
->withDomain('example.com')
->withPath('export')
->addRoute(/* ... */)
// ...
Parametrii de interogare
Măștile pot conține, de asemenea, parametri de interogare (parametri după semnul întrebării din URL). Acestea nu pot defini o expresie de validare, dar pot modifica numele sub care sunt transmise prezentatorului:
// utilizarea parametrului de interogare "cat" ca "categoryId" în aplicație
$router->addRoute('product ? id=<productId> & cat=<categoryId>', /* ... */);
Parametrii Foo
Acum mergem mai departe. Parametrii Foo sunt, în principiu, parametri fără nume care permit să se potrivească cu
o expresie regulată. Următoarea rută se potrivește cu /index
, /index.html
, /index.htm
și /index.php
:
$router->addRoute('index<? \.html?|\.php|>', /* ... */);
De asemenea, este posibil să se definească în mod explicit un șir de caractere care va fi utilizat pentru generarea
URL-urilor. Șirul trebuie să fie plasat direct după semnul întrebării. Următorul traseu este similar cu cel anterior, dar
generează /index.html
în loc de /index
deoarece șirul .html
este definit ca “valoare
generată”.
$router->addRoute('index<?.html \.html?|\.php|>', /* ... */);
Integrare
Pentru a conecta routerul nostru la aplicație, trebuie să informăm containerul DI despre acesta. Cel mai simplu este să
pregătim fabrica care va construi obiectul router și să spunem configurației containerului să o folosească. Să spunem că
scriem o metodă în acest scop App\Core\RouterFactory::createRouter()
:
namespace App\Core;
use Nette\Application\Routers\RouteList;
class RouterFactory
{
public static function createRouter(): RouteList
{
$router = new RouteList;
$router->addRoute(/* ... */);
return $router;
}
}
Apoi scriem în configurație:
services:
- App\Core\RouterFactory::createRouter
Orice dependență, cum ar fi o conexiune la o bază de date etc., este transmisă metodei factory ca parametru al acesteia folosind autowiring:
public static function createRouter(Nette\Database\Connection $db): RouteList
{
// ...
}
SimpleRouter
Un router mult mai simplu decât Route Collection este SimpleRouter. Acesta poate fi
utilizat atunci când nu este nevoie de un format URL specific, când mod_rewrite
(sau alternative) nu este
disponibil sau când pur și simplu nu vrem să ne deranjăm încă cu URL-uri ușor de utilizat.
Generează adrese în aproximativ această formă:
http://example.com/?presenter=Product&action=detail&id=123
Parametrul constructorului SimpleRouter
este un prezentator și o acțiune implicită, adică acțiunea care va
fi executată dacă deschidem, de exemplu, http://example.com/
fără parametri suplimentari.
// implicit la prezentatorul "Home" și acțiunea "default
$router = new Nette\Application\Routers\SimpleRouter('Home:default');
Vă recomandăm să definiți SimpleRouter direct în configurare:
services:
- Nette\Application\Routers\SimpleRouter('Home:default')
SEO și canonizare
Cadrul crește SEO (optimizarea pentru motoarele de căutare) prin prevenirea duplicării conținutului la diferite URL-uri.
În cazul în care mai multe adrese au legătură cu aceeași destinație, de exemplu /index
și
/index.html
, cadrul o determină pe prima ca fiind principală (canonică) și le redirecționează pe celelalte
către aceasta folosind codul HTTP 301. Datorită acestui lucru, motoarele de căutare nu vor indexa paginile de două ori și nu
le strică page rank-ul. .
Acest proces se numește canonizare. URL-ul canonic este cel generat de router, adică de prima rută corespunzătoare din colecția fără indicatorul OneWay. Prin urmare, în colecție, enumerăm mai întâi rutele primare.
Canonizarea este realizată de către prezentator, mai multe în capitolul canonizare.
HTTPS
Pentru a utiliza protocolul HTTPS, este necesar să îl activați la găzduire și să configurați serverul.
Redirecționarea întregului site către HTTPS trebuie efectuată la nivelul serverului, de exemplu, folosind fișierul .htaccess din directorul rădăcină al aplicației noastre, cu codul HTTP 301. Setările pot fi diferite în funcție de găzduire și arată cam așa:
<IfModule mod_rewrite.c>
RewriteEngine On
...
RewriteCond %{HTTPS} off
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
...
</IfModule>
Routerul generează un URL cu același protocol cu cel cu care a fost încărcată pagina, deci nu este nevoie să setați nimic altceva.
Cu toate acestea, dacă avem nevoie în mod excepțional de rute diferite pentru a rula sub protocoale diferite, vom pune acest lucru în masca de rută:
// Va genera o adresă HTTP
$router->addRoute('http://%host%/<presenter>/<action>', /* ... */);
// Va genera o adresă HTTPS
$router->addRoute('https://%host%/<presenter>/<action>', /* ... */);
Debugging Router
Bara de rutare afișată în Tracy Bar este un instrument util care afișează o listă de rute și, de asemenea, parametrii pe care routerul i-a obținut din URL.
Bara verde cu simbolul ✓ reprezintă ruta care a corespuns URL-ului curent, iar barele albastre cu simbolurile ≈ indică rutele care ar corespunde, de asemenea, URL-ului, dacă verdele nu le-ar depăși. Vedem prezentatorul curent & acțiunea în continuare.
În același timp, dacă există o redirecționare neașteptată din cauza canonicalizării, este util să ne uităm în bara redirect pentru a vedea cum a înțeles inițial routerul URL-ul și de ce a redirecționat.
Atunci când depanați routerul, se recomandă să deschideți Instrumente pentru dezvoltatori în browser (Ctrl+Shift+I sau Cmd+Option+I) și să dezactivați memoria cache din panoul Rețea, astfel încât redirecționările să nu fie stocate în ea.
Performanță
Numărul de rute afectează viteza routerului. Cu siguranță, numărul acestora nu trebuie să depășească câteva zeci. Dacă site-ul dumneavoastră are o structură URL prea complicată, puteți scrie un router personalizat.
Dacă routerul nu are dependențe, cum ar fi de o bază de date, iar fabrica sa nu are argumente, putem serializa forma sa compilată direct într-un container DI și, astfel, să facem aplicația puțin mai rapidă.
routing:
cache: true
Router personalizat
Următoarele linii sunt destinate utilizatorilor foarte avansați. Vă puteți crea propriul router și îl puteți adăuga în mod natural în colecția de rute. Routerul este o implementare a interfeței Nette\Routing\Router cu două metode:
use Nette\Http\IRequest as HttpRequest;
use Nette\Http\UrlScript;
class MyRouter implements Nette\Routing\Router
{
public function match(HttpRequest $httpRequest): ?array
{
// ...
}
public function constructUrl(array $params, UrlScript $refUrl): ?string
{
// ...
}
}
Metoda match
procesează $httpRequest curent, din care pot fi
preluate nu numai URL-ul, ci și antetele etc., într-un array care conține numele prezentatorului și parametrii acestuia. În
cazul în care nu poate procesa cererea, se returnează null. Atunci când procesăm cererea, trebuie să returnăm cel puțin
prezentatorul și acțiunea. Numele prezentatorului este complet și include toate modulele:
[
'presenter' => 'Front:Home',
'action' => 'default',
]
Metoda constructUrl
, pe de altă parte, generează un URL absolut din matricea de parametri. Aceasta poate utiliza
informațiile din parametrul $refUrl
, care este URL-ul curent.
Pentru a adăuga un router personalizat la colecția de rute, utilizați add()
:
$router = new Nette\Application\Routers\RouteList;
$router->add($myRouter);
$router->addRoute(/* ... */);
// ...
Utilizare separată
Prin utilizare separată se înțelege utilizarea capacităților routerului într-o aplicație care nu utilizează aplicația Nette și prezentatorii. Aproape tot ceea ce am arătat în acest capitol i se aplică, cu următoarele diferențe:
- pentru colecțiile de rute folosim clasa Nette\Routing\RouteList
- ca o clasă simplă de router Nette\Routing\SimpleRouter
- deoarece nu există o pereche
Presenter:action
, folosim notația Advanced
Deci, din nou, vom crea o metodă care va construi un router, de exemplu:
namespace App\Core;
use Nette\Routing\RouteList;
class RouterFactory
{
public static function createRouter(): RouteList
{
$router = new RouteList;
$router->addRoute('rss.xml', [
'controller' => 'RssFeedController',
]);
$router->addRoute('article/<id \d+>', [
'controller' => 'ArticleController',
]);
// ...
return $router;
}
}
Dacă folosiți un container DI, ceea ce vă recomandăm, adăugați din nou metoda la configurație și apoi obțineți routerul împreună cu cererea HTTP din container:
$router = $container->getByType(Nette\Routing\Router::class);
$httpRequest = $container->getByType(Nette\Http\IRequest::class);
Sau vom crea obiecte direct:
$router = App\Core\RouterFactory::createRouter();
$httpRequest = (new Nette\Http\RequestFactory)->fromGlobals();
Acum trebuie să lăsăm routerul să funcționeze:
$params = $router->match($httpRequest);
if ($params === null) {
// nu s-a găsit nicio rută corespunzătoare, vom trimite o eroare 404
exit;
}
// procesăm parametrii primiți
$controller = $params['controller'];
// ...
Și viceversa, vom folosi routerul pentru a crea legătura:
$params = ['controller' => 'ArticleController', 'id' => 123];
$url = $router->constructUrl($params, $httpRequest->getUrl());