Usmerjanje

Usmerjevalnik (Router) skrbi za vse v zvezi z URL naslovi, da vam nad njimi ne bi bilo treba več razmišljati. Pokazali si bomo:

  • kako nastaviti usmerjevalnik, da bodo URL-ji po želji
  • povedali si bomo o SEO in preusmeritvah
  • in pokazali si bomo, kako napisati lasten usmerjevalnik

Bolj človeški URL-ji (ali tudi kul ali lepi URL-ji) so bolj uporabni, lažje zapomnljivi in pozitivno prispevajo k SEO. Nette na to misli in razvijalcem popolnoma ustreza. Za svojo aplikacijo si lahko zasnujete točno takšno strukturo URL naslovov, kakršno boste želeli. Lahko jo zasnujete celo šele takrat, ko je aplikacija že končana, saj se to izvede brez posegov v kodo ali predloge. Definira se namreč na eleganten način na enem samem mestu, v usmerjevalniku, in ni tako razpršena v obliki anotacij v vseh presenterjih.

Usmerjevalnik v Nette je izjemen s tem, da je dvosmeren. Zna tako dekodirati URL v HTTP zahtevku kot tudi ustvarjati povezave. Igra torej ključno vlogo v Nette Application, saj delsno odloča o tem, kateri presenter in akcija bosta izvajala trenutni zahtevek, delsno pa se uporablja za generiranje URL-jev v predlogi itd.

Vendar usmerjevalnik ni omejen samo na to uporabo, lahko ga uporabite v aplikacijah, kjer se presenterji sploh ne uporabljajo, za REST API itd. Več v delu Samostojna uporaba.

Zbirka poti

Najprijetnejši način, kako definirati obliko URL naslovov v aplikaciji, ponuja razred Nette\Application\Routers\RouteList. Definicija je sestavljena iz seznama t.i. poti (routes), torej mask URL naslovov in k njim pridruženih presenterjev in akcij s pomočjo preprostega API-ja. Poti ni treba poimenovati.

$router = new Nette\Application\Routers\RouteList;
$router->addRoute('rss.xml', 'Feed:rss');
$router->addRoute('article/<id>', 'Article:view');
// ...

Primer pravi, da če v brskalniku odpremo https://domain.com/rss.xml, se prikaže presenter Feed z akcijo rss, če https://domain.com/article/12, se prikaže presenter Article z akcijo view itd. V primeru nenajdene primerne poti Nette Application reagira s sprožitvijo izjeme BadRequestException, ki se uporabniku prikaže kot stran z napako 404 Not Found.

Vrstni red poti

Popolnoma ključni je vrstni red, v katerem so posamezne poti navedene, ker se vrednotijo postopoma od zgoraj navzdol. Velja pravilo, da poti deklariramo od specifičnih k splošnim:

// SLABO: 'rss.xml' ujame prva pot in ta niz razume kot <slug>
$router->addRoute('<slug>', 'Article:view');
$router->addRoute('rss.xml', 'Feed:rss');

// DOBRO
$router->addRoute('rss.xml', 'Feed:rss');
$router->addRoute('<slug>', 'Article:view');

Poti se vrednotijo od zgoraj navzdol tudi pri generiranju povezav:

// SLABO: povezava na 'Feed:rss' generira kot 'admin/feed/rss'
$router->addRoute('admin/<presenter>/<action>', 'Admin:default');
$router->addRoute('rss.xml', 'Feed:rss');

// DOBRO
$router->addRoute('rss.xml', 'Feed:rss');
$router->addRoute('admin/<presenter>/<action>', 'Admin:default');

Ne bomo vam skrivali, da pravilno sestavljanje poti zahteva določeno spretnost. Preden se vanjo poglobite, vam bo koristen pomočnik usmerjevalna plošča.

Maska in parametri

Maska opisuje relativno pot od korenskega direktorija spletnega mesta. Najenostavnejša maska je statični URL:

$router->addRoute('products', 'Products:default');

Pogosto maske vsebujejo t.i. parametre. Ti so navedeni v ostrih oklepajih (npr. <year>) in so posredovani v ciljni presenter, na primer metodi renderShow(int $year) ali v persistentni parameter $year:

$router->addRoute('chronicle/<year>', 'History:show');

Primer pravi, da če v brskalniku odpremo https://example.com/chronicle/2020, se prikaže presenter History z akcijo show in parametrom year: 2020.

Parametrom lahko določimo privzeto vrednost neposredno v maski in s tem postanejo izbirni:

$router->addRoute('chronicle/<year=2020>', 'History:show');

Pot bo zdaj sprejela tudi URL https://example.com/chronicle/, ki spet prikaže History:show s parametrom year: 2020.

Parameter je lahko seveda tudi ime presenterja in akcije. Na primer tako:

$router->addRoute('<presenter>/<action>', 'Home:default');

Navedena pot sprejema npr. URL v obliki /article/edit ali tudi /catalog/list in jih razume kot presenterje in akcije Article:edit in Catalog:list.

Hkrati daje parametroma presenter in action privzeti vrednosti Home in default in sta torej tudi izbirna. Tako pot sprejema tudi URL v obliki /article in ga razume kot Article:default. Ali obratno, povezava na Product:default generira pot /product, povezava na privzeti Home:default pot /.

Maska lahko opisuje ne samo relativno pot od korenskega direktorija spletnega mesta, ampak tudi absolutno pot, če se začne s poševnico, ali celo celoten absolutni URL, če se začne z dvema poševnicama:

// relativno glede na document root
$router->addRoute('<presenter>/<action>', /* ... */);

// absolutna pot (relativna glede na domeno)
$router->addRoute('/<presenter>/<action>', /* ... */);

// absolutni URL vključno z domeno (relativen glede na shemo)
$router->addRoute('//<lang>.example.com/<presenter>/<action>', /* ... */);

// absolutni URL vključno s shemo
$router->addRoute('https://<lang>.example.com/<presenter>/<action>', /* ... */);

Validacijski izrazi

Za vsak parameter lahko določimo validacijski pogoj s pomočjo regularnega izraza. Na primer, parametru id določimo, da lahko vsebuje samo števke s pomočjo regularnega izraza \d+:

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

Privzeti regularni izraz za vse parametre je [^/]+, tj. vse razen poševnice. Če mora parameter sprejemati tudi poševnice, navedemo izraz .+:

// sprejema https://example.com/a/b/c, path bo 'a/b/c'
$router->addRoute('<path .+>', /* ... */);

Izbirne sekvence

V maski lahko označujemo izbirne dele s pomočjo oglatih oklepajev. Izbirni je lahko katerikoli del maske, lahko se v njem nahajajo tudi parametri:

$router->addRoute('[<lang [a-z]{2}>/]<name>', /* ... */);

// Sprejema poti:
//    /sl/download  => lang => sl, name => download
//    /download     => lang => null, name => download

Ko je parameter del izbirne sekvence, postane seveda tudi izbiren. Če nima navedene privzete vrednosti, bo null.

Izbirni deli so lahko tudi v domeni:

$router->addRoute('//[<lang=en>.]example.com/<presenter>/<action>', /* ... */);

Sekvence je mogoče poljubno gnezditi in kombinirati:

$router->addRoute(
	'[<lang [a-z]{2}>[-<sublang>]/]<name>[/page-<page=0>]',
	'Home:default',
);

// Sprejema poti:
// 	/sl/hello
// 	/en-us/hello
// 	/hello
// 	/hello/page-12

Pri generiranju URL-jev se stremi k najkrajši varianti, zato se vse, kar je mogoče izpustiti, izpusti. Zato na primer pot index[.html] generira pot /index. Obrniti obnašanje je mogoče z navedbo klicaja za levim oglatim oklepajem:

// sprejema /hello in /hello.html, generira /hello
$router->addRoute('<name>[.html]', /* ... */);

// sprejema /hello in /hello.html, generira /hello.html
$router->addRoute('<name>[!.html]', /* ... */);

Izbirni parametri (tj. parametri, ki imajo privzeto vrednost) brez oglatih oklepajev se obnašajo v bistvu tako, kot da bi bili oklepajeni na naslednji način:

$router->addRoute('<presenter=Home>/<action=default>/<id=>', /* ... */);

// ustreza temu:
$router->addRoute('[<presenter=Home>/[<action=default>/[<id>]]]', /* ... */);

Če bi želeli vplivati na obnašanje končne poševnice, da bi se npr. namesto /home/ generiralo samo /home, lahko to dosežemo takole:

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

Nadomestni znaki

V maski absolutne poti lahko uporabimo naslednje nadomestne znake in se tako izognemo npr. potrebi po zapisovanju domene v masko, ki se lahko razlikuje v razvojnem in produkcijskem okolju:

  • %tld% = top level domain, npr. com ali org
  • %sld% = second level domain, npr. example
  • %domain% = domena brez poddomen, npr. example.com
  • %host% = celoten gostitelj, npr. www.example.com
  • %basePath% = pot do korenskega direktorija
$router->addRoute('//www.%domain%/%basePath%/<presenter>/<action>', /* ... */);
$router->addRoute('//www.%sld%.%tld%/%basePath%/<presenter>/<action', /* ... */);

Razširjeni zapis

Cilj poti, običajno zapisan v obliki Presenter:action, je lahko zapisan tudi s pomočjo polja, ki definira posamezne parametre in njihove privzete vrednosti:

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

Za podrobnejšo specifikacijo lahko uporabimo še razširjenejšo obliko, kjer poleg privzetih vrednosti lahko nastavimo tudi druge lastnosti parametrov, kot na primer validacijski regularni izraz (glej parameter id):

use Nette\Routing\Route;

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

Pomembno je opozoriti, da če parametri, definirani v polju, niso navedeni v maski poti, njihovih vrednosti ni mogoče spremeniti, niti s pomočjo poizvedbenih parametrov, navedenih za vprašajem v URL-ju.

Filtri in prevodi

Izvorne kode aplikacije pišemo v angleščini, vendar če naj ima spletno mesto slovenske URL-je, potem preprosto usmerjanje tipa:

$router->addRoute('<presenter>/<action>', 'Home:default');

bo generiralo angleške URL-je, kot na primer /product/123 ali /cart. Če želimo imeti presenterje in akcije v URL-ju predstavljene s slovenskimi besedami (npr. /izdelek/123 ali /kosarica), lahko uporabimo prevodni slovar. Za njegov zapis že potrebujemo »bolj zgovorno« varianto drugega parametra:

use Nette\Routing\Route;

$router->addRoute('<presenter>/<action>', [
	'presenter' => [
		Route::Value => 'Home',
		Route::FilterTable => [
			// niz v URL => presenter
			'izdelek' => 'Product',
			'kosarica' => 'Cart',
			'katalog' => 'Catalog',
		],
	],
	'action' => [
		Route::Value => 'default',
		Route::FilterTable => [
			'seznam' => 'list',
		],
	],
]);

Več ključev prevodnega slovarja lahko vodi na isti presenter. S tem se zanj ustvarijo različni aliasi. Za kanonično varianto (torej tisto, ki bo v generiranem URL-ju) se šteje zadnji ključ.

Prevodno tabelo lahko na ta način uporabimo za katerikoli parameter. Pri čemer, če prevod ne obstaja, se vzame prvotna vrednost. To obnašanje lahko spremenimo z dopolnitvijo Route::FilterStrict => true in pot potem zavrne URL, če vrednost ni v slovarju.

Poleg prevodnega slovarja v obliki polja lahko uporabimo tudi lastne prevodne funkcije.

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,
]);

Funkcija Route::FilterIn pretvarja med parametrom v URL-ju in nizom, ki se nato posreduje v presenter, funkcija FilterOut zagotavlja pretvorbo v nasprotno smer.

Parametri presenter, action in module že imajo preddefinirane filtre, ki pretvarjajo med slogom PascalCase oz. camelCase in kebab-case, uporabljenim v URL-ju. Privzeta vrednost parametrov se zapisuje že v transformirani obliki, tako da na primer v primeru presenterja pišemo <presenter=ProductEdit>, ne pa <presenter=product-edit>.

Splošni filtri

Poleg filtrov, namenjenih konkretnim parametrom, lahko definiramo tudi splošne filtre, ki prejmejo asociativno polje vseh parametrov, ki jih lahko kakorkoli modificirajo in nato vrnejo. Splošne filtre definiramo pod ključem 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 { /* ... */ },
	],
]);

Splošni filtri dajejo možnost prilagoditi obnašanje poti na popolnoma kakršenkoli način. Lahko jih uporabimo na primer za modifikacijo parametrov na podlagi drugih parametrov. Na primer, prevajanje <presenter> in <action> na podlagi trenutne vrednosti parametra <lang>.

Če ima parameter definiran lasten filter in hkrati obstaja splošni filter, se izvede lastni FilterIn pred splošnim in obratno splošni FilterOut pred lastnim. Torej znotraj splošnega filtra so vrednosti parametrov presenter oz. action zapisane v slogu PascalCase oz. camelCase.

Enosmerne poti OneWay

Enosmerne poti se uporabljajo za ohranjanje funkcionalnosti starih URL-jev, ki jih aplikacija ne generira več, vendar jih še vedno sprejema. Označimo jih z zastavico OneWay:

// stari URL /product-info?id=123
$router->addRoute('product-info', 'Product:detail', $router::ONE_WAY);
// novi URL /product/123
$router->addRoute('product/<id>', 'Product:detail');

Pri dostopu do starega URL-ja presenter samodejno preusmeri na nov URL, tako da vam te strani iskalniki ne indeksirajo dvakrat (glej SEO in kanonizacija).

Dinamično usmerjanje s povratnimi klici

Dinamično usmerjanje s povratnimi klici (callbacks) vam omogoča, da potem dodelite neposredno funkcije (callbacke), ki se izvedejo, ko je dana pot obiskana. Ta fleksibilna funkcionalnost vam omogoča hitro in učinkovito ustvarjanje različnih končnih točk (endpoints) za vašo aplikacijo:

$router->addRoute('test', function () {
	echo 'ste na naslovu /test';
});

Lahko tudi definirate v maski parametre, ki se samodejno posredujejo v vaš callback:

$router->addRoute('<lang sl|en>', function (string $lang) {
	echo match ($lang) {
		'sl' => 'Dobrodošli na slovenski različici našega spletnega mesta!',
		'en' => 'Welcome to the English version of our website!',
	};
});

Moduli

Če imamo več poti, ki spadajo v skupni modul, uporabimo withModule():

$router = new RouteList;
$router->withModule('Forum') // naslednje poti so del modula Forum
	->addRoute('rss', 'Feed:rss') // presenter bo Forum:Feed
	->addRoute('<presenter>/<action>')

	->withModule('Admin') // naslednje poti so del modula Forum:Admin
		->addRoute('sign:in', 'Sign:in');

Alternativa je uporaba parametra module:

// URL manage/dashboard/default se preslika na presenter Admin:Dashboard
$router->addRoute('manage/<presenter>/<action>', [
	'module' => 'Admin',
]);

Poddomene

Zbirke poti lahko členimo po poddomenah:

$router = new RouteList;
$router->withDomain('example.com')
	->addRoute('rss', 'Feed:rss')
	->addRoute('<presenter>/<action>');

V imenu domene lahko uporabimo tudi Nadomestni znaki:

$router = new RouteList;
$router->withDomain('example.%tld%')
	// ...

Predpona poti

Zbirke poti lahko členimo po poti v URL-ju:

$router = new RouteList;
$router->withPath('eshop')
	->addRoute('rss', 'Feed:rss') // ujame URL /eshop/rss
	->addRoute('<presenter>/<action>'); // ujame URL /eshop/<presenter>/<action>

Kombinacije

Zgoraj navedeno členjenje lahko medsebojno kombiniramo:

$router = (new RouteList)
	->withDomain('admin.example.com')
		->withModule('Admin')
			->addRoute(/* ... */)
			->addRoute(/* ... */)
		->end()
		->withModule('Images')
			->addRoute(/* ... */)
		->end()
	->end()
	->withDomain('example.com')
		->withPath('export')
			->addRoute(/* ... */)
			// ...

Poizvedbeni parametri

Maske lahko vsebujejo tudi poizvedbene parametre (parametre za vprašajem v URL-ju). Tem ni mogoče definirati validacijskega izraza, vendar lahko spremenimo ime, pod katerim se posredujejo v presenter:

// poizvedbeni parameter 'cat' želimo v aplikaciji uporabiti pod imenom 'categoryId'
$router->addRoute('product ? id=<productId> & cat=<categoryId>', /* ... */);

Foo parametri

Zdaj gremo že globlje. Foo parametri so v bistvu neimenovani parametri, ki omogočajo ujemanje regularnega izraza. Primer je pot, ki sprejema /index, /index.html, /index.htm in /index.php:

$router->addRoute('index<? \.html?|\.php|>', /* ... */);

Lahko tudi eksplicitno definiramo niz, ki bo uporabljen pri generiranju URL-ja. Niz mora biti umeščen neposredno za vprašajem. Naslednja pot je podobna prejšnji, vendar generira /index.html namesto /index, ker je niz .html nastavljen kot generacijska vrednost:

$router->addRoute('index<?.html \.html?|\.php|>', /* ... */);

Vključitev v aplikacijo

Da bi ustvarjeni usmerjevalnik vključili v aplikacijo, moramo o njem povedati DI vsebnika. Najlažja pot je pripraviti tovarno, ki bo objekt usmerjevalnika izdelala, in sporočiti v konfiguraciji vsebnika, da jo naj uporabi. Recimo, da za ta namen napišemo 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;
	}
}

konfiguracijo nato zapišemo:

services:
	- App\Core\RouterFactory::createRouter

Kakršnekoli odvisnosti, na primer od podatkovne baze itd., se posredujejo tovarniški metodi kot njeni parametri s pomočjo autowiringa:

public static function createRouter(Nette\Database\Connection $db): RouteList
{
	// ...
}

SimpleRouter

Veliko enostavnejši usmerjevalnik kot zbirka poti je SimpleRouter. Uporabimo ga takrat, ko nimamo posebnih zahtev glede oblike URL-ja, če ni na voljo mod_rewrite (ali njegove alternative) ali če zaenkrat ne želimo reševati lepih URL-jev.

Generira naslove približno v tej obliki:

http://example.com/?presenter=Product&action=detail&id=123

Parameter konstruktorja SimpleRouterja je privzeti presenter & akcija, na katerega naj se usmerja, če odpremo stran brez parametrov, npr. http://example.com/.

// privzeti presenter bo 'Home' in akcija 'default'
$router = new Nette\Application\Routers\SimpleRouter('Home:default');

Priporočamo, da SimpleRouter neposredno definirate v konfiguraciji:

services:
	- Nette\Application\Routers\SimpleRouter('Home:default')

SEO in kanonizacija

Ogrodje prispeva k SEO (optimizaciji najdljivosti na internetu) s tem, da preprečuje podvojenost vsebine na različnih URL-jih. Če do določenega cilja vodi več naslovov, npr. /index in /index.html, ogrodje prvega od njih določi za primarnega (kanoničnega) in ostale nanj preusmeri s pomočjo HTTP kode 301. Zahvaljujoč temu vam iskalniki strani ne indeksirajo dvakrat in ne razpršijo njihovega page ranka.

Temu procesu rečemo kanonizacija. Kanonični URL je tisti, ki ga generira usmerjevalnik, tj. prva ustrezna pot v zbirki brez zastavice OneWay. Zato v zbirki navajamo primarne poti kot prve.

Kanonizacijo izvaja presenter, več v poglavju kanonizacija.

HTTPS

Da bi lahko uporabljali HTTPS protokol, ga je treba omogočiti na gostovanju in pravilno konfigurirati strežnik.

Preusmeritev celotnega spletnega mesta na HTTPS je treba nastaviti na ravni strežnika, na primer s pomočjo datoteke .htaccess v korenskem direktoriju naše aplikacije, in to s HTTP kodo 301. Nastavitev se lahko razlikuje glede na gostovanje in izgleda približno takole:

<IfModule mod_rewrite.c>
	RewriteEngine On
	...
	RewriteCond %{HTTPS} off
	RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
	...
</IfModule>

Usmerjevalnik generira URL z istim protokolom, s katerim je bila stran naložena, zato ni treba ničesar več nastavljati.

Če pa izjemoma potrebujemo, da različne poti tečejo pod različnimi protokoli, ga navedemo v maski poti:

// Generiral bo naslov s HTTP
$router->addRoute('http://%host%/<presenter>/<action>', /* ... */);

// Generiral bo naslov s HTTPS
$router->addRoute('https://%host%/<presenter>/<action>', /* ... */);

Razhroščevanje usmerjevalnika

Usmerjevalna plošča, ki se prikazuje v Tracy Baru, je koristen pomočnik, ki prikazuje seznam poti in tudi parametrov, ki jih je usmerjevalnik pridobil iz URL-ja.

Zelena vrstica s simbolom ✓ predstavlja pot, ki je obdelala trenutni URL, z modro barvo in simbolom ≈ so označene poti, ki bi prav tako obdelale URL, če jih zelena ne bi prehitela. Nato vidimo trenutni presenter & akcijo.

Hkrati, če pride do nepričakovane preusmeritve zaradi kanonizacije, je koristno pogledati v ploščo v vrstici redirect, kjer ugotovite, kako je usmerjevalnik URL prvotno razumel in zakaj je preusmeril.

Pri razhroščevanju usmerjevalnika priporočamo, da v brskalniku odprete Developer Tools (Ctrl+Shift+I ali Cmd+Option+I) in v plošči Network izklopite predpomnilnik, da se vanj ne shranjujejo preusmeritve.

Zmogljivost

Število poti vpliva na hitrost usmerjevalnika. Njihovo število zagotovo ne bi smelo preseči nekaj deset. Če ima vaše spletno mesto preveč zapleteno strukturo URL-jev, si lahko napišete po meri Lasten usmerjevalnik.

Če usmerjevalnik nima nobenih odvisnosti, na primer od podatkovne baze, in njegova tovarna ne sprejema nobenih argumentov, lahko njegovo sestavljeno obliko serializiramo neposredno v DI vsebnik in s tem aplikacijo nekoliko pospešimo.

routing:
	cache: true

Lasten usmerjevalnik

Naslednje vrstice so namenjene zelo naprednim uporabnikom. Lahko si ustvarite lasten usmerjevalnik in ga popolnoma naravno vključite v zbirko poti. Usmerjevalnik je implementacija vmesnika Nette\Routing\Router z dvema metodama:

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 obdela trenutni zahtevek $httpRequest, iz katerega lahko pridobimo ne samo URL, ampak tudi glave itd., v polje, ki vsebuje ime presenterja in njegove parametre. Če zahtevka ne zna obdelati, vrne null. Pri obdelavi zahtevka moramo vrniti vsaj presenter in akcijo. Ime presenterja je popolno in vsebuje tudi morebitne module:

[
	'presenter' => 'Front:Home',
	'action' => 'default',
]

Metoda constructUrl nasprotno sestavi iz polja parametrov končni absolutni URL. Pri tem lahko uporabi informacije iz parametra $refUrl, kar je trenutni URL.

V zbirko poti ga dodate s pomočjo add():

$router = new Nette\Application\Routers\RouteList;
$router->add($myRouter);
$router->addRoute(/* ... */);
// ...

Samostojna uporaba

Samostojna uporaba pomeni uporabo sposobnosti usmerjevalnika v aplikaciji, ki ne uporablja Nette Application in presenterjev. Zanj velja skoraj vse, kar smo si v tem poglavju pokazali, s temi razlikami:

Torej spet ustvarimo metodo, ki nam bo sestavila usmerjevalnik, npr.:

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;
	}
}

Če uporabljate DI vsebnik, kar priporočamo, spet metodo dodamo v konfiguracijo in nato usmerjevalnik skupaj s HTTP zahtevkom pridobimo iz vsebnika:

$router = $container->getByType(Nette\Routing\Router::class);
$httpRequest = $container->getByType(Nette\Http\IRequest::class);

Ali pa objekte neposredno izdelamo:

$router = App\Core\RouterFactory::createRouter();
$httpRequest = (new Nette\Http\RequestFactory)->fromGlobals();

Zdaj preostane le še, da usmerjevalnik spustimo k delu:

$params = $router->match($httpRequest);
if ($params === null) {
	// ni bila najdena ustrezna pot, pošljemo napako 404
	exit;
}

// obdelamo pridobljene parametre
$controller = $params['controller'];
// ...

In obratno uporabimo usmerjevalnik za sestavljanje povezave:

$params = ['controller' => 'ArticleController', 'id' => 123];
$url = $router->constructUrl($params, $httpRequest->getUrl());
različica: 4.0