Routing
Il Router si occupa di tutto ciò che riguarda gli indirizzi URL, così non dovrai più pensarci tu. Vedremo:
- come impostare il router affinché gli URL siano come desiderato
- parleremo di SEO e redirect
- e mostreremo come scrivere un router personalizzato
URL più umani (o anche cool o pretty URL) sono più usabili, memorizzabili e contribuiscono positivamente al SEO. Nette ci pensa e va incontro pienamente agli sviluppatori. Puoi progettare per la tua applicazione esattamente la struttura degli indirizzi URL che desideri. Puoi progettarla persino quando l'applicazione è già finita, perché si può fare senza interventi nel codice o nei template. Si definisce infatti in modo elegante in un unico posto, nel router, e non è quindi disseminata sotto forma di annotazioni in tutti i presenter.
Il router in Nette è eccezionale perché è bidirezionale. Sa sia decodificare gli URL nella richiesta HTTP, sia creare i link. Svolge quindi un ruolo fondamentale in Nette Application, perché decide quale presenter e azione eseguirà la richiesta corrente, ma viene anche utilizzato per la generazione di URL nel template, ecc.
Tuttavia, il router non è limitato solo a questo utilizzo, puoi usarlo in applicazioni dove i presenter non vengono affatto utilizzati, per API REST, ecc. Maggiori informazioni nella sezione Utilizzo indipendente.
Collezione di route
Il modo più piacevole per definire la forma degli indirizzi URL nell'applicazione è offerto dalla classe Nette\Application\Routers\RouteList. La definizione è costituita da un elenco delle cosiddette route, cioè maschere di indirizzi URL e presenter e azioni associati ad esse tramite una semplice API. Non è necessario dare un nome alle route.
$router = new Nette\Application\Routers\RouteList;
$router->addRoute('rss.xml', 'Feed:rss');
$router->addRoute('article/<id>', 'Article:view');
// ...
L'esempio dice che se apriamo https://domain.com/rss.xml
nel browser, verrà visualizzato il presenter
Feed
con l'azione rss
, se https://domain.com/article/12
, verrà visualizzato il presenter
Article
con l'azione view
, ecc. In caso di mancata corrispondenza di una route adatta, Nette Application
reagisce lanciando un'eccezione BadRequestException, che viene
mostrata all'utente come una pagina di errore 404 Not Found.
Ordine delle route
L'ordine in cui sono elencate le singole route è assolutamente cruciale, perché vengono valutate sequenzialmente dall'alto verso il basso. Vale la regola che dichiariamo le route dalle specifiche alle generali:
// SBAGLIATO: 'rss.xml' viene catturato dalla prima route e interpreta questa stringa come <slug>
$router->addRoute('<slug>', 'Article:view');
$router->addRoute('rss.xml', 'Feed:rss');
// GIUSTO
$router->addRoute('rss.xml', 'Feed:rss');
$router->addRoute('<slug>', 'Article:view');
Le route vengono valutate dall'alto verso il basso anche durante la generazione dei link:
// SBAGLIATO: il link a 'Feed:rss' genera come 'admin/feed/rss'
$router->addRoute('admin/<presenter>/<action>', 'Admin:default');
$router->addRoute('rss.xml', 'Feed:rss');
// GIUSTO
$router->addRoute('rss.xml', 'Feed:rss');
$router->addRoute('admin/<presenter>/<action>', 'Admin:default');
Non ti nasconderemo che la corretta composizione delle route richiede una certa abilità. Prima di padroneggiarla, ti sarà utile il pannello di routing.
Maschera e parametri
La maschera descrive il percorso relativo dalla directory principale del sito web. La maschera più semplice è un URL statico:
$router->addRoute('products', 'Products:default');
Spesso le maschere contengono i cosiddetti parametri. Questi sono indicati tra parentesi angolari (es.
<year>
) e vengono passati al presenter di destinazione, ad esempio al metodo renderShow(int $year)
o al parametro persistente $year
:
$router->addRoute('chronicle/<year>', 'History:show');
L'esempio dice che se apriamo https://example.com/chronicle/2020
nel browser, verrà visualizzato il presenter
History
con l'azione show
e il parametro year: 2020
.
Possiamo specificare un valore predefinito per i parametri direttamente nella maschera, rendendoli così opzionali:
$router->addRoute('chronicle/<year=2020>', 'History:show');
La route accetterà ora anche l'URL https://example.com/chronicle/
, che visualizzerà nuovamente
History:show
con il parametro year: 2020
.
Un parametro può ovviamente essere anche il nome del presenter e dell'azione. Ad esempio così:
$router->addRoute('<presenter>/<action>', 'Home:default');
La route specificata accetta ad es. URL nella forma /article/edit
o anche /catalog/list
e li
interpreta come presenter e azioni Article:edit
e Catalog:list
.
Allo stesso tempo, assegna ai parametri presenter
e action
i valori predefiniti Home
e
default
e sono quindi anche opzionali. Quindi la route accetta anche URL nella forma /article
e la
interpreta come Article:default
. O viceversa, un link a Product:default
genererà il percorso
/product
, un link al predefinito Home:default
il percorso /
.
La maschera può descrivere non solo il percorso relativo dalla directory principale del sito web, ma anche il percorso assoluto, se inizia con uno slash, o persino l'intero URL assoluto, se inizia con due slash:
// relativamente alla document root
$router->addRoute('<presenter>/<action>', /* ... */);
// percorso assoluto (relativo al dominio)
$router->addRoute('/<presenter>/<action>', /* ... */);
// URL assoluto incluso il dominio (relativo allo schema)
$router->addRoute('//<lang>.example.com/<presenter>/<action>', /* ... */);
// URL assoluto incluso lo schema
$router->addRoute('https://<lang>.example.com/<presenter>/<action>', /* ... */);
Espressioni di validazione
Per ogni parametro è possibile stabilire una condizione di validazione tramite un'espressione regolare. Ad esempio, per il parametro
id
specifichiamo che può assumere solo cifre tramite l'espressione regolare \d+
:
$router->addRoute('<presenter>/<action>[/<id \d+>]', /* ... */);
L'espressione regolare predefinita per tutti i parametri è [^/]+
, cioè tutto tranne lo slash. Se un parametro
deve accettare anche gli slash, specifichiamo l'espressione .+
:
// accetta https://example.com/a/b/c, path sarà 'a/b/c'
$router->addRoute('<path .+>', /* ... */);
Sequenze opzionali
Nella maschera è possibile contrassegnare parti opzionali tramite parentesi quadre. Qualsiasi parte della maschera può essere opzionale, possono esserci anche parametri al suo interno:
$router->addRoute('[<lang [a-z]{2}>/]<name>', /* ... */);
// Accetta percorsi:
// /cs/download => lang => cs, name => download
// /download => lang => null, name => download
Quando un parametro fa parte di una sequenza opzionale, diventa ovviamente anche opzionale. Se non ha un valore predefinito specificato, sarà null.
Le parti opzionali possono essere anche nel dominio:
$router->addRoute('//[<lang=en>.]example.com/<presenter>/<action>', /* ... */);
Le sequenze possono essere nidificate e combinate liberamente:
$router->addRoute(
'[<lang [a-z]{2}>[-<sublang>]/]<name>[/page-<page=0>]',
'Home:default',
);
// Accetta percorsi:
// /cs/hello
// /en-us/hello
// /hello
// /hello/page-12
Durante la generazione dell'URL, si cerca la variante più corta, quindi tutto ciò che può essere omesso viene omesso. Per
questo, ad esempio, la route index[.html]
genera il percorso /index
. È possibile invertire il
comportamento specificando un punto esclamativo dopo la parentesi quadra sinistra:
// accetta /hello e /hello.html, genera /hello
$router->addRoute('<name>[.html]', /* ... */);
// accetta /hello e /hello.html, genera /hello.html
$router->addRoute('<name>[!.html]', /* ... */);
I parametri opzionali (cioè i parametri con un valore predefinito) senza parentesi quadre si comportano essenzialmente come se fossero racchiusi tra parentesi nel modo seguente:
$router->addRoute('<presenter=Home>/<action=default>/<id=>', /* ... */);
// corrisponde a questo:
$router->addRoute('[<presenter=Home>/[<action=default>/[<id>]]]', /* ... */);
Se volessimo influenzare il comportamento dello slash finale, in modo che ad esempio invece di /home/
venga
generato solo /home
, si può ottenere così:
$router->addRoute('[<presenter=Home>[/<action=default>[/<id>]]]', /* ... */);
Caratteri jolly
Nella maschera del percorso assoluto possiamo utilizzare i seguenti caratteri jolly ed evitare così, ad esempio, la necessità di scrivere nella maschera il dominio, che può differire nell'ambiente di sviluppo e produzione:
%tld%
= top level domain, es.com
oorg
%sld%
= second level domain, es.example
%domain%
= dominio senza sottodomini, es.example.com
%host%
= intero host, es.www.example.com
%basePath%
= percorso alla directory principale
$router->addRoute('//www.%domain%/%basePath%/<presenter>/<action>', /* ... */);
$router->addRoute('//www.%sld%.%tld%/%basePath%/<presenter>/<action', /* ... */);
Notazione estesa
La destinazione della route, solitamente scritta nella forma Presenter:action
, può anche essere scritta
utilizzando un array che definisce i singoli parametri e i loro valori predefiniti:
$router->addRoute('<presenter>/<action>[/<id \d+>]', [
'presenter' => 'Home',
'action' => 'default',
]);
Per una specifica più dettagliata, è possibile utilizzare una forma ancora più estesa, dove oltre ai valori predefiniti
possiamo impostare altre proprietà dei parametri, come ad esempio l'espressione regolare di validazione (vedi parametro
id
):
use Nette\Routing\Route;
$router->addRoute('<presenter>/<action>[/<id>]', [
'presenter' => [
Route::Value => 'Home',
],
'action' => [
Route::Value => 'default',
],
'id' => [
Route::Pattern => '\d+',
],
]);
È importante notare che se i parametri definiti nell'array non sono specificati nella maschera del percorso, i loro valori non possono essere modificati, nemmeno tramite i parametri query specificati dopo il punto interrogativo nell'URL.
Filtri e traduzioni
Scriviamo il codice sorgente dell'applicazione in inglese, ma se il sito web deve avere URL in italiano, allora un semplice routing del tipo:
$router->addRoute('<presenter>/<action>', 'Home:default');
genererà URL in inglese, come /product/123
o /cart
. Se vogliamo che i presenter e le azioni
nell'URL siano rappresentati da parole italiane (es. /prodotto/123
o /carrello
), possiamo utilizzare un
dizionario di traduzione. Per la sua scrittura abbiamo già bisogno della variante “più verbosa” del secondo parametro:
use Nette\Routing\Route;
$router->addRoute('<presenter>/<action>', [
'presenter' => [
Route::Value => 'Home',
Route::FilterTable => [
// stringa nell'URL => presenter
'prodotto' => 'Product',
'carrello' => 'Cart',
'catalogo' => 'Catalog',
],
],
'action' => [
Route::Value => 'default',
Route::FilterTable => [
'elenco' => 'list',
],
],
]);
Più chiavi del dizionario di traduzione possono portare allo stesso presenter. In questo modo si creano diversi alias per esso. La variante canonica (cioè quella che sarà nell'URL generato) è considerata l'ultima chiave.
La tabella di traduzione può essere utilizzata in questo modo per qualsiasi parametro. Se la traduzione non esiste, viene
preso il valore originale. Possiamo cambiare questo comportamento aggiungendo Route::FilterStrict => true
e la
route rifiuterà quindi l'URL se il valore non è nel dizionario.
Oltre al dizionario di traduzione sotto forma di array, è possibile implementare anche funzioni di traduzione personalizzate.
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,
]);
La funzione Route::FilterIn
converte tra il parametro nell'URL e la stringa, che viene poi passata al presenter,
la funzione FilterOut
assicura la conversione nella direzione opposta.
I parametri presenter
, action
e module
hanno già filtri predefiniti che convertono tra
lo stile PascalCase o camelCase e kebab-case utilizzato nell'URL. Il valore predefinito dei parametri viene scritto già nella
forma trasformata, quindi ad esempio nel caso del presenter scriviamo <presenter=ProductEdit>
, non
<presenter=product-edit>
.
Filtri generali
Oltre ai filtri destinati a parametri specifici, possiamo definire anche filtri generali, che ricevono un array associativo di
tutti i parametri, che possono modificare in qualsiasi modo e poi restituirli. I filtri generali li definiamo sotto la chiave
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 { /* ... */ },
],
]);
I filtri generali danno la possibilità di modificare il comportamento della route in modo assolutamente qualsiasi. Possiamo
usarli ad esempio per modificare i parametri in base ad altri parametri. Ad esempio, la traduzione di
<presenter>
e <action>
in base al valore corrente del parametro
<lang>
.
Se un parametro ha definito un filtro personalizzato e contemporaneamente esiste un filtro generale, viene eseguito il
FilterIn
personalizzato prima di quello generale e viceversa il FilterOut
generale prima di quello
personalizzato. Quindi all'interno del filtro generale i valori dei parametri presenter
o action
sono
scritti nello stile PascalCase o camelCase.
Sensi unici OneWay
Le route a senso unico vengono utilizzate per mantenere la funzionalità dei vecchi URL, che l'applicazione non genera più, ma
accetta ancora. Le contrassegniamo con il flag OneWay
:
// vecchio URL /product-info?id=123
$router->addRoute('product-info', 'Product:detail', $router::ONE_WAY);
// nuovo URL /product/123
$router->addRoute('product/<id>', 'Product:detail');
Accedendo al vecchio URL, il presenter reindirizza automaticamente al nuovo URL, così i motori di ricerca non indicizzeranno due volte queste pagine (vedi SEO e canonizzazione).
Routing dinamico con callback
Il routing dinamico con callback ti consente di assegnare direttamente alle route funzioni (callback) che vengono eseguite quando viene visitato il percorso dato. Questa funzionalità flessibile ti consente di creare rapidamente ed efficacemente vari endpoint per la tua applicazione:
$router->addRoute('test', function () {
echo 'sei all\'indirizzo /test';
});
Puoi anche definire parametri nella maschera, che verranno automaticamente passati al tuo callback:
$router->addRoute('<lang cs|en>', function (string $lang) {
echo match ($lang) {
'cs' => 'Vítejte na české verzi našeho webu!', // Welcome to the Czech version of our website!
'en' => 'Welcome to the English version of our website!',
};
});
Moduli
Se abbiamo più route che rientrano in un modulo comune, utilizziamo
withModule()
:
$router = new RouteList;
$router->withModule('Forum') // le seguenti route fanno parte del modulo Forum
->addRoute('rss', 'Feed:rss') // il presenter sarà Forum:Feed
->addRoute('<presenter>/<action>')
->withModule('Admin') // le seguenti route fanno parte del modulo Forum:Admin
->addRoute('sign:in', 'Sign:in');
Un'alternativa è l'uso del parametro module
:
// L'URL manage/dashboard/default si mappa sul presenter Admin:Dashboard
$router->addRoute('manage/<presenter>/<action>', [
'module' => 'Admin',
]);
Sottodomini
Possiamo suddividere le collezioni di route per sottodomini:
$router = new RouteList;
$router->withDomain('example.com')
->addRoute('rss', 'Feed:rss')
->addRoute('<presenter>/<action>');
Nel nome del dominio è possibile utilizzare anche Caratteri jolly:
$router = new RouteList;
$router->withDomain('example.%tld%')
// ...
Prefisso del percorso
Possiamo suddividere le collezioni di route per percorso nell'URL:
$router = new RouteList;
$router->withPath('eshop')
->addRoute('rss', 'Feed:rss') // cattura l'URL /eshop/rss
->addRoute('<presenter>/<action>'); // cattura l'URL /eshop/<presenter>/<action>
Combinazioni
Le suddivisioni sopra menzionate possono essere combinate tra loro:
$router = (new RouteList)
->withDomain('admin.example.com')
->withModule('Admin')
->addRoute(/* ... */)
->addRoute(/* ... */)
->end()
->withModule('Images')
->addRoute(/* ... */)
->end()
->end()
->withDomain('example.com')
->withPath('export')
->addRoute(/* ... */)
// ...
Parametri query
Le maschere possono anche contenere parametri query (parametri dopo il punto interrogativo nell'URL). A questi non è possibile definire un'espressione di validazione, ma è possibile cambiare il nome con cui vengono passati al presenter:
// il parametro query 'cat' vogliamo usarlo nell'applicazione con il nome 'categoryId'
$router->addRoute('product ? id=<productId> & cat=<categoryId>', /* ... */);
Parametri Foo
Ora andiamo più a fondo. I parametri Foo sono essenzialmente parametri senza nome che consentono di abbinare un'espressione
regolare. Un esempio è una route che accetta /index
, /index.html
, /index.htm
e
/index.php
:
$router->addRoute('index<? \.html?|\.php|>', /* ... */);
È anche possibile definire esplicitamente la stringa che verrà utilizzata durante la generazione dell'URL. La stringa deve
essere posizionata direttamente dopo il punto interrogativo. La seguente route è simile alla precedente, ma genera
/index.html
invece di /index
, perché la stringa .html
è impostata come valore di
generazione:
$router->addRoute('index<?.html \.html?|\.php|>', /* ... */);
Integrazione nell'applicazione
Per integrare il router creato nell'applicazione, dobbiamo informarne il container DI. Il modo più semplice è preparare una
factory che produca l'oggetto router e comunicare nella configurazione del container che deve usarla. Supponiamo di scrivere a
tale scopo il metodo 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;
}
}
Nella configurazione scriveremo quindi:
services:
- App\Core\RouterFactory::createRouter
Qualsiasi dipendenza, ad esempio dal database ecc., viene passata al metodo factory come suoi parametri tramite autowiring:
public static function createRouter(Nette\Database\Connection $db): RouteList
{
// ...
}
SimpleRouter
Un router molto più semplice della collezione di route è SimpleRouter. Lo useremo quando
non abbiamo particolari esigenze sulla forma dell'URL, se non è disponibile mod_rewrite
(o le sue alternative)
o se per ora non vogliamo occuparci di URL leggibili.
Genera indirizzi approssimativamente in questa forma:
http://example.com/?presenter=Product&action=detail&id=123
Il parametro del costruttore di SimpleRouter è il presenter & azione predefinito, a cui si deve puntare se apriamo la
pagina senza parametri, ad es. http://example.com/
.
// il presenter predefinito sarà 'Home' e l'azione 'default'
$router = new Nette\Application\Routers\SimpleRouter('Home:default');
Consigliamo di definire SimpleRouter direttamente nella configurazione:
services:
- Nette\Application\Routers\SimpleRouter('Home:default')
SEO e canonizzazione
Il framework contribuisce al SEO (ottimizzazione della reperibilità su Internet) impedendo la duplicazione di contenuti su URL
diversi. Se a una determinata destinazione portano più indirizzi, ad es. /index
e /index.html
, il
framework determina il primo come primario (canonico) e reindirizza gli altri ad esso tramite il codice HTTP 301. Grazie a ciò,
i motori di ricerca non indicizzano le pagine due volte e non diluiscono il loro page rank.
Questo processo si chiama canonizzazione. L'URL canonico è quello generato dal router, cioè la prima route corrispondente nella collezione senza il flag OneWay. Pertanto, nella collezione elenchiamo le route primarie per prime.
La canonizzazione viene eseguita dal presenter, maggiori informazioni nel capitolo canonizzazione.
HTTPS
Per poter utilizzare il protocollo HTTPS, è necessario abilitarlo sull'hosting e configurare correttamente il server.
Il redirect dell'intero sito a HTTPS deve essere impostato a livello di server, ad esempio tramite il file .htaccess nella directory principale della nostra applicazione, e con il codice HTTP 301. L'impostazione può variare a seconda dell'hosting e assomiglia circa a questo:
<IfModule mod_rewrite.c>
RewriteEngine On
...
RewriteCond %{HTTPS} off
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
...
</IfModule>
Il router genera URL con lo stesso protocollo con cui è stata caricata la pagina, quindi non è necessario impostare nient'altro.
Se però eccezionalmente abbiamo bisogno che diverse route vengano eseguite sotto protocolli diversi, lo specifichiamo nella maschera della route:
// Genererà un indirizzo con HTTP
$router->addRoute('http://%host%/<presenter>/<action>', /* ... */);
// Genererà un indirizzo con HTTPs
$router->addRoute('https://%host%/<presenter>/<action>', /* ... */);
Debug del router
Il pannello di routing visualizzato nella Tracy Bar è un aiuto utile che mostra l'elenco delle route e anche i parametri che il router ha ottenuto dall'URL.
La barra verde con il simbolo ✓ rappresenta la route che ha elaborato l'URL corrente, con il colore blu e il simbolo ≈ sono contrassegnate le route che avrebbero elaborato anche l'URL se la verde non le avesse precedute. Vediamo inoltre il presenter & azione corrente.

Allo stesso tempo, se si verifica un redirect inaspettato a causa della canonizzazione, è utile guardare il pannello nella barra redirect, dove scoprirete come il router ha originariamente compreso l'URL e perché ha reindirizzato.
Durante il debug del router, consigliamo di aprire gli Strumenti per sviluppatori nel browser (Ctrl+Shift+I o Cmd+Option+I) e nel pannello Network disattivare la cache, in modo che non vi vengano salvati i redirect.
Prestazioni
Il numero di route influisce sulla velocità del router. Il loro numero non dovrebbe assolutamente superare alcune decine. Se il tuo sito web ha una struttura URL troppo complicata, puoi scrivere un Router personalizzato su misura.
Se il router non ha dipendenze, ad esempio dal database, e la sua factory non accetta argomenti, possiamo serializzare la sua forma compilata direttamente nel container DI e accelerare così leggermente l'applicazione.
routing:
cache: true
Router personalizzato
Le righe seguenti sono destinate a utenti molto avanzati. Puoi creare un tuo router personalizzato e integrarlo in modo del tutto naturale nella collezione di route. Il router è un'implementazione dell'interfaccia Nette\Routing\Router con due metodi:
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
{
// ...
}
}
Il metodo match
elabora la richiesta corrente $httpRequest,
dalla quale è possibile ottenere non solo l'URL, ma anche gli header, ecc., in un array contenente il nome del presenter e
i suoi parametri. Se non sa elaborare la richiesta, restituisce null. Durante l'elaborazione della richiesta, dobbiamo restituire
almeno il presenter e l'azione. Il nome del presenter è completo e contiene anche eventuali moduli:
[
'presenter' => 'Front:Home',
'action' => 'default',
]
Il metodo constructUrl
al contrario costruisce dall'array di parametri l'URL assoluto risultante. A tal fine può
utilizzare le informazioni dal parametro $refUrl
, che è l'URL corrente.
Lo aggiungi alla collezione di route usando add()
:
$router = new Nette\Application\Routers\RouteList;
$router->add($myRouter);
$router->addRoute(/* ... */);
// ...
Utilizzo indipendente
Per utilizzo indipendente intendiamo l'utilizzo delle capacità del router in un'applicazione che non utilizza Nette Application e i presenter. Vale per esso quasi tutto ciò che abbiamo mostrato in questo capitolo, con queste differenze:
- per le collezioni di route utilizziamo la classe Nette\Routing\RouteList
- come simple router la classe Nette\Routing\SimpleRouter
- poiché non esiste la coppia
Presenter:action
, utilizziamo la Notazione estesa
Quindi di nuovo creiamo un metodo che ci costruisca il router, ad es.:
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;
}
}
Se usi un container DI, cosa che consigliamo, aggiungiamo di nuovo il metodo alla configurazione e poi otteniamo il router insieme alla richiesta HTTP dal container:
$router = $container->getByType(Nette\Routing\Router::class);
$httpRequest = $container->getByType(Nette\Http\IRequest::class);
Oppure creiamo direttamente gli oggetti:
$router = App\Core\RouterFactory::createRouter();
$httpRequest = (new Nette\Http\RequestFactory)->fromGlobals();
Ora resta solo da mettere al lavoro il router:
$params = $router->match($httpRequest);
if ($params === null) {
// non è stata trovata una route corrispondente, inviamo errore 404
exit;
}
// elaboriamo i parametri ottenuti
$controller = $params['controller'];
// ...
E viceversa usiamo il router per costruire un link:
$params = ['controller' => 'ArticleController', 'id' => 123];
$url = $router->constructUrl($params, $httpRequest->getUrl());