Vlastní formátování odkazů
- tomas.lang
- Člen | 53
Předem upozorňuji že jsem pracně procházel většinu fóra a odpoveď jsem nenašel… :)
Moje otázka je jak pracovat s vytvářením odkazů pomocí funkce
link() – potřeboval bych vytvořit něco takového – www.example.com/…ejaky-clanek, a zatím to dělám
způsobem {$presenter->link('clanky/'.$article->redirect)}
,
ale nejsem si jistý jestli je to nejlepší způsob… Navíc mám pocit že
tímto způsobem nejsem schopen očetřit aby „clanky“ byly hned za
rootem webu, ale budou vždy až pod modulem/presenterem pod který patří –
a to je právě ten problém který řeším, protože zatím mě to generuje
akorát www.example.com/…ejaky-clanek, coz mi moc
nevyhovuje…
Pak se toto týká ještě druhá věc, a to nastavení routeru, a to jestli je pro potřebu těch článků nastaven správně:
$router[] = new Route('clanky/<id>', array(
'presenter' => 'Default',
'action' => 'article',
'id' => NULL,
));
Předem děkuji za všechny rady :)
- David Grudl
- Nette Core | 8218
Nejprve bych rád ujasnil, že parametry metody link() nesouvisí přímo s URL. Prvním argumentem je cíl (destination) určující cílový presenter & view, druhým (resp. dalšími) jsou parametry předávané tomuto presenteru:
$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)- Parametry presenteru je možné předat jako asociativní pole
$this->link('show', array('id' => 10, 'lang' => 'en'))
Asociativní pole není příliš sexy, proto Nette nabízí vychytávku:
pokud existuje v cílovém presenteru metoda
renderShow($id, $lang, ...)
nebo metoda
actionShow($id, $lang, ...)
, kde ono ‚show‘ v názvu
odpovídá názvu linkovaného view, je možné klíče ‚id‘ a ‚lang‘
vynechat – automaticky se vezmou z parametrů těchto metod:
$this->link('show', array(10, 'en'))
A naopak, když je dotyčná metoda po odkliknutí zavolána, tak se jí
předají tyto argumenty v parametrech $id
a $lang
.
V poli je možné uvést další parametry, které metody
renderShow
a actionShow
nedefinují, například lze
nastavit nějaký persistentní parametr (v tom případě ovšem už
s asociativním klíčem). Pokud žádný takový další parametr není, je
možné pole úplně vynechat:
$this->link('show', 10, 'en')
Tedy v Nette se odkazuje na presenter & view, nebo ještě jednodušeji:
odkazuje se na konkrétní metodu.
$this->link('catalog:show', 10, 'en')
odkazuje a po odkliknutí
zavolá metodu CatalogPresenter::renderShow(10, 'en')
. Jaké se
vytvoří URL v tu chvíli nehraje roli. To je úkol oddělené vrstvy –
routování.
- David Grudl
- Nette Core | 8218
tomas.lang napsal(a):
Pak se toto týká ještě druhá věc, a to nastavení routeru, a to jestli je pro potřebu těch článků nastaven správně:
$router[] = new Route('clanky/<id>', array( 'presenter' => 'Default', 'action' => 'article', 'id' => NULL, ));
Předem děkuji za všechny rady :)
To je správné nastavení. Ale je potřeba počítat s tím, že i URL
clanky/
je vyhovující a bude v proměnné $id hodnota NULL.
Ještě taková obecná drobnost – presenter by neměl mít název
Default, stejně jako třídu ve svém projektu nenazveme Default, nebo (byť
jedinou) funkci nějaké třídy nenazveme function default()
.
Nebylo by lepší třeba Homepage?
- tomas.lang
- Člen | 53
#2: no ale v tomto případě si přeci nepomůžu, protože ztratím to slovo clanky které jsem v URL chtěl mít…
#3: takže pokud jsem to správně pochopil tak při používání funkce link() se zajímám jen o to na který presenter, resp. pohled chci odkázat… Takže v tom případě by můj kód měl vypadat pouze takto:
$presenter->link('article', array('id' => $article->redirect))
ale jak mám pomocí routerů docílit té kýžené adresy – to už nějak nechápu…
#4: a pokud bych do toho zápisu routeru neuvedl
'id' => NULL
, pak by si to při URL clanky/ ten router
nepřivlastnil?
S těmi názvy default je to tak že jsem to celé dneska narychlo předelávat z ukázkové příkladu, a tam se to skoro všude jmenuje default :) Mno, je to můj první den s nette, tak jsem se zatím spíše věnoval výzkumu… Homepage zní velice rozumně… :)
Editoval tomas.lang (12. 8. 2008 22:42)
- David Grudl
- Nette Core | 8218
tomas.lang napsal(a):
#3: takže pokud jsem to správně pochopil tak při používání funkce link() se zajímám jen o to na který presenter, resp. pohled chci odkázat… Takže v tom případě by můj kód měl vypadat pouze takto:
$presenter->link('article', array('id' => $article->redirect))
Ano. Jen pro jistotu doplním, že
$presenter->link('article', ...)
vede na současný presenter a
view ‚article‘.
ale jak mám pomocí routerů docílit té kýžené adresy – to už nějak nechápu…
Mně ten router připadá v pořádku, měl by generovat adresy ve
tvaru http://www.example.com/clanky/nejaky-clanek
#4: a pokud bych do toho zápisu routeru neuvedl
'id' => NULL
, pak by si to při URL clanky/ ten router nepřivlastnil?
Přesně tak, id by se stalo povinným parametrem a takovéto URL bez něj by nebylo kompletní a tudíž vyhovující. Aplikace by zkoušela další routy v seznamu a pokud by žádné nevyhovovalo, zobrazila by se chyba 404 Not found.
S těmi názvy default je to tak že jsem to celé dneska narychlo předelávat z ukázkové příkladu, a tam se to skoro všude jmenuje default :) Mno, je to můj první den s nette, tak jsem se zatím spíše věnoval výzkumu… Homepage zní velice rozumně… :)
Jasně, to se vás netýkalo, to byl obecný postřeh.
- tomas.lang
- Člen | 53
Sláva! Vše začalo fungovat tak jak má :) Mnohokráté díky…
Ještě bych se chtěl zeptat jestli záleží na tom v jakém pořadí jsou routery uloženy – uvedu na příkladu:
$router[] = new Route('clanky/<id>', array(
'presenter' => 'Default',
'action' => 'article',
));
$router[] = new Route('<presenter>/<action>/<id>', array(
'presenter' => 'Default',
'action' => 'default',
'id' => NULL,
));
$router[] = new Route('<presenter>/<action>/<id>', array(
'presenter' => 'Default',
'action' => 'default',
'id' => NULL,
));
$router[] = new Route('clanky/<id>', array(
'presenter' => 'Default',
'action' => 'article',
));
je v rámci fungování aplikace mezi těmito dvěma kódy rozdíl?
A poslední otázka (snad) se ještě týká trochu off-topis třídy DibiTable – jde o metodu kterou zpracovávám ten redirect na ty články
public function renderArticle( $id )
{
$articles = new Articles;
$article = $articles->fetch( array( '[redirect]='. $id ) );
$this->template->title = "Article";
$this->template->article = $article;
}
Jde o to jestly by šlo ten fetch
napsat nějak rozumněji –
tedy něco ve stylu
->fetch( array( '[redirect]=%s', $id ) )
– abych tam ty
uvozovky nemusel doplňovat ručně… Samozřejmě bych mohl udělat přímo
SQL dotaz přes dibi a měl bych po problému, ale když už tu mám tu třídu
Articles, tak bych ji rád využil… :)
- David Grudl
- Nette Core | 8218
Na pořadí záleží, zpracovávají se od shora dolů, takže url
/clanky/nejaky-clanek
v druhém příkladu se předá na presenter
‚clanky‘ a view ‚nejaky-clanek‘, druhá routa se nedostane
ke slovu.
ad dibi: momentálně na to nejsem naladěn, nevím, odpovím později.
- pmg
- Člen | 372
Jak víte, libuju si v navážení se do cizích diskusí, zvlášť pokud se jedná o offtopic. Když tedy padla zmínka o DibiTable, nebylo by pěkné, dyby s ní bylo propojeno DibiFluent? Vím, ono je to ještě ve zkušebním provozu, ale jen navrhuji. Představte si to, byla by to magická kombinace… Ale asi jsem zase objevil kolo. Dnes už páté! Hádejte, kde.
Editoval pmg (13. 8. 2008 11:50)
- Panda
- Člen | 569
tomas.lang napsal(a):
A poslední otázka (snad) se ještě týká trochu off-topis třídy DibiTable – jde o metodu kterou zpracovávám ten redirect na ty články
public function renderArticle( $id ) { $articles = new Articles; $article = $articles->fetch( array( '[redirect]='. $id ) ); $this->template->title = "Article"; $this->template->article = $article; }
Jde o to jestly by šlo ten
fetch
napsat nějak rozumněji – tedy něco ve stylu->fetch( array( '[redirect]=%s', $id ) )
– abych tam ty uvozovky nemusel doplňovat ručně… Samozřejmě bych mohl udělat přímo SQL dotaz přes dibi a měl bych po problému, ale když už tu mám tu třídu Articles, tak bych ji rád využil… :)
Mělo by se to chovat stejně inteligentně, jako třeba modifikátory
%v nebo %a, takže stačí asociativní pole sloupec => hodnota
a typ sloupce fouknout za jeho název:
$article = $articles->fetch(array('redirect%s' => $id));
Pokud by bylo potřeba filtrovat třeba podle ID autora (uživatele), tak by to mohlo vypadat takto:
$article = $articles->fetch(array('author%i' => $id));
Pokud jsou parametry správně otypované (tzn. třeba číslo je integer a ne string), tak si dokonce můžeš dovolit modifikátory typu neuvádět:
$article = $articles->fetch(array('author' => 15));
/* SQL:
SELECT *
FROM `articles`
WHERE `author`=15
*/
$article = $articles->fetch(array('author' => '15'));
/* SQL:
SELECT *
FROM `articles`
WHERE `author`='15'
*/
Pokud však používáme nezpracovaný vstup přímo od klienta, tak bude lepší tam ten modifikátor uvést.
- David Grudl
- Nette Core | 8218
Panda napsal(a):
Pokud však používáme nezpracovaný vstup přímo od klienta, tak bude lepší tam ten modifikátor uvést.
A nebo
$article = $articles->fetch(array('author' => (int) $id));
pmg napsal(a):
Jak víte, libuju si v navážení se do cizích diskusí, zvlášť pokud se jedná o offtopic. Když tedy padla zmínka o DibiTable, nebylo by pěkné, dyby s ní bylo propojeno DibiFluent? Vím, ono je to ještě ve zkušebním provozu, ale jen navrhuji. Představte si to, byla by to magická kombinace… Ale asi jsem zase objevil kolo. Dnes už páté! Hádejte, kde.
Je to velmi lákavé, ale zatím se mi to nepovedlo rozumně sloubit. Zádrhel je v tom, že DibiFluent vytvoří dotaz, který je potřeba nakonec spustit metodou execute(), což ovšem odporuje konvenci DibiTable.