Autor Zpráva
Pavel Straka
Profil
Dobré odpoledne, rád bych požádal o radu zkušenějších. Chtěl bych vytvořit web (nepodstatné o čem), kde bude pevně oddělena strana programovací a strana výpisu - myslím to tak, že bude pevně naprogramován nějaký systém a zároveň bude snadné měnit vzhled. Doufám, že je pochopitelné, jak to myslím, nevím, jak to přesně popsat, a to je vlastně důvod, proč sem píšu. Mám pocit, že na podobném principu funguje většina e-shopů typu Zencart apod. Mohl by mi prosím někdo poslat odkaz, kde je vysvětlené, jak toto funguje?

Děkuji
Alphard
Profil
Latte je jeden z nejlepších šablonovacích sytémů, ale je tam závislost na Nette.
Zde jsem se kdysi snažil popsat základy.
Jednoduchý template systém kolegy Jokera.
Pavel Straka
Profil
Děkuju, to využití str_replace se mi zamlouvá.
Alphard
Profil
Pavel Straka:
Jestli vám to nebude vadit, rád bych v toto vlákno (příhodné téma) trochu zneužil pro diskusi o novém příspěvku do FAQ. Ocením i váš názor a všecho ostatních, jestli by vám to bývalo pomohlo, nebo jestli vám tam něco chybí.

Začal jsem to psát o šablonách, ale rychle jsem zjistil, že je potřeba nejdříve trochu rozepsat MVC. Takže tady je pracovní verze, budu rád za připomínky a názory. Kolegové moderátoři samozřejmě mohou hned upravovat a doplňovat.


MVC (MVP)

Za zkratkou MVC se skrývají názvy tří základních vrstev aplikace: Model, View a Controller. V pojetí Nette je Controller nahrazen Presenterem.
Rozčlenění (nejen) větší aplikace na několik vrstev nám přináší mnoho výhod.

(Obrázek znázorňující MVP v Nette)

Z obrázku je patrné, že uživatel požádá presenter o danou stránku (za tímto požadavkem si představte konkrétní url, často s parametry, např. http://djpw.cz/2111). Router z toho pochopí, že uživatel požaduje zobrazení vlákna s id 2111.
Nyní si presenter vezme od modelu potřebné informace. Pod modelem si na webu můžete představit třídy zprostředkující komunikaci s databází.
Na závěr se získáná data předají šablonám.

Velmi jednoduchá implementace presenteru by mohla vypadat takto:
public function renderThread($id) # metoda renderThread se stará o vykreslení vlákna na fóru, $id vlákna jí předá router
{
  $modelThreads = new Threads; #nyní bychom (zlášť v Nette) použili DI, klasicky by se instance vytvářela někde v konstruktoru, ale pro jednoduchost takhle
  $threadData = $modelThreads->getThread($id); #nyní máme všechny potřebné informace pro vykreslení vlákna
  
  $this->template->thread = $threadData; #předání proměnných do šablony
  $this->template->user = $this->user->getBaseInfo(); #předání informací o přihlášeném uživateli do šablony
}

Výhody tohoto členění:
• Každou vrstvu lze samostatně upravovat, o každou se může starat někdo jiný. Např. o šablony kodér, o zbytek programátor.
• Znovupoužitelnost kódu, modelovou třídu Threads můžeme snadno použít jinde.
• Jednoduché vytváření různých výstupů, snadno bychom mohli vytvořit třeba RSS jen změnou šablony.

Pull šablony
Stručně shrnuto, router analyzuje URL a zavolá metodu controlleru, která prostřednictvím modelu načte data a předá je view vrstvě k vykreslení. Tento workflow se hodí především pro hlavní obsah stránky, tedy obsah závislý na url, může to být článek, vlákno fóra, obrázek galerie.
Někdy se ale setkáme se situací, kdy popsaný model nestačí na žádané vykreslení stránky. Můžeme požadovat určité komponenty (widgety), které se vykreslují na různé stránky nezávisle na url, je to např. anketa, nejnovější příspěvky na fóru, seznam nejčtenějších článku apod. V této chvíli je jednodušší dát na vhodné místo v šabloně kód požadující načtení komponenty {control ankteta} a až v této chvíli si komponenta načte a zobrazí data. Průběh načtení je obrácený oproti předchozímu.
Implementace tohoto směru může být mírně složitější.

Výhody:
• Aplikační logika controlleru se nemusí starat o méně podstatné části stránky, které by byly často duplicitní. Načítání až na základě požadavku tady zjednodušuje návrh aplikace.
Nevýhody:
• Pokud nedržíme dosavadní vypsaná data na bufferu, začne se komponenta zpracovávat až po vykreslení části obsahu. V tuto chvíli je pozdě na různá přesměrování, komplikuje se výpis chyb.

Z předchozího plyne, že pokud něco selže, můžeme si dovolit komponentu nevykreslit (a nemáme ani moc možností udělat něco jiného).
Aplikaci lze navrhnout k potlačení nevýhod, ale za cenu komplikovanějšího controlleru, což složitostí přesahuje FAQ.

(Presenter v Nette)
Komponenty v Nette, příklad, jak vytvořit plnohodnotné komponenty.

Tento příspěvek je pouze velmi lehké nastínění problematiky, dále můžete pokračovat na Úvod do architektury MVC případně na další články zdrojáku s nálepkou MVC.

Šablony

Základní představu o šablonách (jestli vůbec nevíte, co to je) jsem se snažil popsat již dříve.
Princip, tedy oddělení prezenční vrstvy je z ukázky patrné, ale zároveň vás asi napadne, že v takové šabloně toho moc neuděláte. Už i výpis článků z pole (tedy pomocí nějakého druhu cyklu) by byl velký problém. Proto vznikly mnohem složitější a mocnější šablonovací systémy. Vyšší složitost šablon ale nemá na rychlost vliv, protože šablona samotná se překládá na klasický soubor s php částmi <?php ?>, který je pak includován do aplikace. Proměnné se často z objektu nebo pole dat pro šablony předávají pomocí extract().

V současnosti je jedním z nejlepších Latte, které je současní Nette. Pokud hledáte nezávislý systém, může pomoci např. Twig nebo Smarty. Tyto systémy už podrobně popisovat nebudu, následujte odkazy na stránky konkrétních projektů.
Mastodont
Profil
Alphard:
Doplnil bych, že existují dva druhy šablon, push a pull. Co ty uvádíš ve svém příkladu, jsou push šablony, kdy workflow vypadá takto:
- připravím data
- inkluduji šablonu obsahující placeholdery pro data

Tyto šablony jsou IMHO vhodné hlavně pro hlavní obsah stránky, který je dán URL, umožňují totiž vytvořit jednoduchý řetězec "router analyzuje URL -> model načte data ->view je zobrazí".

Pull šablony mají otočený workflow:
- inkluduji šablonu
- šablona si načte data a zobrazí je
Tohle se hodí třeba u widgetů, které nejsou striktně vázány na URL, třeba box s nejnovějšími příspěvky apod. K vidění hojně třeba ve Wordpressu.
Alphard
Profil
[#5] Mastodont
Děkuji za názor, aspoň někdo se ozval.
Nyní jsem doplnil tvůj návrh, ale nevím, jestli to není příliš komplikované a změna k horšímu. Z původního, myslím docela přehledného, příspěvku je najednou poměrně komplikovaný návrh struktury, který začátečníka zmate a působí dojmem, že neexistují žádné jistoty :-). Přemýšlím, že pull šablony dám někam samostatně a jen je odkáži.

Nějaké další návrhy, úpravy?
Petr ZZZ
Profil
Všiml jsem si dvou překlepů: DI před klasicky, Presener. (Tedy, předpokládám, že DI je překlep, ale možná není, nevím.)
(Prosím později smazat tento můj příspěvek.)

(OT - dělám něco blbě nebo superkotva nezaměří či neobarví text v pre?)
Alphard
Profil
DI překlep není, je to zkratka Dependency injection, Presener jsem opravil, dík.
panther
Profil
Petr ZZZ:
předpokládám, že DI je překlep
nemyslím si
Petr ZZZ
Profil
Alphard, panther: Díky.
Alphard: Nechceš tvůj nebo pantherův odkaz na dependency injection doplnit do #4 a odmazat šum od #7? (Když už šumím, ještě jeden překlep :)
Alphard
Profil
Petr ZZZ:
Nechceš tvůj nebo pantherův odkaz na dependency injection doplnit do #4
V pre neudělám odkaz, je to jen poznámka na okraj, pochopení DI je složitější než MVC, nevím, jestli to nesmazat.

odmazat šum od #7
Tohle vlákno jsem ukradl, ale původní problém je vyřešen a teď ho beru jako diskusní. [#4] časem zkopíruji do FAQ.

Když už šumím, ještě jeden překlep
Opraveno, já to, abych pravdu řekl, od února nečetl.
Jan Tvrdík
Profil
Alphard:
Moc se mi ten popis MVC nelíbí. Nevěřím, že to z toho někdo pochopí.

Router z toho pochopí, …
Kde se tam nejednou vzal router?

Nyní si presenter vezme od modelu potřebné informace.
Před chvíli ses bavil bavil o nevysvětleném routeru a teď jsem najednou u presenteru, což pořád nevím co je? A co je to sakra ten model? Co jsou to ty potřebné informace?

Velmi jednoduchá implementace presenteru by mohla vypadat takto:
To vypadá, jako by presenter byl jedna metoda.

Místo Threads použij alespoň ThreadsModel.

Dál už mě to nebavilo číst.

nevím, jestli to nesmazat
Smaž to. Začátečník z toho stejně nic mít nebude.
Alphard
Profil
[#12] Jan Tvrdík
Cílem bylo udělat to stručně, pro někoho, kdo to třeba hned nechce programovat, ale chce si udělat představu a nechce číst seriál pěti článků.
Nepochybně tam je hodně nejasností, ale to by muselo být 10x delší. Mám to podrobněji dopsat? Nebo odkázat jinam?
Petr ZZZ
Profil
Alphard:
pochopení DI je složitější než MVC, nevím, jestli to nesmazat
Já bych to nemazal, ale neškodilo by to vypsat nebo doplnit vypsané do závorky. Dependency injection čtenáře spíš napadne hledat než DI – já to neznal a myslel jsem si, že to má být ID. (Neznalý člověk hrozně těžko odhaluje překlepy v odborném textu a nachází-li je v běžné řeči, očekává je i v odborné části, z čehož plynoucí nejistoty ztěžují učení.)
romulus
Profil *
Když už je tdy řeč o těch šablonách. Co jsem nalezl na různých webech, tak je to použitelné, když se struktura nemění, ale jak se řeší třeba výpis do tabulek, kde se mění počet řádků/sloupců popřípadě DIVů?
Alphard
Profil
[#15] romulus
Šablonovací jazyk disponuje podmínkami, cykly a makry, které umožňují vykreslit cokoliv. Mohu-li konkrétně ukázat třeba Latte, je zřejmé, že možnosti jsou bohaté.
panther
Profil
romulus:
kdyby byl obsah statický, nepotřebuješ na něj šablonovací systém, CMS, nic.

Další, a hodně užívaný šablonovací systém, je Smarty, manuál.

Vaše odpověď

Mohlo by se hodit

Odkud se sem odkazuje


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: