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 sau org
  • %sld% = domeniu de al doilea nivel, de exemplu example
  • %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ă

Al doilea parametru al traseului, pe care îl scriem adesea în formatul Presenter:action, este o abreviere, pe care o putem scrie și sub forma unui câmp, în care indicăm direct valorile (implicite) ale parametrilor individuali:

$router->addRoute('<presenter>/<action>[/<id \d+>]', [
	'presenter' => 'Home',
	'action' => 'default',
]);

Sau putem folosi această formă, observați rescrierea expresiei regulate de validare:

use Nette\Routing\Route;

$router->addRoute('<presenter>/<action>[/<id>]', [
	'presenter' => [
		Route::Value => 'Home',
	],
	'action' => [
		Route::Value => 'default',
	],
	'id' => [
		Route::Pattern => '\d+',
	],
]);

Aceste formate mai vorbărețe sunt utile pentru adăugarea altor metadate.

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:

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());
versiune: 4.0