Instradamento
Il router si occupa di tutto ciò che riguarda gli URL, in modo da non doverci più pensare. Mostreremo:
- come impostare il router in modo che gli URL abbiano l'aspetto desiderato
- alcune note sul reindirizzamento SEO
- e vi mostreremo come scrivere il vostro router personale
Gli URL più umani (o gli URL belli o cool) sono più utilizzabili, più memorabili e contribuiscono positivamente alla SEO. Nette ha in mente questo aspetto e soddisfa pienamente i desideri degli sviluppatori. Potete progettare la struttura degli URL per la vostra applicazione esattamente come volete. È possibile progettarla anche dopo che l'applicazione è pronta, senza dover modificare il codice o il modello. È definita in modo elegante in un unico punto, nel router, e non è sparsa sotto forma di annotazioni in tutti i presentatori.
Il router di Nette è speciale perché è bidirezionale, può sia decodificare gli URL delle richieste HTTP sia creare collegamenti. Svolge quindi un ruolo fondamentale nell'applicazione Nette, in quanto decide quale presentatore e quale azione eseguirà la richiesta corrente ed è anche utilizzato per la generazione di URL nel modello, ecc.
Tuttavia, il router non si limita a questo uso: è possibile utilizzarlo in applicazioni in cui i presentatori non vengono utilizzati affatto, per le API REST, ecc. Maggiori informazioni nella sezione Uso separato.
Raccolta di rotte
Il modo più piacevole per definire gli indirizzi URL nell'applicazione è attraverso la classe Nette\Application\Routers\RouteList. La definizione consiste in un elenco di cosiddette rotte, ossia maschere di indirizzi URL e di presentatori e azioni ad essi associati, utilizzando una semplice API. Non è necessario dare un nome alle rotte.
$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://any-domain.com/rss.xml
con l'azione rss
, se
https://domain.com/article/12
con l'azione view
, ecc. Se non viene trovato un percorso adatto, Nette
Application risponde lanciando un'eccezione BadRequestException, che appare
all'utente come una pagina di errore 404 Not Found.
Ordine dei percorsi
L'ordine in cui sono elencate le rotte è molto importante perché vengono valutate in sequenza dall'alto verso il basso. La regola è quella di dichiarare le rotte dalla specifica alla generale:
// SBAGLIATO: 'rss.xml' corrisponde alla prima rotta e la interpreta come <slug>.
$router->addRoute('<slug>', 'Article:view');
$router->addRoute('rss.xml', 'Feed:rss');
// BUONO
$router->addRoute('rss.xml', 'Feed:rss');
$router->addRoute('<slug>', 'Article:view');
Le rotte vengono valutate dall'alto verso il basso anche quando vengono generati i collegamenti:
// SBAGLIATO: genera un link a 'Feed:rss' come 'admin/feed/rss'.
$router->addRoute('admin/<presenter>/<action>', 'Admin:default');
$router->addRoute('rss.xml', 'Feed:rss');
// BUONO
$router->addRoute('rss.xml', 'Feed:rss');
$router->addRoute('admin/<presenter>/<action>', 'Admin:default');
Non vi nasconderemo che ci vuole una certa abilità per costruire correttamente un elenco. Finché non ci si riesce, il pannello di instradamento sarà uno strumento utile.
Maschera e parametri
La maschera descrive il percorso relativo basato sulla radice del sito. La maschera più semplice è un URL statico:
$router->addRoute('products', 'Products:default');
Spesso le maschere contengono i cosiddetti parametri. Essi sono racchiusi tra parentesi angolari (ad es.
<year>
) e vengono passati al presentatore 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://any-domain.com/chronicle/2020
e l'azione show
con il parametro
year: 2020
.
Possiamo specificare un valore predefinito per i parametri direttamente nella maschera, che diventa così facoltativa:
$router->addRoute('chronicle/<year=2020>', 'History:show');
La rotta accetterà ora l'URL https://any-domain.com/chronicle/
con il parametro year: 2020
.
Naturalmente, anche il nome del presentatore e l'azione possono essere un parametro. Ad esempio:
$router->addRoute('<presenter>/<action>', 'Home:default');
Questo percorso accetta, ad esempio, un URL nella forma /article/edit
e /catalog/list
e li traduce in
presentatori e azioni Article:edit
e Catalog:list
.
Inoltre, assegna ai parametri presenter
e action
i valori predefinitiHome
e
default
, che sono quindi facoltativi. Quindi il percorso accetta anche un URL /article
e lo traduce in
Article:default
. O viceversa, un link a Product:default
genera un percorso /product
, un
link al default Home:default
genera un percorso /
.
La maschera può descrivere non solo il percorso relativo basato sulla radice del sito, ma anche il percorso assoluto quando inizia con una barra, o addirittura l'intero URL assoluto quando inizia con due barre:
// percorso relativo alla radice del documento dell'applicazione
$router->addRoute('<presenter>/<action>', /* ... */);
// percorso assoluto, relativo al nome host del server
$router->addRoute('/<presenter>/<action>', /* ... */);
// URL assoluto che include il nome dell'host (ma relativo allo schema)
$router->addRoute('//<lang>.example.com/<presenter>/<action>', /* ... */);
// URL assoluto comprensivo di schema
$router->addRoute('https://<lang>.example.com/<presenter>/<action>', /* ... */);
Espressioni di validazione
È possibile specificare una condizione di validazione per ogni parametro utilizzando un 'espressione regolare. Per esempio, impostiamo
id
in modo che sia solo numerico, usando la regexp \d+
:
$router->addRoute('<presenter>/<action>[/<id \d+>]', /* ... */);
L'espressione regolare predefinita per tutti i parametri è [^/]+
, cioè tutto tranne lo slash. Se un parametro
deve corrispondere anche a una barra, si imposta l'espressione regolare a .+
.
// accetta https://example.com/a/b/c, il percorso è 'a/b/c'
$router->addRoute('<path .+>', /* ... */);
Sequenze opzionali
Le parentesi quadre indicano le parti opzionali della maschera. Qualsiasi parte della maschera può essere impostata come opzionale, comprese quelle contenenti parametri:
$router->addRoute('[<lang [a-z]{2}>/]<name>', /* ... */);
// URL accettati: Parametri:
// /en/download lang => en, name => download
// /download lang => null, name => download
Naturalmente, quando un parametro fa parte di una sequenza opzionale, diventa anch'esso opzionale. Se non ha un valore predefinito, sarà nullo.
Le sezioni opzionali possono anche essere nel dominio:
$router->addRoute('//[<lang=en>.]example.com/<presenter>/<action>', /* ... */);
Le sequenze possono essere liberamente annidate e combinate:
$router->addRoute(
'[<lang [a-z]{2}>[-<sublang>]/]<name>[/page-<page=0>]',
'Home:default',
);
// URL accettati:
// /en/hello
// /en-us/hello
// /hello
// /hello/page-12
Il generatore di URL cerca di mantenere l'URL il più breve possibile, quindi ciò che può essere omesso viene omesso.
Pertanto, ad esempio, un percorso index[.html]
genera un percorso /index
. È possibile invertire questo
comportamento scrivendo un punto esclamativo dopo la parentesi quadra sinistra:
// accetta sia /hello che /hello.html, genera /hello
$router->addRoute('<name>[.html]', /* ... */);
// accetta sia /hello che /hello.html, genera /hello.html
$router->addRoute('<name>[!.html]', /* ... */);
I parametri opzionali (cioè quelli che hanno un valore predefinito) senza parentesi quadre si comportano come se fossero avvolti in questo modo:
$router->addRoute('<presenter=Home>/<action=default>/<id=>', /* ... */);
// equivale a:
$router->addRoute('[<presenter=Home>/[<action=default>/[<id>]]]', /* ... */);
Per cambiare il modo in cui viene generato lo slash più a destra, cioè invece di /home/
ottenere un
/home
, regolare il percorso in questo modo:
$router->addRoute('[<presenter=Home>[/<action=default>[/<id>]]]', /* ... */);
Caratteri jolly
Nella maschera del percorso assoluto, si possono usare i seguenti caratteri jolly per evitare, ad esempio, la necessità di scrivere un dominio nella maschera, che può essere diverso nell'ambiente di sviluppo e in quello di produzione:
%tld%
= dominio di primo livello, ad esempiocom
oorg
%sld%
= dominio di secondo livello, ad es.example
%domain%
= dominio senza sottodomini, ad es.example.com
%host%
= intero host, ad es.www.example.com
%basePath%
= percorso della directory principale
$router->addRoute('//www.%domain%/%basePath%/<presenter>/<action>', /* ... */);
$router->addRoute('//www.%sld%.%tld%/%basePath%/<presenter>/<action', /* ... */);
Notazione avanzata
L'obiettivo di una rotta, solitamente scritto nella forma Presenter:action
, può anche essere espresso 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, si può usare una forma ancora più estesa, in cui oltre ai valori predefiniti si possono
impostare altre proprietà dei parametri, come un'espressione regolare di validazione (vedere il 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 inclusi nella maschera del percorso, i loro valori non possono essere modificati, nemmeno utilizzando i parametri di query specificati dopo un punto interrogativo nell'URL.
Filtri e traduzioni
È buona norma scrivere il codice sorgente in inglese, ma cosa succede se è necessario che il sito web abbia un URL tradotto in una lingua diversa? Percorsi semplici come:
$router->addRoute('<presenter>/<action>', 'Home:default');
genereranno URL in inglese, come /product/123
o /cart
. Se vogliamo che i presenter e le azioni
nell'URL siano tradotti in tedesco (per esempio /produkt/123
o /einkaufswagen
), possiamo usare un
dizionario di traduzione. Per aggiungerlo, abbiamo già bisogno di una variante “più loquace” del secondo parametro:
use Nette\Routing\Route;
$router->addRoute('<presenter>/<action>', [
'presenter' => [
Route::Value => 'Home',
Route::FilterTable => [
// stringa nell'URL => presenter
'produkt' => 'Product',
'einkaufswagen' => 'Cart',
'katalog' => 'Catalog',
],
],
'action' => [
Route::Value => 'default',
Route::FilterTable => [
'liste' => 'list',
],
],
]);
È possibile utilizzare più chiavi di dizionario per lo stesso presentatore. Esse creeranno diversi alias per esso. L'ultima chiave è considerata la variante canonica (cioè quella che sarà presente nell'URL generato).
In questo modo, la tabella di traduzione può essere applicata a qualsiasi parametro. Tuttavia, se la traduzione non esiste,
viene preso il valore originale. Possiamo modificare questo comportamento aggiungendo Route::FilterStrict => true
e la rotta rifiuterà l'URL se il valore non è presente nel dizionario.
Oltre al dizionario delle traduzioni sotto forma di array, è possibile impostare funzioni di traduzione proprie:
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 il parametro dell'URL in stringa, che viene poi passata al presentatore,
mentre la funzione FilterOut
assicura la conversione in senso inverso.
I parametri presenter
, action
e module
hanno già dei filtri predefiniti che convertono
tra lo stile PascalCase o camelCase e kebab-case utilizzato nell'URL. Il valore predefinito dei parametri è già scritto nella
forma trasformata, quindi, ad esempio, nel caso di un presentatore, si scrive <presenter=ProductEdit>
invece di
<presenter=product-edit>
.
Filtri generali
Oltre ai filtri per parametri specifici, è possibile definire anche filtri generali che ricevono un array associativo di tutti
i parametri che possono modificare in qualsiasi modo e poi restituire. I filtri generali sono definiti sotto il tasto
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 regolare il comportamento del percorso in qualsiasi modo. Si possono usare, ad
esempio, per modificare i parametri in base ad altri parametri. Ad esempio, la traduzione <presenter>
e
<action>
in base al valore corrente del parametro <lang>
.
Se per un parametro è stato definito un filtro personalizzato e contemporaneamente esiste un filtro generale, il filtro
personalizzato FilterIn
viene eseguito prima del generale e viceversa il generale FilterOut
viene
eseguito prima del personalizzato. Quindi, all'interno del filtro generale si trovano i valori dei parametri
presenter
risp. action
scritti in stile PascalCase risp. camelCase.
Bandiera unidirezionale
Le rotte a senso unico sono utilizzate per preservare la funzionalità di vecchi URL che l'applicazione non genera più, ma che
accetta ancora. Le segnaliamo con 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');
Quando si accede al vecchio URL, il presentatore reindirizza automaticamente al nuovo URL, in modo che i motori di ricerca non indicizzino queste pagine due volte (vedere SEO e canonizzazione).
Instradamento dinamico con callback
L'instradamento dinamico con callback consente di assegnare direttamente delle funzioni (callback) alle rotte, che verranno eseguite quando viene visitato il percorso specificato. Questa funzione flessibile consente di creare in modo rapido ed efficiente vari endpoint per l'applicazione:
$router->addRoute('test', function () {
echo 'You are at the /test address';
});
È anche possibile definire parametri nella maschera, che verranno passati automaticamente alla callback:
$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!',
};
});
Moduli
Se abbiamo più rotte che appartengono a un modulo, possiamo usare
withModule()
per raggrupparle:
$router = new RouteList;
$router->withModule('Forum') // i seguenti router fanno parte del modulo Forum
->addRoute('rss', 'Feed:rss') // il presentatore è Forum:Feed
->addRoute('<presenter>/<action>')
->withModule('Admin') // i seguenti router fanno parte del modulo Forum:Admin
->addRoute('sign:in', 'Sign:in');
Un'alternativa è usare il parametro module
:
// L'URL manage/dashboard/default si riferisce al presentatore Admin:Dashboard
$router->addRoute('manage/<presenter>/<action>', [
'module' => 'Admin',
]);
Sottodomini
Le raccolte di rotte possono essere raggruppate per sottodomini:
$router = new RouteList;
$router->withDomain('example.com')
->addRoute('rss', 'Feed:rss')
->addRoute('<presenter>/<action>');
È inoltre possibile utilizzare i caratteri jolly nel nome del dominio:
$router = new RouteList;
$router->withDomain('example.%tld%')
// ...
Prefisso di percorso
Le raccolte di rotte possono essere raggruppate per percorso nell'URL:
$router = new RouteList;
$router->withPath('eshop')
->addRoute('rss', 'Feed:rss') // corrisponde all'URL /eshop/rss
->addRoute('<presenter>/<action>'); // corrisponde all'URL /eshop/<presenter>/<action>
Combinazioni
L'uso sopra descritto può essere combinato:
$router = (new RouteList)
->withDomain('admin.example.com')
->withModule('Admin')
->addRoute(/* ... */)
->addRoute(/* ... */)
->end()
->withModule('Images')
->addRoute(/* ... */)
->end()
->end()
->withDomain('example.com')
->withPath('export')
->addRoute(/* ... */)
// ...
Parametri della query
Le maschere possono contenere anche parametri di query (parametri dopo il punto interrogativo nell'URL). Non possono definire un'espressione di validazione, ma possono cambiare il nome con cui vengono passati al presentatore:
// utilizzare il parametro di query 'cat' come 'categoryId' nell'applicazione
$router->addRoute('product ? id=<productId> & cat=<categoryId>', /* ... */);
Parametri Foo
Ora stiamo andando più a fondo. I parametri Foo sono fondamentalmente parametri senza nome che permettono di corrispondere a
un'espressione regolare. Il percorso seguente corrisponde a /index
, /index.html
, /index.htm
e /index.php
:
$router->addRoute('index<? \.html?|\.php|>', /* ... */);
È anche possibile definire esplicitamente una stringa che sarà usata per la generazione dell'URL. La stringa deve essere
posta direttamente dopo il punto interrogativo. Il percorso seguente è simile al precedente, ma genera /index.html
invece di /index
, perché la stringa .html
è impostata come “valore generato”.
$router->addRoute('index<?.html \.html?|\.php|>', /* ... */);
Integrazione
Per collegare il nostro router all'applicazione, dobbiamo comunicarlo al contenitore DI. Il modo più semplice è preparare il
factory che costruirà l'oggetto router e dire al contenitore di configurazione di usarlo. Diciamo quindi di scrivere un metodo a
questo scopo 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;
}
}
Poi scriviamo nella configurazione:
services:
- App\Core\RouterFactory::createRouter
Tutte le dipendenze, come la connessione al database, ecc. vengono passate al metodo factory come parametri, utilizzando l'autowiring:
public static function createRouter(Nette\Database\Connection $db): RouteList
{
// ...
}
Router semplice
Un router molto più semplice della Route Collection è SimpleRouter. Può essere usato
quando non c'è bisogno di un formato URL specifico, quando mod_rewrite
(o alternative) non è disponibile o quando
semplicemente non si vuole ancora preoccuparsi di URL facili da usare.
Genera indirizzi più o meno in questa forma:
http://example.com/?presenter=Product&action=detail&id=123
Il parametro del costruttore SimpleRouter
è un presentatore e un'azione predefiniti, cioè l'azione da eseguire
se si apre, ad esempio, http://example.com/
senza ulteriori parametri.
// default al presenter 'Home' e all'azione 'default'
$router = new Nette\Application\Routers\SimpleRouter('Home:default');
Si consiglia di definire SimpleRouter direttamente nella configurazione:
services:
- Nette\Application\Routers\SimpleRouter('Home:default')
SEO e canonizzazione
Il framework aumenta la SEO (ottimizzazione per i motori di ricerca) impedendo la duplicazione di contenuti in URL diversi. Se
più indirizzi rimandano a una stessa destinazione, ad esempio /index
e /index.html
, il framework
determina il primo come primario (canonico) e reindirizza gli altri ad esso utilizzando il codice HTTP 301. In questo modo,
i motori di ricerca non indicizzeranno le pagine due volte e non ne comprometteranno il page rank. .
Questo processo è chiamato canonizzazione. L'URL canonico è quello generato dal router, cioè dal primo percorso corrispondente nella raccolta senza il flag OneWay. Pertanto, nella raccolta, vengono elencati per primi i percorsi primari.
La canonizzazione viene eseguita dal presentatore, come descritto nel capitolo Canonizzazione.
HTTPS
Per utilizzare il protocollo HTTPS, è necessario attivarlo sull'hosting e configurare il server.
Il reindirizzamento dell'intero sito verso HTTPS deve essere eseguito a livello di server, ad esempio utilizzando il file .htaccess nella directory principale della nostra applicazione, con il codice HTTP 301. Le impostazioni possono variare a seconda dell'hosting e hanno un aspetto simile a questo:
<IfModule mod_rewrite.c>
RewriteEngine On
...
RewriteCond %{HTTPS} off
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
...
</IfModule>
Il router genera un URL con lo stesso protocollo con cui è stata caricata la pagina, quindi non è necessario impostare altro.
Tuttavia, se abbiamo eccezionalmente bisogno di rotte diverse da eseguire con protocolli diversi, lo inseriremo nella maschera di rotta:
// Genererà un indirizzo HTTP
$router->addRoute('http://%host%/<presenter>/<action>', /* ... */);
// Genererà un indirizzo HTTPS
$router->addRoute('https://%host%/<presenter>/<action>', /* ... */);
Debug del router
La barra di routing visualizzata in Tracy Bar è un utile strumento che mostra un elenco di percorsi e anche i parametri che il router ha ottenuto dall'URL.
La barra verde con il simbolo ✓ rappresenta il percorso che corrisponde all'URL corrente, le barre blu con i simboli ≈ indicano i percorsi che corrisponderebbero all'URL se il verde non li superasse. Vediamo ulteriormente il presentatore e l'azione corrente.
Allo stesso tempo, se c'è un reindirizzamento inaspettato dovuto alla canonicalizzazione, è utile guardare nella barra redirect per vedere come il router ha originariamente compreso l'URL e perché ha reindirizzato.
Quando si esegue il debug del router, si consiglia di aprire gli Strumenti per sviluppatori nel browser (Ctrl+Maiusc+I o Cmd+Opzione+I) e di disabilitare la cache nel pannello Rete, in modo che i reindirizzamenti non vengano memorizzati.
Prestazioni
Il numero di rotte influisce sulla velocità del router. Il loro numero non dovrebbe superare le poche decine. Se il sito ha una struttura di URL troppo complicata, si può scrivere un router personalizzato.
Se il router non ha dipendenze, ad esempio da un database, e il suo factory non ha argomenti, possiamo serializzare la sua forma compilata direttamente in un contenitore DI e quindi rendere l'applicazione leggermente più veloce.
routing:
cache: true
Router personalizzato
Le righe seguenti sono destinate a utenti molto avanzati. È possibile creare il proprio router e aggiungerlo naturalmente alla propria collezione di rotte. 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 $httpRequest corrente, da cui è
possibile recuperare non solo l'URL, ma anche le intestazioni ecc. in un array contenente il nome del presentatore e i suoi
parametri. Se non può elaborare la richiesta, restituisce null. Quando si elabora la richiesta, è necessario restituire almeno
il presentatore e l'azione. Il nome del presentatore è completo e include eventuali moduli:
[
'presenter' => 'Front:Home',
'action' => 'default',
]
Il metodo constructUrl
, invece, genera un URL assoluto dall'array di parametri. Può utilizzare le informazioni
del parametro $refUrl
, che è l'URL corrente.
Per aggiungere un router personalizzato alla collezione di rotte, utilizzare add()
:
$router = new Nette\Application\Routers\RouteList;
$router->add($myRouter);
$router->addRoute(/* ... */);
// ...
Uso separato
Per uso separato si intende l'uso delle funzionalità del router in un'applicazione che non utilizza l'applicazione Nette e i presentatori. Quasi tutto ciò che è stato mostrato in questo capitolo è applicabile, con le seguenti differenze:
- per le raccolte di rotte usiamo la classe Nette\Routing\RouteList
- come semplice classe router Nette\Routing\SimpleRouter
- poiché non c'è la coppia
Presenter:action
, usiamo la notazione avanzata
Quindi creeremo di nuovo un metodo che costruirà un router, ad esempio:
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 si usa un contenitore DI, cosa che consigliamo, si aggiunge nuovamente il metodo alla configurazione e si ottiene il router insieme alla richiesta HTTP dal contenitore:
$router = $container->getByType(Nette\Routing\Router::class);
$httpRequest = $container->getByType(Nette\Http\IRequest::class);
Oppure creeremo direttamente gli oggetti:
$router = App\Core\RouterFactory::createRouter();
$httpRequest = (new Nette\Http\RequestFactory)->fromGlobals();
Ora dobbiamo far funzionare il router:
$params = $router->match($httpRequest);
if ($params === null) {
// non è stata trovata alcuna rotta corrispondente, verrà inviato un errore 404
exit;
}
// elaboriamo i parametri ricevuti
$controller = $params['controller'];
// ...
E viceversa, useremo il router per creare il collegamento:
$params = ['controller' => 'ArticleController', 'id' => 123];
$url = $router->constructUrl($params, $httpRequest->getUrl());