Route – deklarace parametru obsahující lomítka
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:
$Ro[] = new Route("<node>", array(
"presenter" => "Page",
"action" => "default",
));
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. Taktéž na vhodném místě změníme funkci: na funkci, která vrací řetězec, který dostane. 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 | Route::FILTER_IN | filterIn | funkce |
| výstupní filtr | Route::FILTER_OUT | filterOut | funkce |
| filtrovací(překladová) tabulka | Route::FILTER_TABLE | filterTable | pole |
| interní – nepoužívat | 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")
- pole:
‚node‘=>array(Route::VALUE=>…,Route::FILTER_TABLE=>…). Danému
parametru přiřazujeme metadata z tabulky výše.
- 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>
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.
$router[] = new Route("<node>", array(
"presenter" => "Page",
"action" => "default",
"node" => array(
Route::FILTER_OUT => function ($uri) { return $uri; },
Route::PATTERN => ".*",
),
));
1a)
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.
$router[] = new Route("<node .*>", array(
"presenter" => "Page",
"action" => "default",
"node" => array(
Route::FILTER_OUT => NULL,
),
));
3)
Poznámka: Místo Route::$styles['node'] = ... se spíš
používá Route::addStyle() a Route::setStyleProperty().
Deklarujeme metadata pro parametr node „předem“.
Route::$styles['node'] = array(
Route::FILTER_OUT => null,
Route::PATTERN => ".*?",
);
$router[] = new Route("<node>", array(
"presenter" => "Page",
"action" => "default",
));
4)
Deklarujeme styl #raw, který potom použijeme pro node.
Route::$styles['#raw'] = array(
Route::FILTER_OUT => null,
Route::PATTERN => ".*?",
);
$router[] = new Route("<node #raw>", array(
"presenter" => "Page",
"action" => "default",
));
Pokud chcete, aby cesta nekončila lomítkem, tak místo
.* pište .*?.
HosipLan | 10. 3. 2011, 15:22 | comment
Šikovný přehled :)
Víš, že David někde psal, že nedoporučuje používat styly, protože budou deprecated? nebo tak něco…