Pár začátečnických dotazů

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

Ahoj, už pár dnů pročítám všechno možné ohledně Nette (dokumentaci, quick start, wiki apod.), dívám se na videa a jsem z Nette čím dál tím více nadšený ;-) Zkoušel jsem už si s Nette i trochu hrát (ne, že by tenmůj výtvor fungoval :-D ), a tak chci poprosit o zodpovězení několika otázek, které by mě zatím zajímaly:

  1. Defaultní chování routeru: Pokud jsem to dobře pochopil, tak vytvořený router, kterému nepředám žádné pravidla, funguje následujícím způsobem: muj-server.cz/presenter/action/param1/…/paramX/

…pochopil jsem to dobře? :-) Moje pokusy naznačují že ano, ale radši jsem se zeptal.

  1. Někde v ukázkových kódech o routování (myslím že někde tady v dokumentaci) jsem našel tenhle kód:
class Forum
{
    function createRoutes($router, $prefix)
    {
        $router[] = new Route($prefix . 'index.php', array(
            'presenter' => 'Forum:Homepage',
            'action' => 'default',
        ));
        $router[] = new Route($prefix . 'admin.php', array(
            'presenter' => 'Forum:Admin',
            'action' => 'default',
        ));
        ...
    }
}

Jen by mě zajímal detail, jestli tam nechybí znak & …takhle: function createRoutes(&$router, $prefix)

  1. Když už jsme u těch routerů: Dejme tomu, že mám e-shop a v něm produkty, které patří do kategorií. Kategorie se do sebe můžou nekonečně vnořovat. Jak by vypadalo přidání routu v tomto stylu? /zbozi/<kategorie>/<podkat1>/<podkat2>/.../<podkatX>/<zbozi_id>.html
  2. Někde (myslím že na wiki) jsem četl, že v hierarchii presenterů by měl být každý presenter buď abstract, nebo final. A pak jsem viděl video Davia Grudla na ČVUT, kde popisuje tvorbu e-shopu v tomhle stylu:

Z presenteru, který zobrazuje hlavní stránku, může dědit presenter, který zobrazuje kategorie zboží. Z něho může dědit další, který zobrazuje detail zboží. Díky tomu už v detailu budeme mít načtené i informace o kategorii.

Tyhle dvě informace se ale navzájem vylučují, jak je to teda správně? :-)

  1. Není mi jasná jedna věc ohledně licence. Když pomocí Nette udělám e-shop a ten někomu prodám, musím mu k tomu dát i zdrojové kódy celého toho e-shopu?

Pokud ano, jak se to řeší v případě, kdy zákazníkům tyto e-shopy pouze pronajímám (třeba běží na mojem vlastním serveru) ?

  1. Persistentní proměnné: To opravdu můžu změnit chování proměnné tím, že nad ní do komentáŕe napíšu @persistent? Podle mě je to nelogické, komentáře by přece neměly ovlivňovat kód.
  2. Metody actionNeco(), renderNeco(): jak spolu komunikují a předávají si proměnné? A ještě jsem tady na fóru četl něco o beforeRender a to už vůbec nevím o čem byla řeč :-)

Moc děkuju ochotným za odpovědi ;-)

JakubKohout
Člen | 92
+
0
-

Routy nechám napsat někoho ostřílenějšího než jsem já :)

5. Nette má vlastní licenci která říká, že autor frameworku není zodpovědný za škody která uděláš pomocí něj a že musíš zanechat autora ve zdrojových kódech + mít přiloženou licenci nette

6. ano jmenuje se to anotace, je to i v mnoha dalších programovacích jazyků (např. v javě)

7. spolu komunikují přes proměnné daného presenteru. Např. proměnnou template. Tzv. pokud chci uložit něco do šablony z action tak zapíšu $this->template->fooVar = ‚foo‘; a potom s tím klidně můžu dál pracovat v renderu.

Jednotlivé metody presenteru se volají postupně, v jakém jdou pořádí se dozvíš například tady v cheatsheetu

Ovšem výhoda action je v tom že může říct jaký render se má zvolit pomocí metody setView(‚foo‘); //změní render na renderFoo();

Ola
Člen | 385
+
0
-
  1. nevím přesně, jak to myslíš – router ve skeletonu se takhle nechová
  2. ano, chybí
  3. asi bych to řešil přidáním parametru kategorie, který by mohl obsahovat i lomítka a jeho následným filtrováním (převod z třeba aaa/bbb/ccc na pole {aaa, bbb, ccc} a naopak), nebo vlastním routerem (asi vhodnější, pak máš naprostou volnost)
  4. informace na wiki je myslím novější
  5. ne
  6. ano, pokud se Ti nelíbí anotace, je tam tuším ještě možnost definovat funkci getPersistentParams vracející pole proměnných, které jsou persistentní
  7. nekomunikují spolu (přímo) vůbec, proměnné si předávají maximálně skrze nějakou členskou proměnnou. renderNeco() je volána po actionNeco(), beforeRender() je obecná funkce která se volá před každou renderNeco(). Parametr můžeš získat buď voláním $this->getParam('nazevParametru'), nebo uvedením v parametrech funkce, nebo přes $this->param (u persistentního parametru) (neplatí pro beforeRender, v ní je možné jen $this->param u persistentních parametrů a $this->getParam())

Editoval Ola (20. 7. 2010 0:34)

LuKo
Člen | 116
+
0
-
  1. http://php.vrana.cz/reference.php
  2. Pokud zákazníkovi nepředáš zdrojáky, jak si ten eshop nainstaluje na svůj server? Jak si tam vlastními silami doprogramuje nějakou úpravu? Pokud mu jen prodáš přístup do eshopu na tvém serveru, jak se to pak liší od pronájmu? Jen způsobem platby?
nanuqcz
Člen | 822
+
0
-

Díky za rychlé odpovědi ;-)

1)

Pokud jsem to dobře pochopil, tak vytvořený router, kterému nepředám žádné pravidla, funguje následujícím způsobem: muj-server.cz/presenter/action/param1/…/paramX/

nevím přesně, jak to myslíš – router ve skeletonu se takhle nechová

Aha máš pravdu (zkusil jsem si to znovu), a jde nějak nastavit obecné chování routeru? Např router v Zendu funguje v základu controller/action/name/value/name2/value2/... Prostě něco, abych měl hezké url, ale abych nemusel pro každý presenter (a akci) psát zvláštní routu.

4)

informace na wiki je myslím novější

Škoda no, doufal jsem, že správně bude ta z toho videa, strašně se mi tam ta myšlenka dědičnosti líbila :-)

5)

Pokud zákazníkovi nepředáš zdrojáky, jak si ten eshop nainstaluje na svůj server? Jak si tam vlastními silami doprogramuje nějakou úpravu? Pokud mu jen prodáš přístup do eshopu na tvém serveru, jak se to pak liší od pronájmu? Jen způsobem platby?

No na tohle se neptám kvůli sobě, kdyby bylo na mě, s radostí bych jim ty zdrojáky dal. Bohužel můj šéf má jinou filosofii, tak jsem se ptal kvůli tomu aby mi v Nette nezakázal dělat on, kdyby zjistil že klientům musí dát všechny zdrojáky :-)

7)

nekomunikují spolu (přímo) vůbec, proměnné si předávají maximálně skrze nějakou členskou proměnnou. renderNeco() je volána po actionNeco(), beforeRender() je obecná funkce která se volá před každou renderNeco(). Parametr můžeš získat buď voláním $this->getParam(‚nazevParametru‘), nebo uvedením v parametrech

Aha, takže to chápu tak, že mám používat na všechno zatím jen actionNeco(), dokud nebudu Nette rozumět víc :-P

Ola
Člen | 385
+
0
-
  1. Pro každý presenter a action novou routu rozhodně netvoř („zabil“ bys výkon). Pro správný pochopení rout je potřeba znát alespoň základy PCRE. Podívej se na příklad: (úmyslně jsem masku psal tak, aby obsahovala téměř vše možné).
$router[] = new Route('[<lang [a-z]{2}>/]<presenter>/<action>/<id [0-9]+><?\.html?|\.php|>', array(
	'lang' => 'cs'
	'presenter' => 'Article',
	'action' => 'show',
	'param' => 10,
));

Každá routa má dva úkony – vygenerovat adresu (tedy známé parametry převést na URL, dále constructUrl) a opačně, URL převést na parametry (tedy match) (parametr je i presenter či action). Aplikace při svém startu projde všechny přidané routy, a na každé zavolá match s aktuální URL – to může skončit buď tak, že routa neodpovídá aktuální URL, nebo, že routa odpovídá – poté se kvůli kanonikalizaci zavolá construktUrl a případně se přesměruje. Výchozí třída – Route se o toto postará, pokud jí dáš masku (tedy první parametr konstruktoru) a pole výchozích hodnot. Onu masku si lze představit jako regulární výraz aplikovaný na URL. Každý parametr předaný presenteru se zapisuje jako <nazev>, za jeho názvem může následovat regulární výraz určující, jestli nalezená hodnota k danému parametru opravdu danému parametru sedí. Pokud URL neobsahuje nějaký parametr, dopadá to zpravidla dvěma výsledky – buď se vezme parametr z pole výchozích hodnot, nebo routa nevyhovuje. Pokud maska neobsahuje některý z parametrů, pak se parametr buď získá z pole výchozích hodnot, nebo z query stringu (tedy v tomto případě bych mohl hodnotu parametru param změnit přidáním ?param=20 na konec URL). Uvedená maska říká (složené závorky označují tzv. volitelné parametry, ještě je použit foo parametr, více viz dokumentace třídy Route):

  • pokud routa před prvním lomítkem obsahuje dvouznakový řetězec složený pouze ze znaků anglické abecedy, pak ho použij jako hodnotu parametru lang, jinak do lang dosaď cs
  • hodnotu v URL mezi prvním a druhým lomítkem (resp. před prvním lomítkem, pokud v URL není přítomen parametr lang) dosaď jako presenter, pokud není uvedená (má ale podmínku, že jsou volitelné i všechny parametry vpravo od současného, tj action i id), použij Article
  • hodnotu v URL mezi druhým a třetím lomítkem (resp. mezi prvním a druhým lomítkem, pokud v URL není přítomen parametr lang) dosaď jako action, pokud není uvedená, použij show
  • pokud za třetím (resp. za druhým lomítkem) je hodnota složená z pouze z číslic (alespoň jedné), pak jeho hodnotu dosaď do id, pokud není, pak výraz nevyhovuje.
    • za číselným parametrem ještě může následovat .html, .php nebo nic, při generaci url se použije .html, protože je těsně za otazníkem – viz dokumentace foo parametrů

Pokud routa matchne, zavolá se na ní ještě constructUrl se získanými parametry – to způsobí např. to, že pokud bych měl url cs/article/show/1, budu přesměrován na vytvořenou URL ve tvaru article/show/1.html. Generování URL se řídí spoustou faktorů, více viz dokumentace.

Což znamená, že routě vyhoví pouze následující URL:

  • <lang>/<presenter>/<action>/<id>.html
  • <lang>/<presenter>/<action>/<id>.php (přesměruje na <lang>/<presenter>/<action>/<id>.html nebo <presenter>/<action>/<id>.html, pokud je lang rovno cs)
  • <lang>/<presenter>/<action>/<id> (přesměruje na <lang>/<presenter>/<action>/<id>.html nebo <presenter>/<action>/<id>.html, pokud je lang rovno cs)
  • <presenter>/<action>/<id>.html
  • <presenter>/<action>/<id>.php (přesměruje na <presenter>/<action>/<id>.html)
  • <presenter>/<action>/<id> (přesměruje na <presenter>/<action>/<id>.html)

Editoval Ola (20. 7. 2010 21:52)

nanuqcz
Člen | 822
+
0
-

Aha, asi mi to právě docvaklo (možná ne :-) ) Pochopil jsem to správné, že tebou vytvořená routa mi obslouží i url users/edit/5.html nebo en/users/ (zavolá se akce show s id=10) ?

Ola
Člen | 385
+
0
-

Url users/edit/5.html ano, url en/users/ ne (pro id není výchozí hodnota, 10 je pro úplně jiný parametr)

Editoval Ola (20. 7. 2010 21:53)

nanuqcz
Člen | 822
+
0
-

url en/users/ ne (pro id není výchozí hodnota, 10 je pro úplně jiný parametr)

Aha, ono to param s <id> nijak nesouvisí :-D Takže jestli to chápu dobře, tak ten parametr 'param' => 10 nejde pomocí url změnit, protože v masce nikde není <param> ;-)

bojovyletoun
Člen | 667
+
0
-

Nikde jsem nenašel informace o složených závorkách v Route. Význam jako u regexp chápu [znaky]{min,max}, ale tohle mě zaskočilo. Předpokládám že jde totéž co v regexp: (to|nebo|tohle). Znamená otazník, že, když zadám neexistující možnost fr, tak se vrátí cs, nebo jenom, když se neuvede nic, tak se vrátí cs?

<lang {?cs|en}>

Editoval bojovyletoun (11. 10. 2010 14:36)

bojovyletoun
Člen | 667
+
0
-

Zkoušel jsem si hrát s <lang {?cs|en}>, ale opravdu jsem nepřišel, jaký je princip. Dodám, že je to v dokumentaci/Route

chová se to tak jako kdyby to bylo <lang cs>

umí to někdo vysvětlit?