contributte / planette-site

💀 [DISCONTINUED] All the roads go through the Planette
https://planette.vercel.app
MIT License
9 stars 3 forks source link

2015-04-24: route-deklarace-parametru-obsahujici-lomitka #43

Open paveljanda opened 7 years ago

paveljanda commented 7 years ago

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 (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):

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 .*?.

paveljanda commented 7 years ago

author: 3363 ()