Jen pro trpělivé – lamka potřebuje poradit se vším
- Flipajs
- Člen | 29
Dobrý den.
Už asi potřetí jsem se snažil proniknout do Nette. Hrozně mě láká, ale já jsem netrpělivý člověk a počáteční bariéra mě vždy odradila. Projížděl jsem examply a nenašel jsem odpověď na své otázky. Nejhorší je že ani nevím jak problém pojmenovat a tak jsem ani moc nenašel nic v téhle diskuzi. Zkusím nastínit pár problémů a pokud by se našel někdo kdo by si mě vzal na chvíli třeba pod křídlo, byl bych mu vděčný.
Jde o to že na webu chci mít několik stránek, modulů… jak chcete. Dříve jsem to vše řešil přes index kde jsem includoval jednotlivé moduly do textového pole a ostatní obsah v layoutu měl nastavený podle podmínek a občas se něco v základní kostře změnilo.
Jak k tomu přistupovat v Nette? Co modul (novinky, registrace atd.) to jeden presenter? A jak případně řešit věci všem společné – spojení s databází, malý přehled novinek někde v layoutu, menu atd? Případně je možné mít nějaký Default Presenter a v něm ovládat ostatní presentery dle volby?
Předem děkuji za radu a případnou reakci.
Editoval Flipajs (23. 1. 2010 11:56)
- Ondřej Mirtes
- Člen | 1536
Části webu rozdělíš na presentery, asi tak, jako popisuješ – novinky, registrace, články, fotogalerie…
Spojení s databází můžeš navázat v bootstrapu anebo BaseModelu (= předek všech modelů, tříd, které pracují s databází).
Výpis věcí v layoutu můžeš řešit naplněním proměnných v BasePresenteru (= předek všech presenterů).
Taky ti můžu doporučit rok starý thread ode mě, když jsem se já sem zaregistroval a plánoval se naučit s Nette :)
Chce to konkrétní příklady – všechny věci, na které seš při vývoji webů zvyklý, jsou v Nette výborně vyřešeny a obvykle je jediná správná cesta, jak k problému přistoupit a vyřešit ho :)
Takže se klidně ptej :)
K učení doporučuji seriál na Zdrojáku, který je teď podle mě na naučení se základů asi nejlepší – oficiální dokumentace teď prochází bouřlivým vývojem a je možné, že jsou její části i zastaralé a v nejnovější revizi Nette nefunkční.
A ještě můžu doporučit pustit si videa o Nette, u kterých si odpočineš a krásně tě natěší :))
Editoval Ondřej Mirtes (23. 1. 2010 12:39)
- Flipajs
- Člen | 29
Takže BasePresenter je nějaký v Nette nadefinovaný pojem a ten presenter
se tak musí jmenovat?
V něm si vytvořím obsluhu menu (zvýraznění třeba aktuální položky
atd.), postranní panely a podobně? A ten se spustí vždy a zároveň s ním
třeba RegistracePresenter kde už bude přímo registrace kterou budu mít
v templates v složce registrec se všemi jejími pohledy?
Na Zdrojak jsem koukal a caffeMachine projížděl a na tvůj thread jsem narazil. Letmo jsem ho projížděl. Zkusím to ještě jednou.
Zatím moc díky;)
- _Martin_
- Generous Backer | 679
K tomu BasePresenteru
: Jde o to, že každý presenter je
v PHP třída. A třídy mohou dědit od jiných tříd. A toho se využívá
tak, že všem presenterům dáš jako předka třídu, do které nastavíš
společné věci. A pro tuto třídu se zažilo označení
BasePresenter
. Jde o „BestPractice“, nikoliv o požadavek
frameworku.
Ještě podotýkám, že některé části může být vhodné předělat na
komponenty (třeba menu) a v BasePresenteru
mít pouze továrničku
na tuto komponentu.
- Ondřej Mirtes
- Člen | 1536
Taky si doporučuju nastudovat OOP – určitě pojmy jako dědičnost, polymorfismus, interfaces, statické a členské proměnné a jak se s tím vším v PHP pracuje – Nette je plně objektově napsaný framework a při programování se dnes bez OOP neobejdeš nikde.
- Flipajs
- Člen | 29
To _Martin_: ok, dědičnost jakž takž chápu. Jde tedy o to že BasePresenter extends Presenter a všechny ostatní presentery které na něm budu stavět budou JinyPresenter extends BasePresenter?
a jak to má být s routováním? BasePresenter se vždy zavolá sám když z něj budu chtít dědit nebo ho někdem usím includovat nebo jak?
Díky.
To OndřejMirtes: jo na OOP určitě mrknu. Ještě v tom pořád trochu plavu. Na zdrojáku je koukám nějaký tutoriál tak si to projdu. Když na to dojde. Můžu se zkusit ptát i ohledně toho? Nebo to bych sem na nette fórum neměl tahat?
Taktéž děkuju!
- Ondřej Mirtes
- Člen | 1536
Tím, že extenduješ BasePresenter nějakým JinyPresenter, tak JinyPresenter má automaticky všechny vlastnosti BasePresenter. To je OOP :)
Můžeš se ptát na cokoli, i když nějaké věci čistě okolo PHP se hodí spíše na PHP fórum :)
- despiq
- Člen | 320
Pokud nevis nebo poradne nerozumis OOP tak opatrne s Nette, nechtel bych te od Nette odradit ale i David na svych skoleni vyzaduje znalost OOP a urcite to je treba jinak by ses mohl pri tom plavani utopit.
EDIT: a dusledek toho by byl opetovny odchod od Nette protoze „to tvoje“ ti funguje
Editoval despiq (23. 1. 2010 20:57)
- _Martin_
- Generous Backer | 679
Flipajs napsal(a):
a jak to má být s routováním? BasePresenter se vždy zavolá sám když z něj budu chtít dědit nebo ho někdem usím includovat nebo jak?
Routování se to netýká (jak psal Ondra) a pokud jde o načtení toho souboru s třídou BasePresener, tak o to se postará RobotLoader.
- Flipajs
- Člen | 29
Takže abych si to ujasnil…
Routování mám nastavené jako v examplu z CD-collection. Zadám si tam nějakej DefaultPresenter nebo třeba UvodPresenter a v něm budu mít první stránku. UvodPresenter bude využívat jako rodiče BasePresenter. A BasePresenter musím někde includovat? Nebo je to jméno které RobotLoader vyhledává sám? Nebo jak? V jiném vlákně na fóru jsem četl že RobotLoader pro věci co se Nette týká není potřebam že se používá pro includování jiných knihoven a tříd atd. Tak jak tedy?
Děkuji
- Panda
- Člen | 569
Nemusíš, RobotLoader
vyhledá všechny závislosti sám. Pokud
je tedy třída UvodPresenter
potomkem třídy
BasePresenter
a ta je potomkem třídy Presenter
,
načte se nejprve Presenter
, pak BasePresenter
a
úplně nakonec UvodPresenter
.
RobotLoader
pro samotné Nette skutečně potřeba není (Nette
má NetteLoader
a potřebné require_once
klauzule
v souborech jsou), ale když jej načteš, tak se rovnou použije (místo
NetteLoaderu
). Pro soubory Tvé aplikace a ostatní knihovny se za
předpokladu, že je umístíš do libs
(či jiné složky, kterou
RobotLoader
u zadáš), používá automaticky také.
A jak již bylo řečeno, routování se samotným procesem načítání tříd nesouvisí.
- Flipajs
- Člen | 29
Panda: předpokládám že RobotLoader nebo NetteLoader musím nějako volat a určit mu adresáře? Protože bez toho musím do všech potomků třídy BasePresenter includovat ten BasePresenter.
Jestli chápu dobře… v Presenterech by neměl být vůbec žádný html kód? tedy pokud chci includovat třeba menu tak bych měl právě třeba v basepresenteru v fci onstartup() přiřadit do templates->menu pole hodnot jako název označené/neoznačené, odkaz atd. a poté to v v layoutu projet nějakým foreachem ok a teprve tam používat html tagy?
Díky.
Editoval Flipajs (25. 1. 2010 16:58)
- Ondřej Mirtes
- Člen | 1536
RobotLoader můžeš spustit pár příkazy v bootstrapu anebo tímto řádkem v config.ini (detailní nastavení):
service.Nette-Loaders-RobotLoader.run = TRUE
Pro tvoji první aplikaci ti doporučuji nakopírovat si složkovou strukturu z tools/Skeleton z distribuce frameworku, a začít vyvíjet na tom – nemusíš se patlat s některými nastaveními, tvorbou configu a bootstrapu, můžeš rovnou začít vyvíjet :)
K menu – pro naplnění šablony (pro více views) doporučuji metodu beforeRender – startup by měl sloužit spíš pro technické věci a např. kontroly oprávnění, než plnění šablony.
A do Presenteru opravdu žádné HTML nepatří :) To patří jen do šablon.
Zkusím ti tu napsat, jak by to přibližně mělo vypadat (nebudu to testovat):
//BasePresenter:
protected function beforeRender() {
$this->template->menu = array(
//'Název' => array('Presenter:action', array('parametry'));
'Úvod' => array('Homepage:', NULL),
'Aktuality' => array('Articles:', array('category' => 'news')),
'Registrace' => array('User:new', NULL),
);
}
{* @layout.phtml: *}
...
<ul id="menu">
{foreach $menu as $key=>$item}
<li>
{ifCurrent $item[0], $item[1]}
<strong>{$key}</strong>
{else}
<a href="{plink $item[0], $item[1]}">{$key}</a>
{/if}
</li>
{/foreach}
</ul>
...
- Flipajs
- Člen | 29
Ještě jestli jsem správně pochopil strukturu…
V app/presenters/ mám jednotlivé presentery… dejme tomu BasePresenter, UserPresenter NewsPresenter atd…
Tuším z examples CD-Collection jsem do bootstrap.php zkusil nějako napodobit toto: (přiznávám že je to ctrl+c ctrl+v bez toho že bych tomu nějako extra porozuměl)
// mod_rewrite detection
if (function_exists('apache_get_modules') && in_array('mod_rewrite', apache_get_modules())) {
$router[] = new Route('index.php', array(
'presenter' => 'Default',
'action' => 'default',
), Route::ONE_WAY);
$router[] = new Route('<presenter>/<action>/<id>', array(
'presenter' => 'Default',
'action' => 'default',
'id' => NULL,
));
} else {
$router[] = new SimpleRouter('Default:default');
}
toto je .htaccess
# mod_rewrite
<IfModule mod_rewrite.c>
RewriteEngine On
# RewriteBase /
# front controller
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule !\.(pdf|js|ico|gif|jpg|png|css|rar|zip|tar\.gz)$ index.php [L]
</IfModule>
no a v templates mám strukturu tak že @layout.phtml a co presenter to složka a v ní jednotlivé náhledy tedy Default/default.phtml atd…
Proč to píšu… pokud mám třeba odkaz jak jsi psal User:new atd… znamená to že se bude hledat UserPresenter a v něm metoda renderNew? Případně proč mám červeně označený odkaz kde odkazuju na Default:default? Musím někde něco ještě nastavit? Přepsat atd?
Druhý dotaz.
$this->template->registerFilter(‚Nette\Templates\CurlyBracketsFilter::invoke‘);
by mělo být v každém prezenteru v beforeRender() nebo to můžu šoupnout
do BasePresenteru berforeRender()
No pokud tohle někdo aspoň trochu pochopí a zvládne odpovědět tak by zasloužil metál…
Díky =D
- Ondřej Mirtes
- Člen | 1536
Všechno vypadá, že máš správně – případně ti můžu doporučit vzít si adresář tools/Skeleton, nakopírovat si do libs/Nette celý framework a začít pracovat s tím – ušetří ti to právě psaní bootstrapu, vytváření složek a tak :) (Koukám, že už jsem to psal v předchozím postu)
Registrovat LatteFilter nemusíš nikde, ten už se pěkně dlouho registruje automaticky :) A pokud chceš mít např. nějakou proměnnou v šabloně dostupnout všude, strč její plnění do beforeRender v BasePresenter. Ale pozor – pokud budeš mít tuto metodu i v nějakém Presenteru (poděděném od BasePresenter), tak musíš v té metodě zavolat rodiče (parent::beforeRender()) – protože se jednoduše překryje a PHP vidí jen tu překrytou implementaci (např. z DefaultPresenter).
pokud mám třeba odkaz jak jsi psal User:new atd… znamená to že se bude hledat UserPresenter a v něm metoda renderNew? Případně proč mám červeně označený odkaz kde odkazuju na Default:default? Musím někde něco ještě nastavit? Přepsat atd?
První věta je správně. Odkaz s chybou máš nejspíše proto, že nemáš DefaultPresenter, či ho nemáš ve správném umístění…
- Flipajs
- Člen | 29
Aha =) tu složku v tools už vidím. Ten základ dodržuju =) akorát si přidám ten config atd =) Díky!
Nevím právě co na tom je špatně =D předpokládám že by měl hledat UserPresenter v app/presenters ne?
Problém bude možná v tom že nepoužívám toho RobotLoadera… zkusím tam nasypat ten config a další srandy. Třeba to něco provede. Díky =) (nejsem programátor… spíše alchymista =D)
Mimochdoem co znamená public $oldLayoutMode = FALSE; z vzorového BasePresenteru? Zmizí mi veškerý Layout ?překvapivě? =D
EDIT: no odkazy nefungují stále, ale stáhl jsem novou verzi Nette =D… najednou mi to všechno includuje samo, a opravdu filtry se taky spouštěj samy… Tak jeden problém vyřešen =D
Ten error v odkazech – dole v stavovém řádku: Error: Extra parametr for signal ‚TestPresenter:renderdefault‘.
presenter TestPresenter mám a v něm metodu renderDefault a citlivost na velká a malá písmena jsem zkoušel, ale nezabralo. Díky za radu.
Editoval Flipajs (27. 1. 2010 0:24)
- Ondřej Mirtes
- Člen | 1536
$oldLayoutMode = FALSE
zapne nový způsob šablon, jehož popis
vzniká tady a
o kterém David mluví v přednášce z PS v Pardubicích.
Pokud odkazy nezprovozníš (fakt doporučuji stavět na Skeletonu), tak sem hoď zip s tím, co máš, a nějak se s tím poperem.
- Ondřej Mirtes
- Člen | 1536
Už to vidím – odkazy Aktuality a Registrace hlásí toto:
error: Cannot load presenter 'Articles', class 'ArticlesPresenter' was not found in 'D:\Webs\html\otazky\document_root/../app/presenters/ArticlesPresenter.php'.
Protože ten Presenter jednoduše nemáš založený :)
A odkaz Test hlásí chybu proto, že ten kus kódu, co jsem napsal nahoře, je nefunkční :o) Ty v té šabloně musíš rozlišit případy, kdy cílová action vůbec žádné parametry nechce. Ona takhle dostane NULL parametr a považuje ho za nadbytečný a odkaz se nevygeneruje. Takže ta šablona se zesložití a ty podmínky v ní se rozvětví… bohužel.
Editoval Ondřej Mirtes (27. 1. 2010 12:33)
- Lei
- Člen | 4
Sice jsem lama, ktere ja v studovani Nette jen o kousek dal nez ty, ale
v Dokumentaci ted nekdy nedavno pribyli tutorialy. Projed si Quickstart, rekl
bych, ze tam najdes hodne odpovedi.
https://doc.nette.org/cs/quickstart
- Flipajs
- Člen | 29
Jasně. QuickStart jsem si projel už předtím, teď znova, ale odpověď jsem tam nenašel… Tak nějako nevím kde bych měl vůbec nějaké to nastavení pro paramtery odkazů atd jít… Kde se to dělá? když mám jenom jednoduché pole ‚Domů‘ ⇒ array(‚Default:default‘) tak to jede…
Nakopne mě tedy někdo kousek dál správným směrem? Nebo jsme ztracený případ? =D
- Ondřej Mirtes
- Člen | 1536
Musíš tam rozvětvit tu podmínku.
Nechce se mi to rozepisovat, tak jen náznak:
{if $item[1] != NULL}
{ifCurrent $item[0], $item[1]}<strong....
{else}{link $item[0], $item[1]}{/if}
{else}
{ifCurrent $item[0]}<strong....
{else}{link $item[0]}{/if}
{/if}
Nebo třeba někdo přijde na nějaké lepší řešení.
Editoval Ondřej Mirtes (27. 1. 2010 16:14)
- Flipajs
- Člen | 29
EDIT: vyřešeno… Ráno moudřejší rána ve tři hodiny… =D
Přeci jenom menší dotaz. Po odeslání formuláře v registraci je
lepší redirectnout na nový view kde bude nějaký blábol o úspěšné
registraci a odeslání mailu nebo redirectnout zpět na pohled s formulářem
a zobrazit nějakou hlášku nad ním? Případně jak na to?
(Stačí jen naťuknout =) díky!)
Na ty hlášky použít něco jako
{foreach $flashes as $flash}<div class=„flash {$flash->type}“>{$flash->message}</div>{/foreach} do layoutu?
Jak by to mělo vypadat v prezenteru atd?
Editoval Flipajs (30. 1. 2010 10:58)
- Ondřej Mirtes
- Člen | 1536
Redirectnout můžeš kam chceš, co ti z hlediska uživatele přijde lepší – nejrozumnější bude asi přihlašovací formulář :o)
$this->flashMessage('Úspěšně zaregistrován. Můžete se přihlásit!');
$this->redirect('Login:');
- Flipajs
- Člen | 29
Tak opět já a nějaký problém…
Tvořím formulář za pomocí komponent, tak i přes to že komponentu mám tak mi to hlásí že neexistuje :-/
<?php
class RegistracePresenter extends BasePresenter
{
protected function createComponentFormRegistraceSkupiny()
{
$form = new AppForm;
.....
$form->addSubmit('zaregistrovat', 'Zaregistrovat')
->onClick[] = array($this, 'eventFormRegistraceSkupinyClick');
return $form;
}
public function eventFormRegistraceSkupinyClick($submitButton)
{
$form = $this['formRegistraceSkupiny'];
... insert do db... funguje vše ok...
}
protected function createComponentFormRegistraceUctu()
{
$form = new AppForm;
$form->addSubmit('zaregistrovat', 'Zaregistrovat')
->onClick[] = array($this, 'eventFormRegistraceUctuClick');
}
public function eventFormRegistraceUctuClick($submitButton)
{
$form = $this['formRegistraceUctu'];
.... zpracování formuláře
}
public function actionRegistraceSkupiny()
{
//funguje all right
$this->template->display = $this['formRegistraceSkupiny'];
}
public function actionRegistraceUctu()
{
//NEFUNGUJE... možná je někde nějaká pitomá chyba. Možná jsem přehlédl nějaké pravidlo ohledně počtu továrniček na presenter nebo tak něco... PROSÍM POMOZTE! Už jsem z toho šílenej =D
$this->template->display = $this['formRegistraceUctu'];
}
}
Díky moc;)
- Flipajs
- Člen | 29
Jejda! =D Tak to mě netrklo… Díky moc =) Uchránil jsi mě od další bezesné noci kdy mě honěj $ a mračej se na mě presentery atd… =D
Mimochodem… Máte někdo v formulářích zkušenosti s Captchou? Mě se nepovedlo zprovoznit ani jednu (normoš ani 3d). Je docela pravděpodobné že byla chyba mezi klávesnicí a židlí. Nebo od nové verze nette jednoduše nefunguje?
Editoval Flipajs (8. 2. 2010 22:15)
- tombom
- Člen | 10
Ahoj chtěl jsem se zeptat, snažím se také něco vyrábět a narazil jsem na problém jak vyřešit nějaký wysiwyg editor pro obsah stránky. Když jsem zkusil navěsit TyniMCE tak je problém, že mi do DB uloží html kód který se mi na stránce pak vypíše jako text. Narazil jsem tu na pár příspěvků, kde se řeší, že html do databáze nepatří, ale už nebylo řešeno jak to teda udělat jinak…
- Patrik Votoček
- Člen | 2221
Moc jinak to v případě WYSIWYG editoru neuděláš… Pokud jde o to
escapování tak stačí dát před proměnou v Latte která ten obsah vypisuje
vykřičník tj. {!$page}
místo {$page}
.