Routování, jak docílit těchto tvarů
- Jirda
- Člen | 103
Zdravím všechny,
ve svém prázdninovém tažení po tajích nette jsem konečně došel k routám. Ale nevím si rady, jak co nejefektivněji napsat routy, pokud chci docílit takovýchto tvarů:
Předvedu nějaké příklady:
- domena.cz/user/jirda/
User:default … id=jirda
- domena.cz/user/change-password/
User:changePassword
- domena.cz/product/hp-notebook/
product:default … id=hp-notebook
- domena.cz/product/edit/hp-notebook/ nebo domena.cz/product/hp-notebook/edit/
(je mi jedno, na ktere z techto pozic bude edit)
product:edit … id=hp-notebook
- domena.cz/product/info/
product:info
Snažil jsem se napsat více příkladů, aby bylo jasnější o co mi jde.
Možná by se to dalo shrnout takto:
- Nechci, aby se jakkoli v adrese zobrazil default (viz. 1. a 3. příklad)
- Pokud možno nniverzálně, ne psát routy zvlášť pro každý presenter
- Předejít situaci, kdy by mohlo třeba v příkladě 2 dojít k volání User:default s id=change-password
Jak jsem bojoval já?
<?php
$router[] = new Route('<presenter>/<id>/', array(
'presenter' => 'Default',
'action' => 'default',
'id' => null,
));
$router[] = new Route('<presenter>/<action>/<id>/', array(
'presenter' => 'Default',
'action' => 'default',
'id' => null,
));
?>
Těmto routám vyhovoval:
- domena.cz/user/jirda/
User:default … id=jirda
- domena.cz/product/hp-notebook/
product:default … id=hp-notebook
- domena.cz/product/edit/hp-notebook/
product:edit … id=hp-notebook
Nevyhovoval:
- domena.cz/user/change-password/
místo User:changePassword došlo k User:default … id=change-password
- domena.cz/product/info/
místo product:info došlo k Product:info … id=info
Je mi vcelku jasné, proč dochází k tomu, že tyto tvary adres nesplní to, co bych chtěl. Bohužel ale nevím, jak pokrýt všechny podoby adres, které jsem prezentoval a to především co nejefektivněji s minimálním počtem rout.
Závěrem se omlouvám za trochu delší příspěvek, ale snažil jsem se, aby byl co nejobsáhlejší a aby se v něm (snad) dalo dobře zorientovat.
Děkuji všem, za jejich případné rady.
- Jan Tvrdík
- Nette guru | 2595
Napadají mě dvě možnosti: 1. Napsat si vlastní router (ideální varianta, tak jsem to řešil já) 2. Přidat manuální routy
$router[] = new Route('user/change-password/', array(
'presenter' => 'User',
'action' => 'changePassword',
));
- Ondřej Mirtes
- Člen | 1536
No, musíš routeru dát vědět, že neexistuje uživatel s ID
change-password
a product s ID info
(a zajistit
v administraci, aby takové položky nešly do databáze přidat).
Určitě ti tu někdo navrhne vytvoření vlastního routu (k čemuž jsem se zatím neodvážil), já podobný problém řešil nějak takto (snad jsem se nijak neuklepl, nezkoušel jsem to):
$routingModel = new Models\RoutingModel(); //cached
//matches username
$router[] = new Route('user/<id ' . implode('|', $routingModel->getUsers()) . '>/', array(
'presenter' => 'User',
'action' => 'default',
));
//matches product (also its editing)
$router[] = new Route('product/<id ' . implode('|', $routingModel->getProducts()) . '>/<action>', array(
'presenter' => 'Product',
'action' => 'default',
));
//matches everything else (general route)
$router[] = new Route('<presenter>/<action>/<id>/', array(
'presenter' => 'Default',
'action' => 'default',
'id' => NULL,
));
Ty metody routing modelu vrací jednoduché pole s jednotlivými položkami databáze, aby se vytvořil vzor pro routu v tomto tvaru:
'user/<id jarda|pepa|franda>/'
- Jirda
- Člen | 103
Jan Tvrdík napsal(a):
Napadají mě dvě možnosti: 1. Napsat si vlastní router (ideální varianta, tak jsem to řešil já) 2. Přidat manuální routy
$router[] = new Route('user/change-password/', array( 'presenter' => 'User', 'action' => 'changePassword', ));
Myslíš ten, co jsi prezentoval zde ?
- Jan Tvrdík
- Nette guru | 2595
Jirda napsal(a):
Myslíš ten, co jsi prezentoval zde ?
Tak přesně ten jsem nemyslel, ale měl by fungovat, akorát budeš muset použít jeho rozšířenou variantu + případně i upravit celý router, pokud nechceš tu action=edit za otazníkem.
- Jirda
- Člen | 103
Jan Tvrdík napsal(a):
Jirda napsal(a):
Myslíš ten, co jsi prezentoval zde ?
Tak přesně ten jsem nemyslel, ale měl by fungovat, akorát budeš muset použít jeho rozšířenou variantu + případně i upravit celý router, pokud nechceš tu action=edit za otazníkem.
Ještě mě napadla třetí možnost a to v případě, že detekuji stav, kdy je třeba id rovno change-password, tak dojde k zavolání daného view. De facto by došlo k situaci, kdy bych si v defaultu vytvořil takový mini router pro presenter. Akorát si myslím, že takové řešení by nebylo moudré a začalo by mě unášet někam, kam bych neměl jít.
Co se týše ale toho manuálního nastavení, tam nevidím problém tolik
s realizaci, ale spíše se obávám té osudné věty v dokumentaci:
Počet rout má vliv na rychlost aplikace, zejména při generování
odkazů.
Editoval Jirda (31. 7. 2009 23:52)
- Jirda
- Člen | 103
LastHunter napsal(a):
No, musíš routeru dát vědět, že neexistuje uživatel s ID
change-password
a product s IDinfo
(a zajistit v administraci, aby takové položky nešly do databáze přidat).Určitě ti tu někdo navrhne vytvoření vlastního routu (k čemuž jsem se zatím neodvážil), já podobný problém řešil nějak takto (snad jsem se nijak neuklepl, nezkoušel jsem to):
$routingModel = new Models\RoutingModel(); //cached //matches username $router[] = new Route('user/<id ' . implode('|', $routingModel->getUsers()) . '>/', array( 'presenter' => 'User', 'action' => 'default', )); //matches product (also its editing) $router[] = new Route('product/<id ' . implode('|', $routingModel->getProducts()) . '>/<action>', array( 'presenter' => 'Product', 'action' => 'default', )); //matches everything else (general route) $router[] = new Route('<presenter>/<action>/<id>/', array( 'presenter' => 'Default', 'action' => 'default', 'id' => NULL, ));
Ty metody routing modelu vrací jednoduché pole s jednotlivými položkami databáze, aby se vytvořil vzor pro routu v tomto tvaru:
'user/<id jarda|pepa|franda>/'
Zajímavé řešení, ale říkám si, co když je třeba 1000 uživatelů. Jak to pak ovlivní rychlost?
- Jan Tvrdík
- Nette guru | 2595
Jirda napsal(a):
Ještě mě napadla třetí možnost a to v případě, že detekuji stav, kdy je třeba id rovno change-password, tak dojde k zavolání daného view. De facto by došlo k situaci, kdy bych si v defaultu vytvořil takový mini router pro presenter. Akorát si myslím, že takové řešení by nebylo moudré a začalo by mě unášet někam, kam bych neměl jít.
Není to sice čisté z hlediska návrhu, ale určitě to bude fungovat.
Místo změny view je vhodné použít $this->forward
.
Co se týše ale toho manuálního nastavení, tam nevidím problém tolik s realizaci, ale spíše se obávám té osudné věty v dokumentaci:
Počet rout má vliv na rychlost aplikace, zejména při generování odkazů.
Tak zrovna toho bych se nebál. I kdyby jsi těch statických rout měl 10,
tak to na výkonu nepoznáš (schválně to zkus změřit). Pokud by jsi to
chtěl super rychlé, tak lze vytvořit speciální StaticRoute
,
který bude ještě rychlejší (i když téměř neměřitelně).
- Jirda
- Člen | 103
Jan Tvrdík napsal(a):
Jirda napsal(a):
Ještě mě napadla třetí možnost a to v případě, že detekuji stav, kdy je třeba id rovno change-password, tak dojde k zavolání daného view. De facto by došlo k situaci, kdy bych si v defaultu vytvořil takový mini router pro presenter. Akorát si myslím, že takové řešení by nebylo moudré a začalo by mě unášet někam, kam bych neměl jít.
Není to sice čisté z hlediska návrhu, ale určitě to bude fungovat. Místo změny view je vhodné použít
$this->forward
.Co se týše ale toho manuálního nastavení, tam nevidím problém tolik s realizaci, ale spíše se obávám té osudné věty v dokumentaci:
Počet rout má vliv na rychlost aplikace, zejména při generování odkazů.Tak zrovna toho bych se nebál. I kdyby jsi těch statických rout měl 10, tak to na výkonu nepoznáš (schválně to zkus změřit). Pokud by jsi to chtěl super rychlé, tak lze vytvořit speciální
StaticRoute
, který bude ještě rychlejší (i když téměř neměřitelně).
Dobře, ještě to promyslím, jakým směrem se uberu. Ale i tak, díky!
- Patrik Votoček
- Člen | 2221
Přidávám se k možnosti kde máš pár krajních stavů
(change-password
, edit
) udělat statické routy
přesně pro tyto případy. Moc to aplikaci nezpomalí a pro dynamická data
nechat dynamické routy. Sám to tak řeším.
- Oggy
- Člen | 306
Mám takový dotaz..
dejme tomu,že máme v db strukturu webu..nějak takto: id,url,presenter
potom bych viděl možné řešení s url např. takto
<?php
$sekce = new Sekce();
Route::addStyle('#presenter', presenter);
Route::setStyleProperty('#presenter', Route::FILTER_IN, array($sekce,'getPresenterName'));
$router[] = new Route('<presenter #presenter>/<action>/<id>', array(
'module' => 'Front',
'presenter' => 'Home',
'action' => 'default',
'id' => NULL,
));
?>
kde getPresenterName podle url vrátí který presenter se má volat..
čekal bych že pokud zavolám
doména/neco (stránku neco = presenter např. Product)
url bude ve tvaru doména/něco a filtr mi vrátil presenter Product.. který
bude zavolán
ale stále se v url dostávám na tvar:
doména/product ..
nevím, kde dělám chybu..nebo překladový slovník na tohle nelze použít?
- Jan Tvrdík
- Nette guru | 2595
Nechce se mi nad tím přemýšlet, ale téměř určitě je potřeba
použít i Router::FILTER_OUT
.
Editoval Jan Tvrdík (30. 8. 2009 0:54)
- Oggy
- Člen | 306
Jan Tvrdík napsal(a):
Nechce se mi nad tím přemýšlet, ale téměř určitě je potřeba použít i
Router::FILTER_OUT
.
To já ale nepotřebuji.. nebo dsi to moc nedokáži představit..většinu stránek bude „obhospodařovat“ jeden presenetr..např. page.. a pak by bylo pár jiných..Home, Product nebo něco jiného.. tzn.. funkce podle presenteru vrať url by nešla.. není to 1:1
edit:
tak jsem trošku experimentoval..a do filtr out jsem dal stejnou fci..getPresenterName .. a url už je ve správném tvaru..ale teď to nemůže najít odpovídající routu..
url: neco.cz/vrtulnik/objednavka/1
chyba: No route for Front:Page:objednavka(id=1)
routa:
<?php
$router[] = new Route('<presenter>/<action>/<id>', array(
'module' => 'Front',
'presenter' => 'Home',
'action' => 'default',
'id' => NULL,
));
?>
Editoval Oggy (30. 8. 2009 8:03)