SimpleSeoRouter
- Jan Tvrdík
- Nette guru | 2595
Jak jsem již psal, tak
při používání pěkných URL nerad používám třídu Route, protože
presenter pak dostane např. řetězec moje-stránka
místo např.
čísla 7
(představující ID stránky v DB). Proto jsem si pro
tyto účely napsal vlastní velmi jednoduchý router.
Zdrojový kód
Příklad použití
Struktura tabulky galleries
Sloupec | Typ | Nulový | Výchozí |
---|---|---|---|
id | int(3) | Ano | NULL |
name | varchar(100) | Ano | |
description | varchar(1000) | Ano | NULL |
url | varchar(100) | Ano |
Příklad routeru
Registrace v bootstrapu
Těším se na případnou kritiku a někdy příště se možná podíváme na další příklad routeru.
Editoval Jan Tvrdík (19. 5. 2009 16:35)
- Honza Marek
- Člen | 1664
Ono se to musí kouknout při každém generování odkazu do databáze, jestli tomu dobře rozumim. Zajímalo by mě, jestli je to poznat na rychlosti nebo ne. Jinak se mi to hodně líbí a ty abstraktní metody se dají koneckonců naimplementovat jinak.
- jasir
- Člen | 746
Honza M. napsal(a):
Ono se to musí kouknout při každém generování odkazu do databáze, jestli tomu dobře rozumim. Zajímalo by mě, jestli je to poznat na rychlosti nebo ne. Jinak se mi to hodně líbí a ty abstraktní metody se dají koneckonců naimplementovat jinak.
Jo, vypadá to moc hezky. Jinak bych řekl, že je to adept na caching :)
- Honza Marek
- Člen | 1664
Já tohle řešil tak, že jsem na začátku načetl všechny stránky a to hodil do pole.
- Jan Tvrdík
- Nette guru | 2595
ad Caching: čekal jsem, že se někdo zeptá :) Záleží na počtu url adres, které se musí na běžné stránce vygenerovat. Pokud je jich jen pár, tak nemá cachování smysl, protože ty dotazy jsou vysloveně ukázkou vysokorychlostních dotazů.
Pokud by se však generoval na jedné stránce větší množství url adres, tak se cache určitě vyplatí.
Osobně jsem zatím jednoúrovňový router použil jenom v takových situacích, že cachování nemělo smysl. U víceúrovňového routeru jsem se ale cachování nevyhnul.
- Jan Tvrdík
- Nette guru | 2595
Jsem první, komu právě došlu, že ten router se dá použít i pro víceúrovňovou strukturu?
- Honza Marek
- Člen | 1664
Mám ještě dva nápady.
- Myslím, že by dobré umožnit jinou action než výchozí (adresy /clanky/nazev-clanku?action=edit).
Pak ještě jeden nápad, který možná umožní umazat Simple z názvu :-D
- Určitě by se šikla jazyková proměnná, třeba ještě s nastavením defaultního jazyku (adresy /en/article a /nazev-clanku zároveň). Bez toho defaultního jazyka by to taky mohlo být jednoduché.
- Jakub Šulák
- Člen | 222
Vypadá to skvěle, ale nějak se mi nedaří to implementovat.
Musel jsem to trochu upravit, ale:
Ten druhý router je tam pro případ, kdy to bude voláno bez parametru (http://www.neco.cz/katalog/).
Když ale zadám www.neco.cz/…y-text-v-db/ tak se sice zavolá správný router, dokonce to vrátí objekt PresenterRequest, ale následně dojde k přesměrování na http://localhost/katalog?…[category]=5.
Parametr lang je jazyk a je ošetřen tak, že se předává v kontruktoru a
pak v match se předá jako parametr.
Parametr limiter je pole, ve kterém mohu předávat různá omezení na výběr
produktů. $limiter[‚category‘]=5 je omezení na
product->id_kategorie=5.
Pole předávám snad také dobře, upravil jsem fnc getId(url) na konci:
Můžete mně někdo prosím nakopnout, proč mi to dělá to
přesměrování?
Routování jsem ještě s nette neřešil, tak jsem nějak mimo.
díky
- Honza Marek
- Člen | 1664
Můžete mně někdo prosím nakopnout, proč mi to dělá to přesměrování?
Když router zpracuje url, tak se ji aplikace pokusí znovu vygenerovat, aby docházelo k přesměrování na jednu variantu adresy.
- PetrP
- Člen | 587
Jakub Šulák napsal(a):
Vypadá to skvěle, ale nějak se mi nedaří to implementovat.
Když jsem si to zjednodušil:
Tak to mě adresa http://localhost/Nette-test/katalog/name
přesměrovává na
http://localhost/Nette-test/katalog?id%5Bcategory%5D=5
Když odstraním toto:
return $url=='name'?array('category'=>'5'):NULL;
a nahradím to jen za return $url=='name'?5:NULL;
Tak vše funguje
zprávně.
Takže se nemůže vracet pole. (Proč ho vlastně potřebuješ vracet?)
Editoval PetrP (19. 5. 2009 14:15)
- Jan Tvrdík
- Nette guru | 2595
WTF? Co to s mým routerem zkoušíte za hokusy pokusy? :D Čekal jsem, že se spíš dozvím, co zlepšit a ne, že se v něm někdo pohrabal a přestalo mu to fungovat.
Každopádně by to pole klidně vracet mohlo, ale muselo by ho to také detekovat (úpravou jste způsobili nekonzistenci routeru). Tohle by mělo fungovat:
- Jan Tvrdík
- Nette guru | 2595
Honza M. napsal(a):
- Myslím, že by dobré umožnit jinou action než výchozí (adresy /clanky/nazev-clanku?action=edit).
Dobrý nápad. Hotovo.
- Určitě by se šikla jazyková proměnná, třeba ještě s nastavením defaultního jazyku (adresy /en/article a /nazev-clanku zároveň). Bez toho defaultního jazyka by to taky mohlo být jednoduché.
Nechceš tuhle představu nějak rozepsat, než se to rozhodnu napsat? Jak to
chceš zkombinovat se současnou proměnnou $pathPrefix
? Spíš mě
napadá, že máš pravdu s tím, že tenhle požadavek odstraní z názvu to
Simple
, protože to bude dost možná snažší řešit jako
abstract class SeoRouter extends Route
.
- PetrP
- Člen | 587
Jan Tvrdík napsal(a):
WTF? Co to s mým routerem zkoušíte za hokusy pokusy? :D Čekal jsem, že se spíš dozvím, co zlepšit a ne, že se v něm někdo pohrabal a přestalo mu to fungovat.
Tak já zkoušel to co zkoušel Jakub Šulák
;]
Každopádně by to pole klidně vracet mohlo, ale muselo by ho to také detekovat (úpravou jste způsobili nekonzistenci routeru). Tohle by mělo fungovat:
Tak v takovéhle formě by vracení pole smysl nemělo, jedině kdyby se jednotlivé položky přidávali jako params (ale nenapadá mě smyslulpné využití ;])
- Jan Tvrdík
- Nette guru | 2595
PetrP napsal(a):
Spíš mam takovej dotaz co to vylepšuje nad použitím překladoveho slovníku?
Přesně tohle jsem tady napsal v příspěvku, který jsem smazal, protože jsem si uvědomil, že to nefunguje tak dobře, jak se mi původně zdálo.
Jediný (!) rozdíl, který tam totiž je, je velmi klíčový – pokud
metoda getId
v SimpleSeoRouter
vrátí
NULL
, vrátí router NULL
. Pokud ale funkce
v překladovém slovníku vrátí NULL
, tak Route
NULL
nevrátí.
Přemýšlel jsem nad tím, jak to třídu Route
naučit a
zatím jsem skončil u představy založené na něčem jako
PATTERN_CALLBACK
.
- PetrP
- Člen | 587
Hmmm jen takovým jednoduchým zásahem na řádku 207 to vrací NULL
To samé možná bude potřeba i u FILTER_OUT (ted mi to ale vraci url
správně; mozná tam bude ještě nějaká záludnost).
Asi to neni úplně ideální ;] možná to bude mít nějaké skrýté
vlastnosti.
Takže když použiju toto:
Na http://localhost/Nette-test/katalog/xxx
vrací
string(24) "/Nette-test/katalog/name"
string(23) "/Nette-test/katalog/xxx"
int(4)
Na http://localhost/Nette-test/katalog/name
string(24) "/Nette-test/katalog/name"
string(23) "/Nette-test/katalog/xxx"
int(5)
Je to očekávané chováni?
Editoval PetrP (19. 5. 2009 18:48)
- Jan Tvrdík
- Nette guru | 2595
Ano, toto bude (pravděpodobně) fungovat identicky, jako SimpleSeoRouter, ale bohužel zásahy tohoto typu nejsou ideálním řešením :)
- PetrP
- Člen | 587
Jan Tvrdík napsal(a):
Ano, toto bude (pravděpodobně) fungovat identicky, jako SimpleSeoRouter, ale bohužel zásahy tohoto typu nejsou ideálním řešením :)
No identicky to nefunguje protože můzu mít více parametrů v jedné
routě ze slovníkem.
Jakou konkrétně nevýhodu to má? Možná jsem už moc unavenej ale nic moc
nevydím, nebo se slovník používá k něčemu při čem by to vadilo?
- Jan Tvrdík
- Nette guru | 2595
Je třeba si uvědomit, že třída Route
a
SimpleSeoRouter
mají zcela jiný účel. Route
je
třída pro obecné routování kdečeho, SimpleSeoRouter řeší velmi
specifickou situaci, kterou třída Route
řešit neumí
(přímá editace [ještě ke všemu nekompatibilní] zdrojového kódu
route.php není řešením).
Ostatní věci vyplývají ze specifičnosti SimpleSeoRouteru
.
Jako každá věc na světě, která je specializovaná na určitou činnost,
bude vždy lepší (!) než obecné řešení v případě, že řeší
přesně to, co řešit potřebuješ. Pokud potřebuješ řešit něco
jiného, než SimpleSeoRouter
řeší, pak nemá smysl, aby jsi ho
používal.
I kdyby se třída Route
naučil zpracovávat
PATTERN_CALLBACK
, tak pokud budeš potřebovat řešit to, co
SimpleSeoRouter
řeší, tak z obecných principů plyne, že
třída Route
nikdy nemůže (!) být na danou věc lepší než
SimpleSeoRouter
. Na druhou stranu pokud by třída
Route
uměla zpracovávat PATTERN_CALLBACK
, tak by
třída SimpleSeoRouter
pravděpodobně nikdy nevznikla.
- Jan Tvrdík
- Nette guru | 2595
Předtím, když nějaký filterIn vrátil NULL
, tak router
nevrátil NULL
. Pokud má někdo router, který spoléhá na
stávající chování, tak mu přestane fungovat. Mnohem víc mi ale vadí, že
by mi v kontextu třídy Route
přišlo takové chování
nelogické.
- PetrP
- Člen | 587
Pro to by možná mohl být nějaký příznak při nastavení setStyleProperty, připadně existovat jiný druh filtru. Nerozumim přesně proč by podobné chování mělo být nelogické, jen je to nepatrné rozšíření stávajících překladových slovníků (i ty ti připadají nelogické?). Vyřešila by se s tím poslední věc co routy neumí (původně jsem myslel že s tím byl slovník vyroben; ninejší chování pokládám spíš za chybu). A bylo by to mnohem použitelnější než SimpleSeoRouter (ze vší úctou).
- David Grudl
- Nette Core | 8254
Můžete zkusit ověřit, jestli by pomohla tato úprava v Route.php (od řádku 208)
- Jan Tvrdík
- Nette guru | 2595
David Grudl napsal(a):
Můžete zkusit ověřit, jestli by pomohla tato úprava v Route.php (od řádku 208)
Neprojde to podmínkou isset($meta['fixity'])
. Upřímně ani
netuším, k čemu má $meta['fixity']
sloužit.
- PetrP
- Člen | 587
Tak fixity může nabývat 4 stavů
Route::OPTIONAL, Route::PATH_OPTIONAL, Route::CONSTANT, NULL
NULL znamená podle mě povinný protože třeba:
je fixity NULL
Route::PATH_OPTIONAL je nepovinný:
Route::CONSTANT je když není uvedena v masce, ale má defaultní neměnej parametr
Route::OPTIONAL je když je parametr v query a ma defaultni hodnotu
Proto nerozumím proč je tam $meta['fixity'] === self::CONSTANT
protože to se možnost filtrem zastavit match dá použít jen na hotnoty
které nejsou v url ;] a nemyslím si ze by někdo na to používal filtry.
Takže asi navrhuju změnit podmínku na
tedy že by se to dalo zastavit jen na povinné parametry, bez defaultni hodnoty.
- David Grudl
- Nette Core | 8254
Díky za shrnutí významu fixity, když něco dělám po delší době
s třídou Route, tak nad tím vždycky dumám a tohle se mi bude hodit ;) Což
byl ostatně i tento případ, správná je tva formuluace s
!isset($meta['fixity'])
.
Přidávám to do Route.
Ještě si říkám, že by se možná mohly výsledky z FILTER_OUT kešovat.
- David Grudl
- Nette Core | 8254
Chtěl jsem se zeptat, jak je to aktuálně se SimpleSeoRouter – je svou funkcionalitou nahraditelný pomocí Route, nebo naopak by bylo vhodné ho zařadit do extras?
- Jan Tvrdík
- Nette guru | 2595
V praxi jsem ho ještě třídou Route
nahradit nezkoušel, ale
mělo by to bez problémů fungovat. Teď už má SimpleSeoRouter
spíš smysl jako jeden z příkladů, jak může vypadat vlastní router.