Útválasztás
Az útválasztó felelős mindenért az URL-ekkel kapcsolatban, így nem kell többé gondolkodnod rajtuk. Megmutatjuk:
- hogyan állítsuk be a routert, hogy az URL-ek úgy nézzenek ki, ahogyan szeretnénk.
- néhány megjegyzést a SEO átirányításról
- és megmutatjuk, hogyan írhatod meg a saját routeredet.
Az emberibb URL-ek (vagy menőbb vagy csinosabb URL-ek) jobban használhatóak, emlékezetesebbek és pozitívan járulnak hozzá a SEO-hoz. A Nette ezt tartja szem előtt, és teljes mértékben megfelel a fejlesztők vágyainak. Pontosan úgy alakíthatja ki az alkalmazás URL-szerkezetét, ahogyan szeretné. Akár az alkalmazás elkészülte után is megtervezheti, mivel ez kód- vagy sablonmódosítás nélkül is elvégezhető. Elegáns módon, egyetlen helyen, a routerben kerül meghatározásra, és nem szóródik szét megjegyzések formájában az összes bemutatóban.
A Nette router azért különleges, mert kétirányú, képes mind a HTTP-kérő URL-ek dekódolására, mind a linkek létrehozására. Tehát létfontosságú szerepet játszik a Nette alkalmazásban, mert eldönti, hogy melyik prezenter és akció fogja végrehajtani az aktuális kérést, és a sablonban az URL generálásához is használják stb.
A router azonban nem korlátozódik erre a felhasználásra, használhatja olyan alkalmazásokban is, ahol egyáltalán nem használnak prezentereket, REST API-khoz stb. Bővebben az elkülönített használat szakaszban.
Útvonalgyűjtés
Az URL címek definiálásának legkellemesebb módja az alkalmazásban a Nette\Application\Routers\RouteList osztályon keresztül történik. A definíció úgynevezett útvonalak listájából áll, azaz URL-címek maszkjaiból és a hozzájuk tartozó bemutatókból és műveletekből egy egyszerű API segítségével. Az útvonalakat nem kell megneveznü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 megnyitjuk a https://any-domain.com/rss.xml
prezenter a rss
akcióval
jelenik meg, ha a https://domain.com/article/12
a view
akcióval, stb. Ha nem találunk megfelelő
útvonalat, a Nette Application egy BadRequestException kivétel
dobásával válaszol, amely a felhasználó számára egy 404 Not Found hibaoldalként jelenik meg.
Az útvonalak sorrendje
Az útvonalak sorrendje nagyon fontos, mivel az útvonalakat a rendszer fentről lefelé haladva értékeli ki. A szabály az, hogy az útvonalakat specifikusról az általánosra jelentjük be:
// ROSSZ: az 'rss.xml' az első útvonalra illeszkedik, és ezt félreérti <slug>-nak tekinti.
$router->addRoute('<slug>', 'Article:view');
$router->addRoute('rss.xml', 'Feed:rss');
// JÓ
$router->addRoute('rss.xml', 'Feed:rss');
$router->addRoute('<slug>', 'Article:view');
Az útvonalakat a linkek generálásakor is felülről lefelé értékeljük ki:
// ROSSZ: a 'Feed:rss' linket 'admin/feed/rss' néven 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 tartjuk titokban Ön előtt, hogy a lista helyes felépítéséhez némi szakértelemre van szükség. Amíg bele nem jön, az útvonalválasztó panel hasznos eszköz lesz.
Maszk és paraméterek
A maszk a relatív elérési utat írja le a webhely gyökere alapján. A legegyszerűbb maszk egy statikus URL:
$router->addRoute('products', 'Products:default');
A maszkok gyakran tartalmaznak úgynevezett paramétereket. Ezeket szögletes zárójelek közé zárják (pl.
<year>
), és a célbemutatónak adják át, például a renderShow(int $year)
metódusnak vagy a
$year
állandó paraméternek:
$router->addRoute('chronicle/<year>', 'History:show');
A példa azt mondja, hogy ha megnyitjuk a https://any-domain.com/chronicle/2020
prezenter és a show
művelet a year: 2020
paraméterrel megjelenik.
A paraméterek alapértelmezett értékét közvetlenül a maszkban adhatjuk meg, és így opcionálissá válik:
$router->addRoute('chronicle/<year=2020>', 'History:show');
Az útvonal mostantól elfogadja a https://any-domain.com/chronicle/
címet fogja megjeleníteni a
year: 2020
paraméterrel.
Természetesen a bemutató és az akció neve is lehet paraméter. Például:
$router->addRoute('<presenter>/<action>', 'Home:default');
Ez az útvonal elfogad például egy URL-t a /article/edit
illetve /catalog/list
formában, és
lefordítja azokat a Article:edit
illetve Catalog:list
előadókra és műveletekre.
A presenter
és a action
paramétereknek alapértelmezett értékeket ad:Home
és
default
, ezért ezek opcionálisak. Az útvonal tehát elfogad egy /article
URL-t is, és lefordítja
Article:default
-ként. Vagy fordítva, a Product:default
hivatkozás a /product
útvonalat
generálja, az alapértelmezett Home:default
hivatkozás a /
útvonalat generálja.
A maszk nem csak a webhely gyökere alapján a relatív elérési utat írhatja le, hanem az abszolút elérési utat is, ha az kötőjellel kezdődik, vagy akár a teljes abszolút URL-t, ha két kötőjellel kezdődik:
// relatív elérési út az alkalmazási dokumentum gyökeréhez
$router->addRoute('<presenter>/<action>', /* ... */);
// abszolút elérési út, relatív a szerver hostnevéhez
$router->addRoute('/<presenter>/<action>', /* ... */);
// abszolút URL, beleértve a hosztnevet is (de séma-relatív)
$router->addRoute('//<lang>.example.com/<presenter>/<action>', /* ... */);
// abszolút URL, beleértve a sémát is
$router->addRoute('https://<lang>.example.com/<presenter>/<action>', /* ... */);
Érvényesítési kifejezések
Minden paraméterhez megadható egy érvényesítési feltétel szabályos kifejezéssel. Például állítsuk be, hogy
a id
csak numerikus legyen, a \d+
regexp használatával:
$router->addRoute('<presenter>/<action>[/<id \d+>]', /* ... */);
Az alapértelmezett reguláris kifejezés minden paraméterhez a következő [^/]+
, azaz minden, kivéve a
slash-t. Ha egy paraméternek a slash-re is illeszkednie kell, akkor a reguláris kifejezést a .+
-ra állítjuk.
// elfogadja a https://example.com/a/b/c címet, az elérési útvonal 'a/b/c'.
$router->addRoute('<path .+>', /* ... */);
Választható szekvenciák
A szögletes zárójelek a maszk opcionális részeit jelölik. A maszk bármelyik része opcionális lehet, beleértve a paramétereket tartalmazó részeket is:
$router->addRoute('[<lang [a-z]{2}>/]<name>', /* ... */);
// Elfogadott URL-címek: Paraméterek:
// /en/download lang => en, name => download
// /download lang => null, name => download
Természetesen, ha egy paraméter egy opcionális sorozat része, akkor az is opcionálissá válik. Ha nincs alapértelmezett értéke, akkor null lesz.
Az opcionális szakaszok a tartományban is lehetnek:
$router->addRoute('//[<lang=en>.]example.com/<presenter>/<action>', /* ... */);
A szekvenciák szabadon egymásba ágyazhatók és kombinálhatók:
$router->addRoute(
'[<lang [a-z]{2}>[-<sublang>]/]<name>[/page-<page=0>]',
'Home:default',
);
// Elfogadott URL-címek:
// /en/hello
// /en-us/hello
// /hello
// /hello/page-12
Az URL-generátor igyekszik az URL-t a lehető legrövidebbre fogalmazni, ezért ami elhagyható, azt elhagyja. Ezért
például egy útvonal index[.html]
generál egy /index
elérési utat. Ezt a viselkedést
megfordíthatja, ha a bal oldali szögletes zárójel után felkiáltójelet ír:
// elfogadja a /hello és a /hello.html fájlt is, és /hello.html-t generál.
$router->addRoute('<name>[.html]', /* ... */);
// elfogadja a /hello és a /hello.html címeket is, generálja a /hello.html címet.
$router->addRoute('<name>[!.html]', /* ... */);
A szögletes zárójel nélküli opcionális paraméterek (azaz az alapértelmezett értékkel rendelkező paraméterek) úgy viselkednek, mintha így lennének becsomagolva:
$router->addRoute('<presenter=Home>/<action=default>/<id=>', /* ... */);
// egyenlő:
$router->addRoute('[<presenter=Home>/[<action=default>/[<id>]]]', /* ... */);
Ha meg akarja változtatni a jobb oldali slash generálásának módját, azaz a /home/
helyett egy
/home
kapjon, állítsa be az útvonalat így:
$router->addRoute('[<presenter=Home>[/<action=default>[/<id>]]]', /* ... */);
.
Az abszolút elérési útvonal maszkjában használhatjuk a következő jokereket, hogy elkerüljük például a tartomány beírását a maszkba, ami a fejlesztői és a termelési környezetben eltérő lehet:
%tld%
= legfelső szintű tartomány, pl.com
vagyorg
%sld%
= második szintű tartomány, pl.example
%domain%
= aldomainek nélküli tartomány, pl.example.com
%host%
= teljes hoszt, pl.www.example.com
%basePath%
= a gyökérkönyvtár elérési útvonala
$router->addRoute('//www.%domain%/%basePath%/<presenter>/<action>', /* ... */);
$router->addRoute('//www.%sld%.%tld%/%basePath%/<presenter>/<action', /* ... */);
Speciális jelölés
Az útvonal célját, amelyet általában a Presenter:action
formában írunk le, egy olyan tömb segítségével
is ki lehet fejezni, amely meghatározza 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 egy még bővebb formát lehet használni, ahol az alapértelmezett értékek mellett más
paramétertulajdonságok is megadhatók, például egy érvényesítési reguláris kifejezés (lásd a 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 nem szerepelnek az elérési útvonal maszkjában, akkor értékük nem módosítható, még az URL-ben kérdőjel után megadott lekérdezési paraméterekkel sem.
Szűrők és fordítások
Jó gyakorlat, hogy a forráskódot angolul írjuk, de mi van akkor, ha a weboldalunknak le kell fordítani az URL-t más nyelvre? Egyszerű útvonalak, mint például:
$router->addRoute('<presenter>/<action>', 'Home:default');
angol nyelvű URL-eket generálnak, például /product/123
vagy /cart
. Ha azt szeretnénk, hogy az
URL-ben szereplő bemutatókat és műveleteket németre fordítsák le (pl. /produkt/123
vagy
/einkaufswagen
), használhatunk egy fordítószótárat. Ennek hozzáadásához már a második paraméter
„beszédesebb“ változatára van szükségünk:
use Nette\Routing\Route;
$router->addRoute('<presenter>/<action>', [
'presenter' => [
Route::Value => 'Home',
Route::FilterTable => [
// string az URL-ben => prezenter
'produkt' => 'Product',
'einkaufswagen' => 'Cart',
'katalog' => 'Catalog',
],
],
'action' => [
Route::Value => 'default',
Route::FilterTable => [
'liste' => 'list',
],
],
]);
Több szótárkulcsot is használhatunk ugyanahhoz a prezentálóhoz. Ezek különböző aliasokat hoznak létre hozzá. Az utolsó kulcsot tekintjük a kanonikus változatnak (vagyis annak, amelyik a generált URL-ben szerepel majd).
A fordítási táblázat így bármely paraméterre alkalmazható. Ha azonban a fordítás nem létezik, akkor az eredeti
értéket veszi át. Ezt a viselkedést megváltoztathatjuk a Route::FilterStrict => true
hozzáadásával, és az
útvonal ekkor elutasítja az URL-t, ha az érték nem szerepel a szótárban.
A fordítási szótár mellett tömb formájában saját fordítási függvények beállítására is lehetőség van:
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 az URL-ben szereplő paraméter és a karakterlánc között konvertál, amelyet
aztán átadunk a prezentálónak, a FilterOut
függvény pedig az ellenkező irányú konvertálást
biztosítja.
A presenter
, action
és module
paraméterek már rendelkeznek előre definiált
szűrőkkel, amelyek az URL-ben használt PascalCase, illetve camelCase stílus és a kebab-case között konvertálnak.
A paraméterek alapértelmezett értékét már az átalakított formában írjuk ki, így például egy bemutató esetében azt
írjuk, hogy <presenter=ProductEdit>
helyett <presenter=product-edit>
.
Általános szűrők
A specifikus paraméterekhez tartozó szűrők mellett általános szűrőket is definiálhat, amelyek megkapják az összes
paraméter asszociatív tömbjét, amelyeket bármilyen módon módosíthatnak, majd visszaadnak. Az általános szűrők a
null
kulcs alatt definiálhatók.
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, hogy az útvonal viselkedését teljesen tetszőleges módon módosítsa.
Használhatjuk őket például arra, hogy a paramétereket más paraméterek alapján módosítsuk. Például fordítás
<presenter>
és a <action>
paraméter aktuális értéke alapján
<lang>
.
Ha egy paraméterhez egyéni szűrő van definiálva és egyidejűleg létezik egy általános szűrő, az egyéni
FilterIn
az általános előtt kerül végrehajtásra, és fordítva, az általános FilterOut
az
egyéni előtt kerül végrehajtásra. Így az általános szűrőn belül a presenter
illetve a action
paraméterek értékei PascalCase illetve camelCase stílusban íródnak.
Egyirányú zászló
Az egyirányú útvonalakat arra használják, hogy megőrizzék a régi URL-ek funkcionalitását, amelyeket az alkalmazás
már nem generál, de még elfogad. Ezeket a OneWay
jelzéssel jelöljük:
// régi URL /product-info?id=123
$router->addRoute('product-info', 'Product:detail', $router::ONE_WAY);
// új URL /termék/123
$router->addRoute('product/<id>', 'Product:detail');
A régi URL elérésekor a bemutató automatikusan átirányítja az új URL-re, hogy a keresőmotorok ne indexeljék kétszer ezeket az oldalakat (lásd SEO és kanonizáció).
Dinamikus útválasztás visszahívásokkal
A dinamikus útválasztás visszahívásokkal lehetővé teszi, hogy az útvonalakhoz közvetlenül hozzárendeljen függvényeket (visszahívásokat), amelyek a megadott útvonal meglátogatásakor végrehajtódnak. Ez a rugalmas funkció lehetővé teszi, hogy gyorsan és hatékonyan hozzon létre különböző végpontokat az alkalmazásához:
$router->addRoute('test', function () {
echo 'You are at the /test address';
});
A maszkban paramétereket is meghatározhat, amelyek automatikusan átadásra kerülnek a visszahívásnak:
$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!',
};
});
Modulok
Ha több olyan útvonalunk van, amelyek egy modulhoz tartoznak, akkor a withModule()
segítségével csoportosíthatjuk őket:
$router = new RouteList;
$router->withModule('Forum') // a következő útválasztók a Forum modul részei
->addRoute('rss', 'Feed:rss') // a bemutató a Forum:Feed
->addRoute('<presenter>/<action>')
->withModule('Admin') // a következő útválasztók a Forum:Admin modul részei
->addRoute('sign:in', 'Bejelentkezés:in');
Alternatív megoldás a module
paraméter használata:
// Az URL manage/dashboard/default a prezenterhez tartozik Admin:Dashboard
$router->addRoute('manage/<presenter>/<action>', [
'module' => 'Admin',
]);
Aldomainek
Az útvonalgyűjteményeket aldomainek szerint lehet csoportosítani:
$router = new RouteList;
$router->withDomain('example.com')
->addRoute('rss', 'Feed:rss')
->addRoute('<presenter>/<action>');
A domainnévben használhat vadjelzőket is:
$router = new RouteList;
$router->withDomain('example.%tld%')
// ...
Path Prefix
Az útvonalgyűjteményeket az URL-ben szereplő elérési útvonal szerint lehet csoportosítani:
$router = new RouteList;
$router->withPath('eshop')
->addRoute('rss', 'Feed:rss') // megfelel az URL-nek /eshop/rss
->addRoute('<presenter>/<action>'); // megfelel az URL-nek /eshop/<presenter>/<action>
Kombinációk
A fenti felhasználás kombinálható:
$router = (new RouteList)
->withDomain('admin.example.com')
->withModule('Admin')
->addRoute(/* ... */)
->addRoute(/* ... */)
->end()
->withModule('Images')
->addRoute(/* ... */)
->end()
->end()
->withDomain('example.com')
->withPath('export')
->addRoute(/* ... */)
// ...
A lekérdezési paraméterek
A maszkok tartalmazhatnak lekérdezési paramétereket is (az URL-ben a kérdőjel utáni paraméterek). Ezek nem határozhatnak meg érvényesítési kifejezést, de megváltoztathatják azt a nevet, amely alatt a bemutatónak átadják őket:
// a 'cat' lekérdezési paramétert 'categoryId'-ként használja az alkalmazásban
$router->addRoute('product ? id=<productId> & cat=<categoryId>', /* ... */);
Foo paraméterek
Most mélyebbre megyünk. A Foo paraméterek alapvetően névtelen paraméterek, amelyek lehetővé teszik a reguláris
kifejezésekkel való egyezést. A következő útvonal megfelel a /index
, /index.html
,
/index.htm
és /index.php
:
$router->addRoute('index<? \.html?|\.php|>', /* ... */);
Lehetőség van arra is, hogy explicit módon definiáljunk egy karakterláncot, amelyet az URL generálásához használunk.
A karakterláncot közvetlenül a kérdőjel után kell elhelyezni. A következő útvonal hasonló az előzőhöz, de a
/index
helyett a /index.html
címet generálja, mivel a .html
karakterláncot „generált
értékként“ állítja be.
$router->addRoute('index<?.html \.html?|\.php|>', /* ... */);
Integráció
Ahhoz, hogy a routerünket az alkalmazásba kapcsoljuk, tájékoztatnunk kell róla a DI konténert. A legegyszerűbb, ha
elkészítjük a gyárat, amely a router objektumot fogja felépíteni, és megmondjuk a konténer konfigurációjának, hogy
használja azt. Tegyük fel, hogy írunk egy metódust erre a célra 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;
}
}
Ezután beírjuk a konfigurációba:
services:
- App\Core\RouterFactory::createRouter
Az esetleges függőségeket, például az adatbázis-kapcsolatot stb., az autowiring segítségével paraméterként átadjuk a gyári metódusnak:
public static function createRouter(Nette\Database\Connection $db): RouteList
{
// ...
}
SimpleRouter
A Route Collectionnél sokkal egyszerűbb útválasztó a SimpleRouter. Ezt akkor
használhatjuk, ha nincs szükség egy adott URL formátumra, ha a mod_rewrite
(vagy alternatívák) nem állnak
rendelkezésre, vagy ha egyszerűen csak nem akarunk még a felhasználóbarát URL-ekkel bajlódni.
Nagyjából ilyen formában generál címeket:
http://example.com/?presenter=Product&action=detail&id=123
A SimpleRouter
konstruktor paramétere egy alapértelmezett bemutató és művelet, azaz a végrehajtandó
művelet, ha további paraméterek nélkül megnyitjuk pl. a http://example.com/
címet.
// alapértelmezett bemutató 'Home' és művelet 'default'
$router = new Nette\Application\Routers\SimpleRouter('Home:default');
Javasoljuk, hogy a SimpleRouter-t közvetlenül a konfigurációban definiáljuk:
services:
- Nette\Application\Routers\SimpleRouter('Home:default')
SEO és kanonizáció
A keretrendszer növeli a SEO-t (keresőmotor-optimalizálás) azáltal, hogy megakadályozza a tartalom duplikálódását a
különböző URL-címeken. Ha több cím hivatkozik ugyanarra a célpontra, pl. /index
és /index.html
,
a keretrendszer az elsőt határozza meg elsődlegesnek (kanonikusnak), és a többit 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 rontják az oldalrangsorukat. .
Ezt a folyamatot nevezzük kanonizációnak. A kanonikus URL az, amelyet az útválasztó generál, azaz a gyűjteményben az első megfelelő útvonal a OneWay jelző nélkül. Ezért a gyűjteményben először elsődleges útvonalakat sorolunk fel.
A kanonizálást a bemutató végzi, bővebben a kanonizálás fejezetben.
HTTPS
A HTTPS protokoll használatához aktiválni kell azt a tárhelyen, és konfigurálni kell a szervert.
A teljes webhely átirányítását HTTPS-re szerverszinten kell elvégezni, például az alkalmazásunk gyökérkönyvtárában lévő .htaccess fájl segítségével, 301-es HTTP-kóddal. A beállítások a tárhelytől függően eltérőek lehetnek, és valahogy így néz ki:
<IfModule mod_rewrite.c>
RewriteEngine On
...
RewriteCond %{HTTPS} off
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
...
</IfModule>
Az útválasztó ugyanolyan protokollal generál egy URL-t, mint amilyen protokollal 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ő protokollok alatt különböző útvonalakat futtassunk, akkor ezt az útvonalmaszkban fogjuk megadni:
// HTTP-címet generál
$router->addRoute('http://%host%/<presenter>/<action>', /* ... */);
// HTTPS-címet generál
$router->addRoute('https://%host%/<presenter>/<action>', /* ... */);
Debugging Router
A Tracy Barban megjelenő útválasztó sáv egy hasznos eszköz, amely megjeleníti az útvonalak listáját, valamint az útválasztó által az URL-ből kapott paramétereket.
A ✓ szimbólummal ellátott zöld sáv az aktuális URL-nek megfelelő útvonalat jelzi, a ≈ szimbólummal ellátott kék sávok pedig azokat az útvonalakat jelzik, amelyek szintén megfelelnének az URL-nek, ha a zöld nem előzné meg őket. Továbbra is látjuk az aktuális előadót & akciót.
Ugyanakkor, ha a kanonikalizálás miatt váratlan átirányítás történik, hasznos megnézni az átirányítás sávot, hogy lássuk, hogyan értette eredetileg az útválasztó az URL-t, és miért irányított át.
Az útválasztó hibakeresésekor ajánlott megnyitni a böngészőben a Fejlesztői eszközök eszközeit (Ctrl+Shift+I vagy Cmd+Option+I), és letiltani a gyorsítótárat a Hálózat panelen, hogy az átirányítások ne tárolódjanak benne.
Teljesítmény
Az útvonalak száma befolyásolja az útválasztó sebességét. Számuk semmiképpen sem haladhatja meg a néhány tucatot. Ha webhelye túlságosan bonyolult URL-struktúrával rendelkezik, írhat egy egyéni útválasztót.
Ha az útválasztónak nincsenek függőségei, például egy adatbázistól, és a gyárának nincsenek argumentumai, akkor a lefordított formáját közvetlenül egy DI konténerbe szerializálhatjuk, és így az alkalmazást valamivel gyorsabbá tehetjük.
routing:
cache: true
Egyéni útválasztó
A következő sorok nagyon haladó felhasználóknak szólnak. Létrehozhatja saját útválasztóját, és természetesen hozzáadhatja az útvonalgyűjteményéhez. Az útválasztó 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 az aktuális $httpRequest-et, amelyből nem csak az URL, hanem a
fejlécek stb. is kinyerhetők, egy tömbben dolgozza fel, amely a bemutató nevét és paramétereit tartalmazza. Ha nem tudja
feldolgozni a kérést, akkor null értéket ad vissza. A kérés feldolgozásakor legalább a prezentert és az actiont kell
visszaadnunk. A prezenter neve teljes, és tartalmazza az esetleges modulokat:
[
'presenter' => 'Front:Home',
'action' => 'default',
]
A constructUrl
módszer ezzel szemben abszolút URL-t generál a paraméterek tömbjéből. Használhatja a
$refUrl
paraméterből származó információt, amely az aktuális URL.
Egyéni útvonal hozzáadásához az útvonalkollekcióhoz a add()
használatával:
$router = new Nette\Application\Routers\RouteList;
$router->add($myRouter);
$router->addRoute(/* ... */);
// ...
Elkülönített használat
A szeparált használat alatt a router képességeinek olyan alkalmazásban történő használatát értjük, amely nem használja a Nette alkalmazást és a prezentereket. Szinte minden, amit ebben a fejezetben bemutattunk, vonatkozik rá, a következő különbségekkel:
- az útvonalgyűjteményekhez az osztályt használjuk Nette\Routing\RouteList
- egyszerű útválasztó osztályként Nette\Routing\SimpleRouter
- mivel nincs
Presenter:action
pár, a Advanced jelölésthasználjuk.
Tehát ismét létrehozunk egy metódust, amely létrehoz egy útválasztót, például:
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álsz, amit ajánlunk, add hozzá a metódust ismét a konfigurációhoz, majd a HTTP-kérelemmel együtt kapd meg a routert a konténerből:
$router = $container->getByType(Nette\Routing\Router::class);
$httpRequest = $container->getByType(Nette\Http\IRequest::class);
Vagy közvetlenül hozzuk létre az objektumokat:
$router = App\Core\RouterFactory::createRouter();
$httpRequest = (new Nette\Http\RequestFactory)->fromGlobals();
Most hagynunk kell, hogy a router működjön:
$params = $router->match($httpRequest);
if ($params === null) {
// nem találtunk megfelelő útvonalat, 404-es hibát küldünk.
exit;
}
// feldolgozzuk a kapott paramétereket
$controller = $params['controller'];
// ...
És fordítva, az útválasztót fogjuk használni a kapcsolat létrehozására:
$params = ['controller' => 'ArticleController', 'id' => 123];
$url = $router->constructUrl($params, $httpRequest->getUrl());