3vrstvá aplikace v PHP/Nette
- zatomik
- Člen | 19
Ahoj,
mám takovou spíš „filozofickou“ otázku, která trochu (více) sahá za hranice Nette.
Trochu jsem hledal rozdíl mezi MVC a 3vrstvou architekturou. Chápu, že MVC ve své podstatě není architektura systému ale spíš návrhový vzor, který se často používá pouze na úrovni prezentační vrstvy. Ovšem rozdíl v MVC a 3vrstvou architekturou je také v tom, že u MVC komunikuje i model s view tím, že mu předává data zatímco u 3vrstvé architektury spolu tyto dvě vrstvy nemůžou komunikovat (obecně můžou komunikovat jen dvě sousední vrstvy).
Z toho mi vzniká otázka jestli samotné Nette implementuje MVC? Protože v Nette většinou Precenter(Controller) získává data z modelu a předává je View (template), ale nikde neprobíhá komunikace model-view. Pravděpodobně je tohle jen moje špatná domněnka, takže budu rád za objasnění.
Pokud bych připustil, že Nette implementuje MVC, jedná se tedy o 1 vrstvou architekturu. Kdybych tedy chtěl s pomocí Nette implementovat 3vrstvou architekturu, jak by to asi vypadalo? Pravděpodobně pro datovou vrstvu bych použil ORM, Nette jako samotné by fungovalo jako prezentační vrstva s implementovaným MVC a mezi to bych ještě vložil business vrstvu, která by dělala část věcí ze současných kontrolerů.
Může mi někdo ilustrovat na jednoduchém příkladu 3vrstvou architekturu s Nette, třeba vytažení tabulky z db a zobrazení ji, včetně autentizace uživatele? Chápu, že je to overhead. Podle mého chápání by to bylo, že uživatel dá požadavek na zobrazení tabulky, tím se spustí Nette Controller. Nette Controller požádá Business vrstvu o zobrazení tabulky, ta pomocí komunikace s db vrstvou ověří uživatele a v případě povolení přístupu opět komunikuje s DB vrstvou, aby získala tabulku. A tabulku vrací Nette controlleru? Tím ale nějak vypadává funkce Modelu u MVC. NEBO je druhá možnost, Nette controller dá požadavek na ověření uživatele a v případě, že je uživatel ověřen zavolá Model v MVC, který přes business vrstvu a db vrstvu získá tabulku?¨
Mám v tom trochu zmatek, tak předem děkuji, pokud to někdo pěkně vysvětlí.
- mkoubik
- Člen | 728
Do otázky jak moc Nette implementuje MVC bych nerad zabředával, protože není moc jasné, co to vlastně znamená. Původní MVC ze smalltalkových desktopových GUI aplikací fungovalo tak, že uživatel zadával povely view, to předalo informace controlleru, ten obsahoval aplikační logiku a tahal data z modelu a pak je předával do view, které je zobrazilo uživateli. Tohle je 3-tier architektuře asi nejblíž.
Pak se do věci vložily webové aplikace, kde uživatel nedává povely view, ale přímo controleru. Cestou zpět zase s uživatelem nekomunikuje view, ale controler, který mu cele view (html stránku) pošle. Buď můžeš považovat controler + šablony za view a mezi controler a hloupý model dát aplikační logiku, nebo u tlustých klientů můžeš za view považovat až javascript na straně klienta.
V případě nette je to složitější, protože díky komponentovému modelu a signálům můžeš vlastně komunikovat přímo s view.
Další rozdělení je podle toho, jestli controler jenom načítá data z modelu a strká je do view, nebo (typicky u GUI) vezme správný model (objekt), nakonfiguruje ho a celý ho předá view, které si na něm pak volá příslušné metody – takhle funguje např dibi datasource/fluent nebo Nette\Database\Table\Selection.
Z těhle všech přístupů si můžeš vybrat ten, ktrerý nejlíp vyhovuje tvým potřebám a bez problému kterýkoliv použít v nette.
- zatomik
- Člen | 19
Díky za odpověď, chápu, že z těch návrhů můžu použít jaký chci.
Spíš mě zajímalo jaké jsou mezi tím rozdíly.
Jinak podle mého názoru je MVC právě v tom případě, kdy si view
vyžádá kompletní model, který je nakonfigurovaný controlerem a ten
zpracuje.
Ve tří vrstvé architektuře bych tedy za View asi označil Nette
Controller+šablony, ty by komunikovali s business vrstvou, která vlastně
v Nette vůbec není a nad tím se postavil model, ale asi jiným způsobem
než funguje model nyní v Nette.
- Patrik Votoček
- Člen | 2221
Myslím že nejlepší pohled na to jak v Nette funguje MVC přesněji spíše MVP poskytne starší i když co do základního pochopení funkčnosti stále aktuální článek na zdrojáku .
- pawouk
- Člen | 172
Pokud chces aby jsi z view komunikoval s modelem, staci v BasePresenteru prepsat beforeRender:
function beforeRender()
{
parent::beforeRender();
$this->template->context = $this->context;
}
To jest vse. Stejne tak na to zda je uzivatel prihlasen se muzes zeptat klidne ze sablony, to mi prijde trochu blbost, ale proti gustu… Presenter tedy muzes uple vynechat…
- Filip Procházka
- Moderator | 4668
To je nejenom otřesné ale i hloupé. Nerad to říkám, ale i v šabloně jde udělat
{$presenter->context->session->getSection('foo')->var}
Ale to že to jde, neznamená, že to budeme používat!
Do šablony se předávají surová data, nebo struktury nad kterými jde iterovat. Pokud jde o výkon, můžeme tam předat objekt, který data při iteraci získá lazy. Ale nikdy však nevolat metody objektu úmyslně v šabloně!
- bojovyletoun
- Člen | 667
- Šablony by měly být deklarativní.
- Šablony chápat jako zápis, jak data vyobrazit do html. (nebrat doslovně)
- Jak zaznělo na jedné z přednášek: <q>V šablonách se neprogramuje</q>
- pawouk
- Člen | 172
HosipLan napsal(a):
To je nejenom otřesné ale i hloupé. Nerad to říkám, ale i v šabloně jde udělat
{$presenter->context->session->getSection('foo')->var}
No samozrejme ze to lze, ale pokud chcete pouzivat model v sablone, tak je to zbytecne dlouhy zapis. Jinak nez zacnete urazet ostatni, radeji si neco nastudujte o MVC, muzete zacit na zdojaku nebo na wikipedii protoze tam se dozvite zjevne pro vas zcela novou informaci, ze view se muze ptat modelu na data ;-)
Ale to že to jde, neznamená, že to budeme používat!
Do šablony se předávají surová data, nebo struktury nad kterými jde iterovat. Pokud jde o výkon, můžeme tam předat objekt, který data při iteraci získá lazy. Ale nikdy však nevolat metody objektu úmyslně v šabloně!
Toto je blbost, pokud jde o jedoducha data je zbytecne do toho zapojovat presenter a zbytecne tim zahlcujete kod, ktery nema zadnou funcni logiku.
- LM
- Člen | 206
pawouk napsal(a):
No samozrejme ze to lze, ale pokud chcete pouzivat model v sablone, tak je to zbytecne dlouhy zapis. Jinak nez zacnete urazet ostatni, radeji si neco nastudujte o MVC, muzete zacit na zdojaku nebo na wikipedii protoze tam se dozvite zjevne pro vas zcela novou informaci, ze view se muze ptat modelu na data ;-)
View se může dotazovat modelu, ale to neznamená že je rozumné v šabloně vytvářet takové závislosti, template != view, view jsou podle mě i render metody v presenteru.
- Patrik Votoček
- Člen | 2221
pawouk napsal(a):
No samozrejme ze to lze, ale pokud chcete pouzivat model v sablone, tak je to zbytecne dlouhy zapis.
Nic ti nebrání v tom udělat si:
{var $session = $presenter->context->session}
{$session->getSection('foo')->var}
Jinak nez zacnete urazet ostatni…
Asi jsem slepý ale nikde jsem nepostřehl že by HosipLan někoho urážel.
Toto je blbost, pokud jde o jedoducha data je zbytecne do toho zapojovat presenter a zbytecne tim zahlcujete kod, ktery nema zadnou funcni logiku.
Naopak toto je důvod pro existenci presenteru, který ona „složitá“ data převede na jednoduchá, která pak předá šabloně.
Nehledě na bod který zmiňuje bojovyletoun:
Jak zaznělo na jedné z přednášek:
V šablonách se neprogramuje
View vrstva v Nette je representováná metodami render[Foo] a šablonami (to že jsou metody render[Foo] součástí presenteru nechme stranou).
- Patrik Votoček
- Člen | 2221
BTW @bojovyletoun citace v Texy! se dělá takto
>>V šablonách se neprogramuje<<
- pawouk
- Člen | 172
LM napsal(a):
pawouk napsal(a):
No samozrejme ze to lze, ale pokud chcete pouzivat model v sablone, tak je to zbytecne dlouhy zapis. Jinak nez zacnete urazet ostatni, radeji si neco nastudujte o MVC, muzete zacit na zdojaku nebo na wikipedii protoze tam se dozvite zjevne pro vas zcela novou informaci, ze view se muze ptat modelu na data ;-)
View se může dotazovat modelu, ale to neznamená že je rozumné v šabloně vytvářet takové závislosti, template != view, view jsou podle mě i render metody v presenteru.
Naprosto souhlasim. Jen jsem chtel podotknout, ze ze sablony se muzeme zeptat modelu, pokud jde o trivialni dotaz, pokud je to jakkoliv slozitejsi tak je tu presenter aby to naserviroval, to je bez pochyby.
- pawouk
- Člen | 172
Patrik Votoček napsal(a):
pawouk napsal(a):
No samozrejme ze to lze, ale pokud chcete pouzivat model v sablone, tak je to zbytecne dlouhy zapis.
Nic ti nebrání v tom udělat si:
{var $session = $presenter->context->session} {$session->getSection('foo')->var}
Jinak nez zacnete urazet ostatni…
Asi jsem slepý ale nikde jsem nepostřehl že by HosipLan někoho urážel.
viz „To je nejenom otřesné ale i hloupé.“
Toto je blbost, pokud jde o jedoducha data je zbytecne do toho zapojovat presenter a zbytecne tim zahlcujete kod, ktery nema zadnou funcni logiku.
Naopak toto je důvod pro existenci presenteru, který ona „složitá“ data převede na jednoduchá, která pak předá šabloně.
Toto mi neprijde ani slozite, ani programovani, pokud by to bylo slozitejsi pak by to samozrejme patrilo do presenteru. (strankovani nechme stranou)
$presenter->context->article->all
Nehledě na bod který zmiňuje bojovyletoun:
Jak zaznělo na jedné z přednášek:
V šablonách se neprogramujeView vrstva v Nette je representováná metodami render[Foo] a šablonami (to že jsou metody render[Foo] součástí presenteru nechme stranou).
- Filip Procházka
- Moderator | 4668
To je nejenom otřesné
Nečistá praktika, to už jsme si ujasnili
ale i hloupé.
Je to hloupé, protože píšeš něco, co psát nemusíš. Zde hloupé, čti jako zbytečné, pokud tě to uráží.
Jinak,
cokoliv co nepochopí kodér, bez znalosti programování, je programování.
A tohle
{var $session = $presenter->context->session}
{$session->getSection('foo')->var}
prostě je programování. Základní cykly atd kodéra naučíš, ale proč by se měl starat o to, že aplikace má nějaké sessions? To je prostě WTF!
Co se týče jednoduchých dotazů. Záleží na tom, jak to nastavíš. Sleduj tohle
class Data extends Nette\Object implements IteratorAggregate
{
private $query;
public function __construct(DibiFluent $query)
{
$this->query = $query;
}
public function getIterator()
{
return $this->query->getIterator();
}
}
Magickou třídu teď použiji
class ArticlePresenter extends BasePresenter
{
...
public function renderView()
{
$query = $this->context->db->select('*')->from('articles');
$this->template->articles = new Data($query);
}
}
V šabloně pak iteruješ
{foreach $articles as $article}
{$article->title}
{/foreach}
Získáš tím
- lazy volání dotazu ⇒ výkon a můžeš cachovat
- kodér nemusí volat metody ⇒ neprogramuješ v šabloně
Můžeš si to samozřejmě zabalit do modelu a nebo mít jinou formu lazy výsledků, to je jedno. Ale ne-programovat v šablonách lze bez problému a mělo by se to dodržovat.
PS: Do šablony můžeš samozřejmě rovnou předávat i objekt
DibiFluent
, ale od čeho máme zapouzdření, že.
Editoval HosipLan (3. 10. 2011 19:44)
- pawouk
- Člen | 172
Lopata napsal(a):
OT: Myslím, že kodér instrukci
cokoliv uvnitř složených závorek je důležité a prostě na to nesahejpochopí velmi dobře… :-)
Moje řeč, navíc moje praxe ja taková, že kodér dodá pouze html, kde jsou nějaká testovací data (napsaná natvrdo) a programátor pouze nahradí text za {…} a je to.
- romiix.org
- Člen | 343
pawouk napsal(a):
Lopata napsal(a):
OT: Myslím, že kodér instrukci
cokoliv uvnitř složených závorek je důležité a prostě na to nesahejpochopí velmi dobře… :-)Moje řeč, navíc moje praxe ja taková, že kodér dodá pouze html, kde jsou nějaká testovací data (napsaná natvrdo) a programátor pouze nahradí text za {…} a je to.
Tiež tak pracujeme.