Jen pro trpělivé – lamka potřebuje poradit se vším

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

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)

_Martin_
Generous Backer | 679
+
0
-

Ahoj, mohl bys přesně popsat strukturu webu, jakou bys chtěl mít? Na konkrétním příkladě se lépe vysvětluje=)

Ondřej Mirtes
Člen | 1536
+
0
-

Čá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
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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!

LuKo
Člen | 116
+
0
-

To Flipajs: Mrkni na videa, která Ti Ondra Mirtes linkoval, pomohou ti se zorientovat v naprostých základech. Sice se tam spousta věcí opakuje, zkouknutí všech zabere dost času, ale zase Ti věci tam probírané lépe vlezou pod kůži.

Ondřej Mirtes
Člen | 1536
+
0
-

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 :)

22
Člen | 1478
+
0
-

hehe, diky za link na PHP forum, ani jsem o něm nevěděl!

despiq
Člen | 320
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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 RobotLoaderu 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
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

$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.

Flipajs
Člen | 29
+
0
-

Tak jsem to celé zazipoval a je to zde

Zatím díky (PS: myslím že to mám podle skeletonu)

Jak mi jde odkazovat tak je například default/test tedy na teplates default/test.phtml

Editoval Flipajs (27. 1. 2010 12:04)

Ondřej Mirtes
Člen | 1536
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

Aha, jasně. Hledal jsem v tom složitosti. Díky =)

Flipajs
Člen | 29
+
0
-

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
+
0
-

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
+
0
-

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;)

redhead
Člen | 1313
+
0
-

u createComponentFormRegistraceUctu ti chybí return $form;

Flipajs
Člen | 29
+
0
-

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
+
0
-

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
+
0
-

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}.