Routing
A Router felelős mindenért, ami az URL címekkel kapcsolatos, hogy Önnek már ne kelljen gondolkodnia rajtuk. Megmutatjuk:
- hogyan állítsuk be a routert, hogy az URL-ek az elképzeléseinknek megfeleljenek
- beszélünk a SEO-ról és az átirányításról
- és megmutatjuk, hogyan írjunk saját routert
Az emberibb URL-ek (vagy cool vagy pretty URL-ek) használhatóbbak, megjegyezhetőbbek és pozitívan hozzájárulnak a SEO-hoz. A Nette erre gondol, és teljes mértékben támogatja a fejlesztőket. Pontosan olyan URL-struktúrát tervezhet az alkalmazásához, amilyet csak szeretne. Akár akkor is megtervezheti, amikor az alkalmazás már kész, mert ez nem igényel beavatkozást a kódba vagy a sablonokba. Ugyanis elegáns módon egy egyetlen helyen definiálódik, a routerben, és így nincs szétszórva annotációk formájában az összes presenterben.
A Nette routere kivételes abban, hogy kétirányú. Képes dekódolni a HTTP kérésben lévő URL-t, és linkeket is létrehozni. Tehát kulcsfontosságú szerepet játszik a Nette Applicationben, mert egyrészt eldönti, hogy melyik presenter és akció fogja végrehajtani az aktuális kérést, másrészt pedig a URL generálására használatos a sablonban stb.
Azonban a router nem korlátozódik csak erre a felhasználásra, használhatja olyan alkalmazásokban is, ahol egyáltalán nem használnak presentereket, REST API-khoz stb. További információk a Önálló használat részben.
Route gyűjtemény
Az alkalmazás URL címeinek formájának definiálásának legkellemesebb módját a Nette\Application\Routers\RouteList osztály kínálja. A definíció ún. route-ok listájából áll, azaz URL cím maszkokból és a hozzájuk rendelt presenterekből és akciókból, egy egyszerű API segítségével. A route-okat nem kell elneveznünk.
$router = new Nette\Application\Routers\RouteList;
$router->addRoute('rss.xml', 'Feed:rss');
$router->addRoute('article/<id>', 'Article:view');
// ...
A példa azt mondja, hogy ha a böngészőben megnyitjuk a https://domain.com/rss.xml
címet, akkor a
Feed
presenter jelenik meg az rss
akcióval, ha a https://domain.com/article/12
címet,
akkor az Article
presenter jelenik meg a view
akcióval stb. Ha nem található megfelelő route, a
Nette Application BadRequestException kivételt dob,
amely a felhasználónak 404 Not Found hibaoldalként jelenik meg.
Route-ok sorrendje
Teljesen kulcsfontosságú a sorrend, amelyben az egyes route-ok fel vannak sorolva, mert sorban fentről lefelé értékelődnek ki. Az a szabály érvényes, hogy a route-okat a specifikusaktól az általánosakig deklaráljuk:
// ROSSZ: az 'rss.xml'-t az első route fogja el, és ezt a stringet <slug>-ként értelmezi
$router->addRoute('<slug>', 'Article:view');
$router->addRoute('rss.xml', 'Feed:rss');
// JÓ
$router->addRoute('rss.xml', 'Feed:rss');
$router->addRoute('<slug>', 'Article:view');
A route-ok fentről lefelé értékelődnek ki a linkek generálásakor is:
// ROSSZ: a 'Feed:rss' linket 'admin/feed/rss'-ként generálja
$router->addRoute('admin/<presenter>/<action>', 'Admin:default');
$router->addRoute('rss.xml', 'Feed:rss');
// JÓ
$router->addRoute('rss.xml', 'Feed:rss');
$router->addRoute('admin/<presenter>/<action>', 'Admin:default');
Nem titkoljuk Ön elől, hogy a route-ok helyes összeállítása némi ügyességet igényel. Mielőtt elsajátítaná, hasznos segítő lesz a routing panel.
Maszk és paraméterek
A maszk a web gyökérkönyvtárától számított relatív utat írja le. A legegyszerűbb maszk egy statikus URL:
$router->addRoute('products', 'Products:default');
Gyakran a maszkok ún. paramétereket tartalmaznak. Ezek hegyes zárójelekben vannak megadva (pl.
<year>
), és átadódnak a cél presenternek, például a renderShow(int $year)
metódusnak vagy a
$year
perzisztens paraméternek:
$router->addRoute('chronicle/<year>', 'History:show');
A példa azt mondja, hogy ha a böngészőben megnyitjuk a https://example.com/chronicle/2020
címet, akkor a
History
presenter jelenik meg a show
akcióval és a year: 2020
paraméterrel.
A paramétereknek közvetlenül a maszkban adhatunk alapértelmezett értéket, és ezzel opcionálissá válnak:
$router->addRoute('chronicle/<year=2020>', 'History:show');
A route mostantól elfogadja a https://example.com/chronicle/
URL-t is, amely szintén a
History:show
-t jeleníti meg a year: 2020
paraméterrel.
A paraméter természetesen lehet a presenter és az akció neve is. Például így:
$router->addRoute('<presenter>/<action>', 'Home:default');
Az említett route elfogadja pl. az /article/edit
vagy az /catalog/list
formátumú URL-eket, és
ezeket Article:edit
és Catalog:list
presenterekként és akciókként értelmezi.
Ugyanakkor a presenter
és action
paramétereknek alapértelmezett értékként Home
-ot
és default
-ot ad, így ezek is opcionálisak. Tehát a route elfogadja az /article
formátumú URL-t
is, és azt Article:default
-ként értelmezi. Vagy fordítva, a Product:default
link az
/product
utat generálja, az alapértelmezett Home:default
link pedig a /
utat.
A maszk nemcsak a web gyökérkönyvtárától számított relatív utat írhatja le, hanem abszolút utat is, ha perjellel kezdődik, vagy akár teljes abszolút URL-t is, ha két perjellel kezdődik:
// relatív a document roothoz
$router->addRoute('<presenter>/<action>', /* ... */);
// abszolút út (relatív a domainhez)
$router->addRoute('/<presenter>/<action>', /* ... */);
// abszolút URL domainnel együtt (relatív a sémához)
$router->addRoute('//<lang>.example.com/<presenter>/<action>', /* ... */);
// abszolút URL sémával együtt
$router->addRoute('https://<lang>.example.com/<presenter>/<action>', /* ... */);
Validációs kifejezések
Minden paraméterhez meg lehet határozni egy validációs feltételt reguláris kifejezéssel. Például az id
paraméternek meghatározzuk, hogy csak számjegyeket tartalmazhat a \d+
reguláris kifejezéssel:
$router->addRoute('<presenter>/<action>[/<id \d+>]', /* ... */);
Minden paraméter alapértelmezett reguláris kifejezése [^/]+
, azaz minden, kivéve a perjelet. Ha egy
paraméternek perjeleket is el kell fogadnia, adjuk meg a .+
kifejezést:
// elfogadja a https://example.com/a/b/c címet, a path 'a/b/c' lesz
$router->addRoute('<path .+>', /* ... */);
Opcionális szekvenciák
A maszkban szögletes zárójelekkel lehet jelölni az opcionális részeket. A maszk bármely része lehet opcionális, és tartalmazhatnak paramétereket is:
$router->addRoute('[<lang [a-z]{2}>/]<name>', /* ... */);
// Elfogadott utak:
// /cs/download => lang => cs, name => download
// /download => lang => null, name => download
Ha egy paraméter egy opcionális szekvencia része, természetesen maga is opcionálissá válik. Ha nincs megadva alapértelmezett értéke, akkor null lesz.
Az opcionális részek a domainben is lehetnek:
$router->addRoute('//[<lang=en>.]example.com/<presenter>/<action>', /* ... */);
A szekvenciákat tetszőlegesen lehet egymásba ágyazni és kombinálni:
$router->addRoute(
'[<lang [a-z]{2}>[-<sublang>]/]<name>[/page-<page=0>]',
'Home:default',
);
// Elfogadott utak:
// /cs/hello
// /en-us/hello
// /hello
// /hello/page-12
Az URL generálásakor a legrövidebb változatra törekszünk, tehát minden, amit ki lehet hagyni, kihagyásra kerül. Ezért
például az index[.html]
route az /index
utat generálja. A viselkedés megfordítása a bal
szögletes zárójel utáni felkiáltójellel lehetséges:
// elfogadja a /hello és /hello.html címeket, /hello-t generál
$router->addRoute('<name>[.html]', /* ... */);
// elfogadja a /hello és /hello.html címeket, /hello.html-t generál
$router->addRoute('<name>[!.html]', /* ... */);
Az opcionális paraméterek (azaz az alapértelmezett értékkel rendelkező paraméterek) szögletes zárójelek nélkül lényegében úgy viselkednek, mintha a következőképpen lennének zárójelezve:
$router->addRoute('<presenter=Home>/<action=default>/<id=>', /* ... */);
// megfelel ennek:
$router->addRoute('[<presenter=Home>/[<action=default>/[<id>]]]', /* ... */);
Ha befolyásolni szeretnénk a záró perjel viselkedését, hogy pl. a /home/
helyett csak /home
generálódjon, azt így lehet elérni:
$router->addRoute('[<presenter=Home>[/<action=default>[/<id>]]]', /* ... */);
Helyettesítő karakterek
Az abszolút út maszkjában használhatjuk a következő helyettesítő karaktereket, és így elkerülhetjük például annak szükségességét, hogy a maszkba írjuk a domaint, amely eltérhet a fejlesztői és az éles környezetben:
%tld%
= top level domain, pl.com
vagyorg
%sld%
= second level domain, pl.example
%domain%
= domain aldomainek nélkül, pl.example.com
%host%
= teljes host, pl.www.example.com
%basePath%
= út a gyökérkönyvtárhoz
$router->addRoute('//www.%domain%/%basePath%/<presenter>/<action>', /* ... */);
$router->addRoute('//www.%sld%.%tld%/%basePath%/<presenter>/<action', /* ... */);
Bővített jelölés
A route célja, amelyet általában Presenter:action
formában írunk, tömbként is megadható, amely
definiálja az egyes paramétereket és azok alapértelmezett értékeit:
$router->addRoute('<presenter>/<action>[/<id \d+>]', [
'presenter' => 'Home',
'action' => 'default',
]);
Részletesebb specifikációhoz használható egy még bővebb forma, ahol az alapértelmezett értékeken kívül
beállíthatjuk a paraméterek további tulajdonságait is, mint például a validációs reguláris kifejezést (lásd az
id
paramétert):
use Nette\Routing\Route;
$router->addRoute('<presenter>/<action>[/<id>]', [
'presenter' => [
Route::Value => 'Home',
],
'action' => [
Route::Value => 'default',
],
'id' => [
Route::Pattern => '\d+',
],
]);
Fontos megjegyezni, hogy ha a tömbben definiált paraméterek nincsenek megadva az út maszkjában, értéküket nem lehet megváltoztatni, még az URL-ben a kérdőjel után megadott query paraméterekkel sem.
Szűrők és fordítások
Az alkalmazás forráskódjait angolul írjuk, de ha a weboldalnak magyar URL-ekkel kell rendelkeznie, akkor az egyszerű routing típus:
$router->addRoute('<presenter>/<action>', 'Home:default');
angol URL-eket fog generálni, mint például /product/123
vagy /cart
. Ha azt szeretnénk, hogy a
presenterek és akciók az URL-ben magyar szavakkal legyenek reprezentálva (pl. /produkt/123
vagy
/kosik
), használhatunk fordítási szótárat. Ennek megadásához már a második paraméter “beszédesebb”
változatára van szükség:
use Nette\Routing\Route;
$router->addRoute('<presenter>/<action>', [
'presenter' => [
Route::Value => 'Home',
Route::FilterTable => [
// string az URL-ben => presenter
'produkt' => 'Product',
'kosik' => 'Cart',
'katalog' => 'Catalog',
],
],
'action' => [
Route::Value => 'default',
Route::FilterTable => [
'lista' => 'list',
],
],
]);
A fordítási szótár több kulcsa is ugyanarra a presenterhez vezethet. Ezzel különböző aliasokat hozunk létre hozzá. Kanonikus változatnak (tehát annak, amely a generált URL-ben lesz) az utolsó kulcs számít.
A fordítási táblát így bármelyik paraméterre lehet alkalmazni. Ha a fordítás nem létezik, az eredeti érték veszi
át. Ezt a viselkedést megváltoztathatjuk a Route::FilterStrict => true
hozzáadásával, és a route
elutasítja az URL-t, ha az érték nincs a szótárban.
A tömb formájú fordítási szótár mellett saját fordítási függvényeket is bevethetünk.
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,
]);
A Route::FilterIn
függvény átalakít az URL-ben lévő paraméter és a presenternek átadott string között,
a FilterOut
függvény pedig az ellenkező irányú átalakítást biztosítja.
A presenter
, action
és module
paramétereknek már vannak előre definiált szűrőik,
amelyek átalakítanak a PascalCase ill. camelCase stílus és az URL-ben használt kebab-case között. A paraméterek
alapértelmezett értéke már az átalakított formában íródik, tehát például a presenter esetében
<presenter=ProductEdit>
-et írunk, nem pedig <presenter=product-edit>
-et.
Általános szűrők
A konkrét paraméterekhez szánt szűrők mellett definiálhatunk általános szűrőket is, amelyek megkapják az összes
paraméter asszociatív tömbjét, amelyet tetszőlegesen módosíthatnak, majd visszaadják. Az általános szűrőket a
null
kulcs alatt definiáljuk.
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 { /* ... */ },
],
]);
Az általános szűrők lehetővé teszik a route viselkedésének teljesen tetszőleges módosítását. Használhatjuk őket
például paraméterek módosítására más paraméterek alapján. Például a <presenter>
és
<action>
lefordítása az aktuális <lang>
paraméter értéke alapján.
Ha egy paraméternek van saját szűrője definiálva, és egyidejűleg létezik általános szűrő is, akkor a saját
FilterIn
hajtódik végre az általános előtt, és fordítva, az általános FilterOut
a saját
előtt. Tehát az általános szűrőn belül a presenter
ill. action
paraméterek értékei PascalCase
ill. camelCase stílusban vannak megadva.
Egyirányú OneWay
Az egyirányú route-okat a régi URL-ek funkcionalitásának megőrzésére használják, amelyeket az alkalmazás már nem
generál, de még mindig elfogad. OneWay
jelzővel jelöljük őket:
// régi URL /product-info?id=123
$router->addRoute('product-info', 'Product:detail', $router::ONE_WAY);
// új URL /product/123
$router->addRoute('product/<id>', 'Product:detail');
A régi URL-re való hozzáféréskor a presenter automatikusan átirányít az új URL-re, így ezeket az oldalakat a keresőmotorok nem indexelik kétszer (lásd SEO a kanonizace).
Dinamikus routing callbackekkel
A dinamikus routing callbackekkel lehetővé teszi, hogy a route-okhoz közvetlenül függvényeket (callbackeket) rendeljen, amelyek akkor hajtódnak végre, amikor az adott utat meglátogatják. Ez a rugalmas funkcionalitás lehetővé teszi, hogy gyorsan és hatékonyan hozzon létre különböző végpontokat (endpoints) az alkalmazásához:
$router->addRoute('test', function () {
echo 'a /test címen van';
});
Definiálhat paramétereket is a maszkban, amelyek automatikusan átadódnak a callbacknek:
$router->addRoute('<lang cs|en>', function (string $lang) {
echo match ($lang) {
'cs' => 'Üdvözöljük weboldalunk cseh verzióján!',
'en' => 'Welcome to the English version of our website!',
};
});
Modulok
Ha több route-unk van, amelyek egy közös modulba tartoznak, használjuk a
withModule()
-t:
$router = new RouteList;
$router->withModule('Forum') // a következő route-ok a Forum modul részei
->addRoute('rss', 'Feed:rss') // a presenter Forum:Feed lesz
->addRoute('<presenter>/<action>')
->withModule('Admin') // a következő route-ok a Forum:Admin modul részei
->addRoute('sign:in', 'Sign:in');
Alternatívaként használható a module
paraméter:
// Az URL manage/dashboard/default az Admin:Dashboard presenterhez map-el
$router->addRoute('manage/<presenter>/<action>', [
'module' => 'Admin',
]);
Aldomainek
A route gyűjteményeket aldomainek szerint is tagolhatjuk:
$router = new RouteList;
$router->withDomain('example.com')
->addRoute('rss', 'Feed:rss')
->addRoute('<presenter>/<action>');
A domain névben használhatunk zástupné znaky helyettesítő karaktereket is:
$router = new RouteList;
$router->withDomain('example.%tld%')
// ...
Útvonal prefix
A route gyűjteményeket az URL útvonala szerint is tagolhatjuk:
$router = new RouteList;
$router->withPath('eshop')
->addRoute('rss', 'Feed:rss') // elfogja az /eshop/rss URL-t
->addRoute('<presenter>/<action>'); // elfogja az /eshop/<presenter>/<action> URL-t
Kombinációk
A fenti tagolásokat kölcsönösen kombinálhatjuk:
$router = (new RouteList)
->withDomain('admin.example.com')
->withModule('Admin')
->addRoute(/* ... */)
->addRoute(/* ... */)
->end()
->withModule('Images')
->addRoute(/* ... */)
->end()
->end()
->withDomain('example.com')
->withPath('export')
->addRoute(/* ... */)
// ...
Query paraméterek
A maszkok tartalmazhatnak query paramétereket is (paraméterek a kérdőjel után az URL-ben). Ezekhez nem lehet validációs kifejezést definiálni, de meg lehet változtatni a nevüket, amely alatt a presenternek átadódnak:
// a 'cat' query paramétert az alkalmazásban 'categoryId' néven szeretnénk használni
$router->addRoute('product ? id=<productId> & cat=<categoryId>', /* ... */);
Foo paraméterek
Most már mélyebbre megyünk. A Foo paraméterek lényegében névtelen paraméterek, amelyek lehetővé teszik reguláris
kifejezések illesztését. Példa egy route-ra, amely elfogadja a /index
, /index.html
,
/index.htm
és /index.php
címeket:
$router->addRoute('index<? \.html?|\.php|>', /* ... */);
Explicit módon is definiálható a string, amelyet az URL generálásakor használni kell. A stringnek közvetlenül a
kérdőjel után kell elhelyezkednie. A következő route hasonló az előzőhöz, de /index.html
-t generál
/index
helyett, mert a .html
string van beállítva generálási értékként:
$router->addRoute('index<?.html \.html?|\.php|>', /* ... */);
Integrálás az alkalmazásba
Ahhoz, hogy a létrehozott routert bekapcsoljuk az alkalmazásba, szólnunk kell róla a DI konténernek. A legegyszerűbb út
egy factory elkészítése, amely a router objektumot létrehozza, és a konfigurációban közölni a konténerrel, hogy azt
használja. Tegyük fel, hogy erre a célra megírjuk az App\Core\RouterFactory::createRouter()
metódust:
namespace App\Core;
use Nette\Application\Routers\RouteList;
class RouterFactory
{
public static function createRouter(): RouteList
{
$router = new RouteList;
$router->addRoute(/* ... */);
return $router;
}
}
A konfigurációba pedig beírjuk:
services:
- App\Core\RouterFactory::createRouter
Bármilyen függőség, például adatbázisra stb., átadódik a factory metódusnak annak paramétereiként autowiring segítségével:
public static function createRouter(Nette\Database\Connection $db): RouteList
{
// ...
}
SimpleRouter
Sokkal egyszerűbb router, mint a route gyűjtemény, a SimpleRouter. Akkor használjuk,
ha nincsenek különösebb igényeink az URL formájára, ha nincs mod_rewrite
(vagy annak alternatívái)
elérhető, vagy ha még nem akarunk szép URL-ekkel foglalkozni.
Körülbelül ilyen formátumú címeket generál:
http://example.com/?presenter=Product&action=detail&id=123
A SimpleRouter konstruktorának paramétere az alapértelmezett presenter & akció, amelyre irányítani kell, ha
paraméterek nélkül nyitjuk meg az oldalt, pl. http://example.com/
.
// az alapértelmezett presenter 'Home' lesz, az akció pedig 'default'
$router = new Nette\Application\Routers\SimpleRouter('Home:default');
Javasoljuk a SimpleRouter közvetlen definiálását a konfigurációban:
services:
- Nette\Application\Routers\SimpleRouter('Home:default')
SEO és kanonizáció
A keretrendszer hozzájárul a SEO-hoz (keresőoptimalizálás) azáltal, hogy megakadályozza a duplikált tartalom
létezését különböző URL-eken. Ha egy bizonyos célhoz több cím vezet, pl. /index
és
/index.html
, a keretrendszer az elsőt elsődlegesnek (kanonikusnak) határozza meg, a többit pedig 301-es HTTP
kóddal átirányítja rá. Ennek köszönhetően a keresőmotorok nem indexelik kétszer az oldalakat, és nem osztják meg a
page rankjüket.
Ezt a folyamatot kanonizációnak nevezik. A kanonikus URL az, amelyet a router generál, azaz az első megfelelő route a gyűjteményben OneWay jelző nélkül. Ezért a gyűjteményben az elsődleges route-okat adjuk meg először.
A kanonizációt a presenter végzi, további információk a kanonizáció fejezetben.
HTTPS
Ahhoz, hogy a HTTPS protokollt használhassuk, engedélyezni kell a hostingen és helyesen kell konfigurálni a szervert.
Az egész weboldal HTTPS-re való átirányítását a szerver szintjén kell beállítani, például a .htaccess
fájl segítségével az alkalmazásunk gyökérkönyvtárában, 301-es HTTP kóddal. A beállítás eltérhet a hostingtól
függően, és kb. így néz ki:
<IfModule mod_rewrite.c>
RewriteEngine On
...
RewriteCond %{HTTPS} off
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
...
</IfModule>
A router ugyanazzal a protokollal generálja az URL-eket, amellyel az oldal betöltődött, így semmi mást nem kell beállítani.
Ha azonban kivételesen szükségünk van arra, hogy különböző route-ok különböző protokollok alatt fussanak, azt a route maszkjában adjuk meg:
// HTTP-vel fog címet generálni
$router->addRoute('http://%host%/<presenter>/<action>', /* ... */);
// HTTPS-sel fog címet generálni
$router->addRoute('https://%host%/<presenter>/<action>', /* ... */);
Router debuggolása
A Tracy Barban megjelenő routing panel hasznos segítő, amely megjeleníti a route-ok listáját és azokat a paramétereket is, amelyeket a router az URL-ből nyert.
A zöld sáv a ✓ szimbólummal azt a route-ot jelöli, amely feldolgozta az aktuális URL-t, a kék szín és a ≈ szimbólum azokat a route-okat jelöli, amelyek szintén feldolgozták volna az URL-t, ha a zöld nem előzte volna meg őket. Továbbá látjuk az aktuális presentert & akciót.

Ugyanakkor, ha váratlan átirányítás történik a kanonizáció miatt, hasznos megnézni a redirect sávban lévő panelt, ahol megtudhatja, hogyan értelmezte a router eredetileg az URL-t, és miért irányított át.
A router debuggolásakor javasoljuk a Developer Tools (Ctrl+Shift+I vagy Cmd+Option+I) megnyitását a böngészőben, és a Network panelen a cache kikapcsolását, hogy az átirányítások ne kerüljenek bele.
Teljesítmény
A route-ok száma befolyásolja a router sebességét. Számuknak semmiképpen sem szabadna meghaladnia a néhány tucatot. Ha a weboldalának túl bonyolult az URL struktúrája, írhat saját, testreszabott vlastní router routert.
Ha a routernek nincsenek függőségei, például adatbázisra, és a factory-ja nem fogad argumentumokat, akkor az összeállított formáját közvetlenül a DI konténerbe szerializálhatjuk, és ezzel kissé felgyorsíthatjuk az alkalmazást.
routing:
cache: true
Saját router
A következő sorok nagyon haladó felhasználóknak szólnak. Létrehozhat saját routert, és teljesen természetesen beillesztheti a route gyűjteménybe. A router a Nette\Routing\Router interfész implementációja két metódussal:
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
{
// ...
}
}
A match
metódus feldolgozza az aktuális kérést $httpRequest, amelyből nemcsak az URL-t, hanem a fejléceket stb. is meg lehet
szerezni, egy tömbbe, amely tartalmazza a presenter nevét és annak paramétereit. Ha nem tudja feldolgozni a kérést, null-t
ad vissza. A kérés feldolgozásakor legalább a presentert és az akciót vissza kell adnunk. A presenter neve teljes, és
tartalmazza az esetleges modulokat is:
[
'presenter' => 'Front:Home',
'action' => 'default',
]
A constructUrl
metódus fordítva, a paraméterek tömbjéből állítja össze a végső abszolút URL-t. Ehhez
felhasználhatja a $refUrl
paraméterből
származó információkat, ami az aktuális URL.
A route gyűjteményhez az add()
segítségével adhatja hozzá:
$router = new Nette\Application\Routers\RouteList;
$router->add($myRouter);
$router->addRoute(/* ... */);
// ...
Önálló használat
Önálló használat alatt azt értjük, hogy a router képességeit olyan alkalmazásban használjuk, amely nem használja a Nette Applicationt és a presentereket. Szinte minden érvényes rá, amit ebben a fejezetben megmutattunk, a következő különbségekkel:
- route gyűjteményekhez a Nette\Routing\RouteList osztályt használjuk
- simple routerként a Nette\Routing\SimpleRouter osztályt
- mivel nincs
Presenter:action
pár, a rozšířený zápis jelölést használjuk
Tehát ismét létrehozunk egy metódust, amely összeállítja nekünk a routert, pl.:
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;
}
}
Ha DI konténert használ, amit javasolunk, ismét hozzáadjuk a metódust a konfigurációhoz, majd a routert a HTTP kéréssel együtt megszerezzük a konténerből:
$router = $container->getByType(Nette\Routing\Router::class);
$httpRequest = $container->getByType(Nette\Http\IRequest::class);
Vagy közvetlenül létrehozzuk az objektumokat:
$router = App\Core\RouterFactory::createRouter();
$httpRequest = (new Nette\Http\RequestFactory)->fromGlobals();
Most már csak hagyni kell a routert dolgozni:
$params = $router->match($httpRequest);
if ($params === null) {
// nem találtunk megfelelő route-ot, 404-es hibát küldünk
exit;
}
// feldolgozzuk a kapott paramétereket
$controller = $params['controller'];
// ...
És fordítva, a routert használjuk a link összeállításához:
$params = ['controller' => 'ArticleController', 'id' => 123];
$url = $router->constructUrl($params, $httpRequest->getUrl());