Nette Framework
  • Úvodní stránka
  • Download
  • Dokumentace
  • Fórum
  • Blog
  • Přispějte
  • Quick Start
    • Začínáme
    • Adresářová struktura
    • Vytvoření presenteru
    • Připojení šablony
    • Tvorba odkazů
    • Hezčí šablony
    • Zobrazení tabulky
    • Stránkování a řazení
    • Tvoříme komponentu
  • Nette\Annotations
  • Nette\Application
    • Application
    • AppForm
    • Control
    • Presenter
    • PresenterCompo­nent
    • PresenterRequest
    • Routování
    • MultiRouter
    • Route
    • SimpleRouter
  • Nette\Caching
  • Nette\Component
  • Nette\Debug
    • Základy
    • Logování chyb
    • Firebug
  • Nette\Environment
  • Nette\Forms
  • Nette\IO\SafeS­tream
  • Nette\Loaders
  • Nette\Object
  • Nette\Security
    • Bezpečnost aplikací
    • Identity
    • SimpleAuthenti­cator
    • Permission
    • Dynamická správa rolí a zdrojů
  • Nette\String
  • Nette\Templates
    • Template
    • Template Filters
    • Template Helpers
  • Nette\Web\Html
  • Nette\Web\HttpR­equest
  • Nette\Web\HttpR­esponse
  • Nette\Web\Session
  • Nette\Web\User
Naposledy změněno 21. 11. 2008 Edituj Historie Poslední změny

Nette\Applica­tion\Route

Úkolem routy je nejen URL adresu naparsovat a vytvořit z ní interní požadavek, ale i přesný opak – z interního požadavku vygenerovat URL.

Třída Route implementující rozhraní IRouter je nástrojem pro tvorbu user-friendly URL adres. Že nejde o nic složitého se můžete přesvědčit sami níže.

Definice cest

Prvním parametrem při tvorbě routy je maska cesty. Ta může být doplněna o validační podmínky ve formě klasických regulárních výrazů. Druhým parametrem je pole výchozích a fixních hodnot.

// akceptuje URL cestu ve tvaru např. admin/edit/10 nebo catalog/
$router[] = new Route('<presenter>/<view>/<id [0-9]+>', array(
    'presenter' => 'Article',
    'view' => 'show',
    'id' => NULL,
));

Příklad ukazuje masku sestávající se ze tří parametrů, přičemž všechny jsou volitelné, neboť mají definovánu výchozí hodnotu. Parametr id má navíc specifikovánu validační podmínku [0-9]+, tj. akceptuje jen číslo (u ostatních parametrů je použita výchozí podmínka [^/]+).

Definice rout obvykle umístímě do souboru bootstrap.php:

$application = Environment::getApplication();
$router = $application->getRouter();

// nebo all-in-one row
$router = Environment::getApplication()->getRouter();

// vytvoření jednosměrné routy, která bude odchytávat
// všechny dotazy směrující na index.php
// a přesměrovávat na routu níže do cool-url tvaru
// automaticky zohledňuje SEO,
// takže se vám tyto stránky nezaindexují dvakrát
$router[] = new Route('index.php', array(
    'presenter' => 'Article',
    'view' => 'show',
), Route::ONE_WAY);

// deklarace obecné dvousměrné routy s cool-url tvarem
$router[] = new Route('<presenter>/<view>/<id>', array(
    'presenter' => 'Article',
    'view' => 'show',
    'id' => NULL,
));

// vytvoříme odkaz
$presenter->link('Article:'); // ekvivalentní s Article:show

Routa s maskou index.php určuje, že při požadavku na stránku index.php se otevře presenter Article a pohled show. Příznak Route::ONE_WAY (jednosměrka) zajistí, že routa může požadavek přijmout (stránka index.php existuje), ale aplikace takové URL nevytvoří. Tedy při generování URL pro presenter Article a pohled show se použije vhodná následující routa.

Jednosměrné routy se používají třeba pro zachování zpětné kompatibility – pokud na web již existují odkazy ve tvaru http://example.com/index.php, budou tyto nadále funkční. Navíc dojde k automatickému přesměrování na nový tvar URL.

Má-li být parametrem routy cesta filesystému, pak maskou .*? povolíme všechny znaky včetně lomítek. Například: new Route('/storage/<path .*?>', ...)

V případě nenalezení routy se vyhodí výjimka.
Pokud se žádná routa nenastaví, tak se o správné chování postará automaticky SimpleRouter.

Uvnitř aplikace se odkazuje tak, jako když jsou volány metody v OOP: Presenter::view($arg1, $arg2). Konrétně třeba Product:detail($id). Voláme metodu detail třídy Product a předáme jí parametr $id. Podrobně je filosofie routování popsána v jiném článku.

Foo parametry

Foo parametry rozšiřují možnosti definice rout. Narozdíl od klasických parametrů nemají název (místo něj se použije otazník), nepředávají se presenteru a slouží k tomu, aby bylo možné do masky přidat regulární výraz.

Příklad: jednosměrná routa akceptující index.html, index.htm a index.php.

$router[] = new Route('index<? \.html?|\.php>', array(
        'presenter' => 'Homepage',
        'view' => 'default',
), Route::ONE_WAY);

Pokud by uvedená routa byla obousměrná, generovala by cestu index, kterou však sama neumí akceptovat. Výraz by se proto musel rozšířit i o prázdnou hodnotu na 'index<? \.html?|\.php|>'.

Nebo lze explicitně definovat řetězec, který bude při generování cesty použit (obdoba výchozí hodnoty u skutečných parametrů). Řetězec se vloží ihned za otazník:

$router[] = new Route('feed<?.xml \.xml|>', array(
        'presenter' => 'Feed',
        'view' => 'rss',
));

Tato routa akceptuje cesty feed.xml a feed, přičemž generuje feed.xml.

Používání rout/odkazů v šablonách

Rozlišujeme více možností vytvoření odkazu, proto není jedno na jakém objektu metodu link() voláme. Jelikož view může měnit pouze presenter, komponenty pracují vždy pod tímto prahem. Navíc se prohledávají odkazy v hierarchii směrem dolů k potomkům. Tudíž $component->link() vede na signál, $presenter->link() obvykle na view (nebo signál, je-li označen vykřičníkem). Pro úplnost, i komponenta může volat $this->presenter->link('view').

V šabloně se odkazy velmi často vytvářejí (příklad s využitím filtru curlyBrackets):

<a href="{$presenter->link('edit', 10)}">self::edit(10)</a>
<a href="{$presenter->link('Product:list')}">Product::list()</a>

<a href="{$control->link('Article:view')}">Zobrazit články</a>     // jedna z možností
<a href="{$presenter->link('Article:view')}">Zobrazit články</a>   // další z možností
<a href="{$component->link('Article:view')}">Zobrazit články</a>   // a do třetice

// jiná možnost: použít všechny možnosti filtru curly brackets

<a href="{link Article:view}">Zobrazit články</a>      // control link
<a href="{plink Article:view}">Zobrazit články</a>     // presenter link
<a href="{ajaxlink Article:view}">Zobrazit články</a>  // ajax link / subrequest

Experimentálně lze využít i filtr netteLinks:

<a href="nette:edit?id=10">self::edit(10)</a>
<a href="nette:Product:list">Product::list()</a>

URL generuje v presenteru (a komponentě) funkce $this->link('edit', 10) – tedy stejně jako v šabloně. Lze vygenerovat URL sám na sebe $this->backlink(). K přesměrování slouží $this->redirect(...), k přechodu na jiný presenter/view $this->forward(...). Rozdíl je v tom, že redirect provede přesměrování na jinou stránku pomocí HTTP a forward jen přepošle zpracování jinam.

Odkaz na jiný presenter

Pro odkazování se do jiného než aktuálního presenteru se používá zápis ve tvaru:
$link->(destination [,arg [,arg ...]]) kde destination je:

  • 'anotherView' (odkaz na aktuální presenter a anotherView)
  • 'AnotherPresenter:anotherView' (odkaz na AnotherPresenter a anotherView)
  • 'AnotherPresenter:' (ozkaz na AnotherPresenter a výchozí view 'default')
  • 'AnotherModule:Presenter:view' (odkaz do jiného modulu)

Viz také:

  • Fully qualified view

Dynamické přidávání rout

Nyní si ukážeme, jak zaroutovat do naší aplikace nějaký existující modul.

Dejme tomu, že do website programované v Nette chceme přidat fórum. Stačí, aby fórum disponovalo instalační funkcí createRoutes():

class Forum
{
    function createRoutes($router, $prefix)
    {
        $router[] = new Route($prefix . 'index.php', array(
            'presenter' => 'Forum:Homepage',
            'view' => 'default',
        ));
        $router[] = new Route($prefix . 'admin.php', array(
            'presenter' => 'Forum:Admin',
            'view' => 'default',
        ));
        ...
    }
}

„Zaroutování“ fóra do existující aplikace je pak velmi jednoduché. bootstrap.php:

$router = $application->getRouter();
// přidáme své routy
...
// přidáme modul forum
Forum::createRoutes($router, '//forum.example.com/');

Multijazyčnost

Nette Framework nikomu nevnucuje konkrétní řešení. Otázkou mnohých složitějších systémů je multijazyčnost. Základem k jejímu vyřešení je dobrý návrh rout. Možností jak vyřešit tento požadavek je spostu a vše záleží jen na Vaší představivosti. Můžete se inspirovat na pár příkladech:

// nejjednodušší způsob řešení
$router[] = new Route('/article/<id>', array(
    'presenter' => 'Article',
    'lang' => 'en',
));

$router[] = new Route('/clanek/<id>', array(
    'presenter' => 'Article',
    'lang' => 'cs',
));

// další z možností: název jazyka ve tvaru doménu 3. řádu
$router[] = new Route('//<lang {?cs|en}>.example.com/<id>/<view>', array( ... ), Route::ONE_WAY);
$router[] = new Route('//<lang [a-z]{2}>.example.com/<id>/<view>', array( ... ), Route::ONE_WAY);


// další možnost: povinné a volitelné parametry
// - module je zadán a není v masce => fixní
// - lang není zadán a podléhá masce => povinný
$router[] = new Route('<lang [a-z]{2}>/<id>/<view>', array(
     'module' => 'Front',
     'presenter' => 'Homepage',
     'view' => 'default',
     'id' => NULL // takto definovaný parametr je volitelný
));
// poté někde ve startup() zavoláme: $this->lang = $this->getParam('lang');

Viz také:

  • Routování
  • Fórum: Příklady routeru
  • Fórum: Routovací tipy a triky
« MultiRouter SimpleRouter »

Nette Framework powered | dibi powered | Texy! powered | Institut Školení PHP