Routovanie – výrazy v maskách vz. názvy premenných v metódach

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Čamo
Člen | 798
+
0
-

Príjemné popoludnie,
potrebujem vysvetliť jednu vec ohľadom routovania.
Takže v quickstarte je nejaký homepage presenter a ten v šablone generuje linky:

<h2><a href="{link Post:show $post->id}">{$post->title}</a></h2>

No a mám napísaný takýto routelist:

$router = new RouteList();
$router[] = new Route('<presenter>/<action>/<postId>');
$router[] = new Route('<presenter>/<action>[/<id>]', 'Homepage:default');

Všetko funguje, len ja nechápem ako. Problém mám s tým <postId>. Mám akciu renderShow($postId) Zistil som, že v route nemôžem napísať <id> ale musí tam byť <postId>. Nechápem, že prečo. Myslel som, že nezáleží na tom ako sa parameter volá(však je to maska). Keď predsa volám v php nejakú metódu s parametrom, tak nezáleží na tom, ako ten parameter pomenujem, v php záleží na poradí. Nechápem ako to, že Nette sa zaoberá tým ako je ten parameter v maske pomenovaný.
Môže mi to prosím vás niekto vysvetliť?
Ďakujem.

Editoval Čamo (30. 5. 2014 15:47)

David Matějka
Moderator | 6445
+
0
-

ty nazvy parametru v route (to <postId>) se mapuje na nazvy parametru v render* nebo action* metodach, tedy na tve renderShow($postId), pokud bys to chtel prejmenovat, musel bys na obou mistech

Jan Tvrdík
Nette guru | 2595
+
0
-

Přečti si dokumentaci. Název masky musí* odpovídat názvu parametru, jinak by nebylo přeci jasné, co je to za parametr, ne?

* Nemusí, jde to přefiltrovat globálními filtry.

Čamo
Člen | 798
+
0
-

Nechápem.
Ako a vlastne prečo záleží na tom ako sa ten parameter v metóde volá. Však na tom vôbec nezáleží. Či záleží???
Potom sa musa všetky parametre v každom presentery a v každej metóde volať postId. Alebo musím napísať nové pravidlo. Mám pocit, že sa tam stráca tá univerzálnosť.

Editoval Čamo (30. 5. 2014 16:05)

Čamo
Člen | 798
+
0
-

Jan Tvrdík:
ale predsa tie parametre sa v PHP predávajú podľa poradia, nie podľa názvu. Tak je to v Pythone. Či čo sa deje?

David Matějka
Moderator | 6445
+
0
-

V php obecne zalezi jen na poradi. Ale nette si zjistuje nazvy parametru, abys dostal opravdu to, co chces. Takze jak pojmenujes parametr v presenteru, tak takove jmeno pak musis pouzit i v route

Čamo
Člen | 798
+
0
-

Toto ale nedáva žiadny zmysel. V URL sú parametre určené poradím. Z URL nezistíš aký prameter prenášaš. Máš tam len hodnotu a tá sa mapuje podľa poradia. Nedáva mi to zmysel ani keď čo robím.

David Matějka
Moderator | 6445
+
0
-

No jasne, v route je to zavisle na poradi. Ale proto se tem parametrum davaji nazvy, aby presenter nebyl zavisly na poradi v URL, ale na nazvu parametru

EDIT: nette presenter ani nema tuseni o nejakym poradi v route nebo v url. Jediny, co presenter zajima, jsou nazvy parametru.

Editoval matej21 (30. 5. 2014 16:35)

Čamo
Člen | 798
+
0
-

matej21:
Ale presenteru by malo byť tiež jedno, ako sa ten parameter volá. Od jeho názvu nezávisí vôbec nič. Či čo sa deje?
Však keď v z kódu zavoláš metódu, tak nezáleží ako pomenuješ parametre $this->renderDefault($ferko_mrkvička). Každý očakáva, že to bude fungovať. Prečo by v tom mal byť problém?

David Matějka
Moderator | 6445
+
0
-

Kazdy ocekava, ze nebude zalezet na poradi parametru, ale pouze na tom, jak ho pojmenuju.
Predstav si url, ktera ma v query stringu treba:

?foo=1&bar=2

k tomu mam v presenteru

public function renderDefault($foo, $bar)

A melo by to preci fungovat bez ohledu na poradi, tedy i s url

?bar=2&foo=1

Kdyby to bylo jak rikas, tedy dle poradi, dostal bych je obracene.

Jen doplnim, ze pristup k parametrum pomoci parametru render* a action* metod je jen jeden ze zpusobu, take muzes pouzit persistentni parametry

/** @persistent */
public $foo;

nebo si pro parametr „sahnout“:

$this->getParameter('foo');

Vsude zalezi pouze na nazvu parametru.
Ty muzes presenter spustit i „rucne“, ze si vytvoris Nette\Application\Request se spravnymi parametry. A tuto tridu vyuziva i routovani – vytvori Request objekt a preda mu parametry, ktere naslo v url.

EDIT:
metody render* a action*, respektive nazvy jejich parametru, vyuziva i nette pri vytvareni linku, kdyz neuvedes nazev parametru.
Muzes vytvaret link (v latte):

{link Homepage:default id=>1}

tedy ze uvedes nazev parametru
Pokud vsak nazev neuvedes a pouzijes jen

{link Homepage:default 1}

Tak nette musi ten parametr nejak pojmenovat, aby se vedelo, kam to v URL patri (dle nazvu parametru) Proto si k tomu najde v HomepagePresenter odpovidajici action/render metodu a zjisti, ze parametr se jmenuje $id

Editoval matej21 (30. 5. 2014 16:56)

Čamo
Člen | 798
+
0
-

Lenže routy sa píšu práve kôli adresám(cool URL), ktoré neprenášajú názov premennej.
Dostaneš len hodnotu. A pomenuješ ju podľa toho na ktorej pozícii sa v URL nachádza.
Ja tvrdím, že by malo byť jedno či sa pomenuje id alebo postId. Akurát ma to obmedzuje v tom, že ja musím tú premennú pomenovať podľa parametra v metóde.
Keď voláš n:href makro tak nepredávaš názov. Záleží práve na poradí.

Pri $this->getParameter('foo') tiež nezáleží na tom ako sa parameter volá. Ak sa bude volať id, tak budeš volať id, ak postId tak voláš postId.

Mne len vadí, že na dve rôzne akcie s povedzme jedným parametrom ale inak pomenovaným, musím napísať dve routy ,alebo ich pomenovať rovnako. Mne to príde neefektívne.

Čamo
Člen | 798
+
0
-

Vyskúšal som to n:href makro.
<a href=„{link Post:show id=>$post->id}“>{$post->title}</a>
nie som si istý iba tým, či je to dobre napísané s tým id=>. Ale podľa všetkého mu je to úplne jedno, lebo metóda má parameter $postId.

David Matějka
Moderator | 6445
+
0
-

A pomenuješ ju podľa toho na ktorej pozícii sa v URL nachádza.

No vidis, POJMENUJU. A toto JMENO musim pouzit i v presenteru.

Ja tvrdím, že by malo byť jedno či sa pomenuje id alebo postId.

Ano, je to jedno, jen to jmeno musi byt stejne.

Keď voláš n:href makro tak nepredávaš názov. Záleží práve na poradí.

Viz posledni cast (za editem) v mem prispevku. Tohle je feature pro usnadneni, abys nemusel psat nazvy parametru. Pro urceni nazvu parametru se pak pouziji prave render* nebo action* metody. Ty parametry se tedy taky pojmenuji, jen to nevidis, stara se o to nette.

Nakonec zopakuju: Presenter nezna poradi v URL. V requestu od routeru dostane pouze nazvy parametru a jejich hodnotu. Proto musis pouzivat ty nazvy.

Jan Tvrdík
Nette guru | 2595
+
0
-

Čamo: Ještě jednou. Parametr je jednoznačně určen svým názvem, tak se pozná od ostatních parametrů. Jasné? Jediná výjimka z tohoto pravidla je, že při tvorbě odkazu pomocí makra link (plink, n:href) nemusíš názvy parametrů uvést a v tom případě budou určeny na základě názvů parametrů cílové action* nebo render* metody.

Příklady, kde se název parametru může objevit:

  • example.com?product=7
  • new Route(‚<presenter>/<product>‘)
  • public function renderView($product)
  • {link Products:view, product ⇒ 7}
Čamo
Člen | 798
+
0
-

Ešte posledný pokus:
Povedzme že máme dve rôzne akcie v dvoch presenteroch:

presenter1->renderShow($productId){}
a
presenter2->renderShow($articleId){}

Líšia sa len tým, ako majú pomenované vstupné parametre.

Nette mi dovolí aby som do jednej routy spojil volanie akcie obydvoch presenterov tj.:

<presenter><action> <- platí pre obydva presentery

ale už mi nedovolí, aby som napísal

<presenter><action><id>

musím napísať dve routy miesto jednej.
<presenter><action><productId>
<presenter><action><articleId>

Editoval Čamo (30. 5. 2014 19:33)

mkoubik
Člen | 728
+
0
-

Nemůžeš si ten parametr pojmenovat prostě $id?

Jan Tvrdík
Nette guru | 2595
+
0
-

Čamo: Protože to, co chceš, je blbost. Routa <presenter><action><productId> podporuje všechny presentery a přitom pracuje s parametrem konkrétního presenteru. Je to nesmyslný hybrid mezi obecnou a konkrétní routou. Buď to musíš napsat zcela obecně <presenter><action><id> (a pak se parametr bude jmenovat id) nebo zcela konkrétně products/<action>/<productId> a articles/<action>/<articleId>.

Čamo
Člen | 798
+
0
-

Jan Tvrdík:
Dokumentácia citujem: „Pamatujte na to, že počet rout má vliv na rychlost aplikace, zejména při generování odkazů.“
O toto mi ide, nie o to či je to podľa teba sémantická blbosť alebo nesmyslný hybrid.

EDIT:
A ten hybrid som takto nenapísal ja, ale je to okopírované z quickstartu. Tak sa trochu schlaď.

Editoval Čamo (30. 5. 2014 19:59)

Jan Tvrdík
Nette guru | 2595
+
0
-

Čamo: Výkon je podřadný funkčnosti. Je docela jedno, že to bude rychlé, když to nebude vůbec fungovat.

A ten hybrid som takto nenapísal ja, ale je to okopírované z quickstartu.

Můžeš odkázat konkrétně? Prošel jsem český i anglický QS a uvedený kód jsem nikde neviděl.

Jan Tvrdík
Nette guru | 2595
+
0
-

Nikde nevidím, že by tam používali výše uvedenou hybridní, nesmyslnou a prakticky nefunkční routu. Používat pro parametry názvy jako postId je zcela v pořádku. Ale musí se pro to pochopitelně napsat správné routy, např.

new Route('posts/<action>[/<postId>]', array(
	'presenter' => 'Posts',
));
Čamo
Člen | 798
+
0
-

A tú dokumentáciu kto písal, keď je výkon podradný funkčnosti?

A takže ty by si ku akcii renderShow($postId) napísal akú routu?
Ja by som sa snažil napísať <presenter><action><id>
Ty by si to napísal ako aby to nebol nesmyslný hybrid? Ja len začínam tak to chcem pochopiť.

Čamo
Člen | 798
+
0
-

Dobre v podstate som sa dozvedel, čo som potreboval, takže ďakujem.

Editoval Čamo (30. 5. 2014 20:31)

mystik
Člen | 312
+
0
-

Čamo: Zkus se zamyslet jak by to fungovalo, kdyby ten parametr nebyl jeden, ale bylo jich třeba pět a některé nepovinné. Nebo případ, kdy by jsi chtěl do budoucna změnit pořadí parametrů v URL. Nebo jsi měl pro jeden presenter více rout. Pak už se bez pojmenování obejdeš jen těžko.