Tento článek ukazuje, jak vytvořit routu, která akceptuje lomítka v url, například pro stahování souborů nebo hiarchickou navigaci. Využijeme k tomu třídu Nette\Application\Route.
Vychází z tohoto tématu na fóru. Také se snažím vysvětlit rozdíly mezi jednotlivými zápisy a vysvětlit trochu práci s metadaty parametrů třídy Route.
Cíl
Chceme, aby URL http://server.com/produkty/elektro/zarovky/ se přeložilo na Nette\Application\PresenterRequest s parametry:
|Presenter| Page
|action| default
|node| produkty/elektro/zarovky/
Bohužel to nyní nejde. Pohledem do api Nette\Application\Route::$styles zjistíme, že výchozí nastavení (styl) pro parametry v cestě(kromě presenter, action a parametrů v querystringu) má metadata, která se nehodí pro náš parametr.
-výchozí vzor=PATTERN ([^/]+) neakceptuje lomítka. Na vhodném místě v kódu ho měníme ho tedy na .*
-Ani tak to nebude fungovat -- lomítka se totiž převedou na %2F -- díky FILTER_OUT (rawurlencode). Taktéž na vhodném místě změníme funkci: na funkci, která vrací řetězec, který dostane (function($s){return $s;}). Ovšem pokud místo funkce uvedeme null, tak dosáhneme stejného efektu.
Připomenu, co to jsou metadata. To jsou de facto vlastnosti daného PARAMETRu v Routě.
Jsou to tyto
význam
zápis
hodnota konstanty
datový typ
výchozí hodnota
*Route::VALUE
value
string
regulerní výraz
*Route::PATTERN
pattern
string
vstupní filtr (transfomuje parametr z url na parametr PresenenterReqeustu)
*Route::FILTER_IN
filterIn
funkce
výstupní filtr (transformuje parametr z Pres.Req. na param v url)
*Route::FILTER_OUT
filterOut
funkce
filtrovací(překladová) tabulka (kombinace a zjednodušení předchozích dvou - klíče jsou, to co se zadá do url, a hodnoty, co dostane PresenterRequest)
*Route::FILTER_TABLE
filterTable
pole
interní - nepoužívat (určuje zda je povinný parametr, v naprosté většině případů není potřeba)
není,
fixity
Ty se uvádějí těmito způsoby(pro parametry v query stringu platí jinačí pravidla):
v definici parametru v masce přímo v ostrých závorkách <PARAMETR[=VALUE] [PATTERN] [#class]> Class popíšu dále,
tímto způsobem nelze přímo v masce určit filtry a překladovku.
v druhém parametru konstruktoru Route, což je pole(jmenuje se $metadata), kde klíče jsou názvy PARAMETRů. Dále se to liší, zda je hodnotou pole nebo string.
pole: 'node'=>array(Route::VALUE=>...,Route::FILTER_TABLE=>...). Danému parametru přiřazujeme metadata z tabulky výše.
jako podmožnost uvádím, kdy metadata se určí staticky pro daný parametr. Viz možnost 3.
string:pokud uvedeme 'node'=>"about-us", tak se to pokládá za výchozí hodnotu. Jinými slovy se to převede na 'node'=>array(Route::VALUE=>"about-us")
Pomocí class: class neboli styl jsou defacto připravená sada hodnot VALUE, PATTERN, FILTRů nebo překladové tabulky. Její ukázka bude v 4. možnosti.
Pozor: gramaticky se deklarace stylu liší jen o křížek, ale možnost bez křížku platí pro daný parametr zatímco s křížkem platí pro parametry, které označíme takto: <jmeno #style1>/<akce #style1>
Totéž, jen filtr změníme na null. Taky pattern . je nahrazen .?, takže zmizí poslední lomítko.
$router[] = new Route("<node>", array(
"presenter" => "Page",
"action" => "default",
"node" => array(
Route::FILTER_OUT => NULL, // to má stejný efekt: přebije se výchozí hodnota rawurlencode,
// ale nevyhoví podmínce isset(), tudíž se parametr nezmění
Route::PATTERN => ".*?",
),
));
2)
PATTERN jsme přesunuli rovnou do deklarace masky. Stejná funkčnost.
Tento článek ukazuje, jak vytvořit routu, která akceptuje lomítka v url, například pro stahování souborů nebo hiarchickou navigaci. Využijeme k tomu třídu Nette\Application\Route.
Vychází z tohoto tématu na fóru. Také se snažím vysvětlit rozdíly mezi jednotlivými zápisy a vysvětlit trochu práci s metadaty parametrů třídy Route.
Cíl
Chceme, aby URL
http://server.com/produkty/elektro/zarovky/
se přeložilo na Nette\Application\PresenterRequest s parametry: |Presenter| Page |action| default |node|produkty/elektro/zarovky/
Začínáme
Nastavíme router. Zkusíme toto:
Jen připomenu část citátu : "but still voodoo"
Bohužel to nyní nejde. Pohledem do api Nette\Application\Route::$styles zjistíme, že výchozí nastavení (styl) pro parametry v cestě(kromě presenter, action a parametrů v querystringu) má metadata, která se nehodí pro náš parametr. -výchozí vzor=PATTERN ([^/]+) neakceptuje lomítka. Na vhodném místě v kódu ho měníme ho tedy na .* -Ani tak to nebude fungovat -- lomítka se totiž převedou na %2F -- díky FILTER_OUT (rawurlencode). Taktéž na vhodném místě změníme funkci: na funkci, která vrací řetězec, který dostane (function($s){return $s;}). Ovšem pokud místo funkce uvedeme null, tak dosáhneme stejného efektu.
Ty se uvádějí těmito způsoby(pro parametry v query stringu platí jinačí pravidla):
<PARAMETR[=VALUE] [PATTERN] [#class]>
Class popíšu dále,'node'=>"about-us"
, tak se to pokládá za výchozí hodnotu. Jinými slovy se to převede na'node'=>array(Route::VALUE=>"about-us")
Pozor: gramaticky se deklarace stylu liší jen o křížek, ale možnost bez křížku platí pro daný parametr zatímco s křížkem platí pro parametry, které označíme takto: <jmeno #style1>/<akce #style1>
Viz Nette\Application\Route::VALUE
Řešení
Vždy sledujeme, abychom nastavili dvě věci: PATTERN .* a FILTER_OUT.
1)
Uvedeme obojí v poli metadata.
1a)
Totéž, jen filtr změníme na null. Taky pattern . je nahrazen .?, takže zmizí poslední lomítko.
2)
PATTERN jsme přesunuli rovnou do deklarace masky. Stejná funkčnost.
3)
Poznámka: Místo
Route::$styles['node'] = ...
se spíš používá Route::addStyle() a Route::setStyleProperty().Deklarujeme metadata pro parametr node "předem".
4)
Deklarujeme styl #raw, který potom použijeme pro node.
Pokud chcete, aby cesta nekončila lomítkem, tak místo
.*
pište.*?
.