Minule jsem ukazoval, jak lze s Nette stavět statické stránky. Ne náhodou jsem začal právě tímto tématem. Statické stránky a technika „dědění“ jsou totiž základním pilířem budování webového sídla. Je na webovém architektovi, aby připravil návrh website, grafik společně s HTML kodérem mohou pilovat vizuální podobu stránek a programátor je oživuje. Nette plně podporuje tuto pokrokovou filozofii skupinového vývoje.
Troška terminologie nikoho nezabije
Začínáme se věnovat oživování stránek, opusťme tedy pojem „statické stránky“. Jen by nás mátl.
Nette podporuje stránky zapsané nejen v jazyce XHTML, ale i HTML a XML (např. RSS kanály). Místo neobratného „HTML-XHTML-XML stránky“ budu dále používat termín dokumenty.
Dokument je tvořen stromem elementů. Program může s touto hierarchií dále pracovat prostřednictvím tzv. DOM.
Základní jednotkou oživování dokumentů je komponenta. Jde
o třídu (resp. objekt, podle kontextu), která je potomkem
Component
. Speciálním druhem komponenty je stránka (třída
Presenter
). Komponenty tvoří stromovou strukturu a jejím
kořenem je vždy nějaký následník třídy Presenter
. Tuto
strukturu budu označovat jako COM. Nemá
to nic společného s technologií COM od Microsoftu.
Všechny třídy v Nette mají prefix N – od PHP
5.3 leží ve jmenném prostoru Nette
.
Trojí hierarchie
Pro rekapitulaci, ve hře jsou tři různé hierarchické struktury:
- Website, tedy hierarchie dokumentů
- strom XML/HTML elementů tvořících dokument
- strom komponent oživující dokument
Website je adresář obsahující dokumenty a případně i další podadresáře. Hierarchie, kterou mám v bodě č. 1 na mysli, však není tvořena rozdělením dokumentů do podadresářů, ale oním děděním popsaným v minulém díle!
Jak se oživuje dokument
Je třeba vytvořit nějakou hierarchii komponent a tu propojit s dokumentem. Pro začátek si vystačíme s nejjednodušší hierarchií, tvořenou jedinou komponentou, tedy komponentou stránky. A protože dokumenty jsou základním pilířem Nette, tam právě dokumentu musíme říci, kde je ukryt oživovací kód. K tomu použijeme hlavičku:
<?nette class="MyPage" ?>
<html>
<head>
<title>Don't know...</title>
</head>
<body>
<p>Hello World!</p>
</body>
</html>
V atributu class
je přípustná i hodnota auto
,
pak bude název třídy určen automaticky z názvu stránky.
Třída MyPage
může vypadat třeba takto:
<?php
class MyPage extends Presenter {
function render($document)
{
$document->head->title = 'Nette example';
}
}
Uvedený kód přes DOM přistupuje zpátky k dokumentu a změní obsah
elementu <title>
. Jednoduché, že?
Nyní ve stránce použijeme komponentu, třeba TGrid:
<?nette class="MyPage2" ?>
<html xml:lang="en" lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:com="https://texy.info/nette">
<head>
<title>Nette demo</title>
</head>
<body>
<com:TGrid id="grid1" />
</body>
</html>
A opět příklad MyPage2
:
<?php
class MyPage2 extends Presenter {
function render($document)
{
$document->getElementById('grid1')->atribut = 'hodnota';
}
}
Dosud vše jasné? To je dobře. Možná si ale říkáte, proč jsem
nepoužil zápis $this->grid1->...
. Je to prosté. DOM a COM
jsou dočista jiné struktury. Takže nyní prosím zpozorněte.
Vazba DOM ↔ COM
Zatímco COM reflektuje potřeby programátora, DOM tvoří HTML kodér. Dva naprosto neslučitelné zájmy. A Nette jim dopřává maximální volnost. Tedy, pokud totálně překopu vzhled stránky, změním tím k nepoznání DOM. Ale je nutné, aby kvůli tomu programátor musel předělávat aplikaci? Ne! Programátor má své COM a to se mu nezměnilo.
Příklad: tvoříme blog.
Nejprve pohledem programátora: Titulní stránku představuje pět
článků a nějaký stránkovací mechanismus pro přístup k dalším
článkům. Na to se nám výborně hodí komponenta TDataGrid. Jde o jeden logický celek, který plně
zvládne požadovaný úkol. Programátor si ho v COM zpřístupní pod názvem
grid1
, tedy $this->grid1
. V metodě
initialize()
ho napojí na zdroj dat a nastaví stránkování po
pěti záznamech.
A nyní pohledem webdesignera: Komponentu DataGrid tvoří dva grafické celky:
- zobrazení záznamů, v našem případě jednotlivých článků
- zobrazení „stránkovátka“
Nette není tak hloupé, aby obojí zobrazovalo napevno za sebou. Naopak – každý z těchto celků si můžeme umístit libovolně na stránce. Ba co víc – webový architekt usoudí, že stránkovátko by mělo být nejen na spodku stránky, ale i nahoře. Ovšem to horní by mělo být méně výrazné, že.
Dejme si to dohromady. Máme komponentu TDataGrid. Ta nabízí dvě
renderovací polohy, říkáme jim parts. Jednu z těchto poloh chceme
na stránce zobrazit dvakrát. Dále víme, že konkrétní instance této
komponenty se jmenuje grid1
.
Jak bude vypadat HTML kód?
<?nette class="MyPage3"?>
<html>
<head>
<title>Blog</title>
</head>
<body>
<h1>The best blog</h1>
<div>
<com:DataGrid.pager name="mygrid" id="horni" />
<hr />
<com:DataGrid.items name="mygrid">
...
...
</com:DataGrid.items>
<h3>Dále pokračujte:</h3>
<com:DataGrid.pager name="mygrid" />
</div>
</body>
</html>
Jedna komponenta v COM, tři zobrazení v dokumentu. Spojuje je atribut
name
. Tím, že jsem horní „stránkovátko“ opatřil
id
, mohu s ním dále pracovat prostřednictvím DOM. A třeba
nastavit mu menší provedení, jak požadoval grafik.
Komentáře
Vojtěch Kopal #1
S každým článkem jsem natěšenější. :) Po pravdě, už se dávno nemůžu dočkat.
Těším se až to vyzkouším, takhle to vypada jako dobry nastroj.
Petr Weida #2
Co pak to je na https://phpfashion.com/category/nette/ ?? Škoda, že to není na začátku zamíchané… 😉
Reg #3
#2 Petře Weido, Hm, funguje to zajímavě když se parametr game-round změní na nějakej text… Jak to je udělaný?
Tomik #4
#3 Regu, Pomocí Nette, pochopitelně… 🙂
Reg #5
#4 Tomiku, Njn, a k čomu to je dobrý takováhle legrácka?
syntax_error #6
#5 Regu, Abychom se při čekání na Nette nenudili… 😛
PiDiBi #7
cim dal vic mi to pripmina MS .NET
thingwath #8
T smrdí Borlandem. Asi budu zvracet.
wizard #9
Nette se jeví jako opravdu silný systém.
Borek #10
Objektový model vypadá sympaticky, jen mě při čtení napadlo pár věcí:
Jinak držím palce, Nette zatím vypadá zajímavě.
llook #11
#8 thingwathu, Já se s tím T poprvé setkal u Turbo Vision. To sice bylo od Borlandu, ale důvod ke zvracení nevidím. Šlo o velice dobrý UI toolkit a takřka průmyslový standard (k vidění byl třeba u M602 nebo účetnictví Pohoda).
Taktéž pochopitelně nechápu, jak to T dokázalo prorůst i do jazyků, kde se neříká type, ale class.
hvge #12
Mne sa to bije s Template z C++ :) No jo, tazko sa da vyhoviet kazdemu :)
wizard #13
#10 Borku, Ano, někde jsem si v článku všiml, že je tam T jako Třída. :)
johno #14
DGX: Nechcem tu vyvolať flamewar o tom, že je to prasácke, ale
<?nette
asi zloží PHP parser pri zapnutomshort_tags_open
.Naopak chválim možnosť rozdeliť komponent na viac častí. Kde sa definuje šablóna komponenty?
#10 Borku, Domnievam sa, že vďaka absencii namespace v PHP to slúži len na odlíšenie Nette od iných knižníc. Ak je táto domnienka správna, tak som za prefix N.
#10 Borku, Premature optimization is the root of all evil. Osobne si myslím, že šablóny sa predgenerujú do nejakého PHP medzikusu a nacachujú. Čiže ten celý poprask okolo generovania a spracovávania šablón, komponentov,… v Nette sa deje len raz a to keď sa niečo zmení.
Pomalosť PHP parsera je to posledné čo by ma trápilo.
johno #15
#14 johno, Hopla, to
short_tags_open
beriem späť. Nette asi neparsuje PHP parser.thingwath #16
#11 llooku, Jenže dnes se píše rok 2006 a máme 21. století. Já hlavně nechápu, proč je třeba před ta jména vůbec něco dávat. To se dělá v jazycích, kde nemají žádné jmenné prostory ani balíčky ani nic podobného a to snad PHP není, nebo jo?
Jakub Podhorský #17
#16 thingwathu, PHP namespace nemá…imho se mi to zdá jako zbytečnost tam dávat ty předpony když je to framework…pochybuju že k tomu bude někdo používat další „systém“(nebo jak to nazvat) třetí strany…možná tak nějaký další vlastní balíčky ale tam bych konflikty názvů nepředpokládal
cita #18
#17 Jakube Podhorský, ja bych nejakou simulaci namespace uvital. V jinych jazycich to ma sve duvody( http://en.wikipedia.org/…(programming) ) a proc si je neprenest i do php 4 a 5, v 6 tusim ze maji byt nativne
llook #19
Pro nějaký prefix bych byl. Třeba kolizi s názvem třídy
Page
si představit dokážu, s třídouNPage
je to lepší.Jmenné prostory měli být už v PHP5 a dokonce i malou chvilku byli, i když dost mizerně navrhlý. Ale už zase nejsou. ☹
Marek #20
#7 PiDiBi, na tohle musím reagovat.
dgx už dřív psal, že Nette trošku .NET připomíná, že má komponenty a události. Jenže já s každým dalším článkem žasnu, jak práve .NET nepřipomíná!
Já jsem programátor ASP.NET. KDysi jsem žasnul nad runat=„server“, komponentou přímo v HTML kódu atd. Dnes ale zírám, jak někdo to zvládá daleko elegantnějí. Rozdělení COM – DOM je geniální tah. To pochopí každý, kdo kdy tvořil složité administrační rozhraní. I když teda zkratku COM bych fakt změnil. Komponenta rozdělená na více částí taky. V ASP.NET prakticky nelze použít datagrid pro hlavní stránku blogu, to by udělal jen začátečník. Jenže v Nette to má logiku.
K PHP se asi nedostanu, ale tomuhle musím fandit, to je skutečně revoluční přístup.
David Grudl #21
#8 thingwathu, #10 Borek Všechny třídy musí začínat nějakým prefixem, neboť v PHP je jmenný prostor děsně zaplácaný. Definovaných 1300 funkcí, 1340 konstant, 75 tříd a 7 rozhraní ještě před vykonáním prvního řádku kódu – a to používám jen několik extensions.
Váhám mezi T a N. Zatím používám T, jako hold Borlandu. Jejich programátoři v roce 1995 napsali VCL pro Delphi, které je v mnoha směrech inspirací pro Nette. Nikoliv tedy .NET, ale Delphi. Nejspíš ale přejdu na N.
#10 Borku, Nette je výkonné dostatečně 🙂
#20 Marku, Když jsem studovat ASP.NET, tak jsem se divil, proč je tolik věcí nedotažených nebo zbytečně omezujících. V tomto směru je Nette trošku jinde.
Borek #22
Nemám stejný pocit jako #20 Marek nebo #21 David Grudl, že by některé věci v ASP.NET byly nedotažené a že Nette je řeší líp (vím, že přímo tato formulace nezazněla, ale chtě nechtě mi to tak vyznívá).
Nette jde cestou absolutní flexibility, ASP.NET cestou rozumného komprimisu mezi řádem a flexibilitou:
Prostě Nette na to jde jinak, v určitém smyslu sympaticky, v určitém smyslu trochu chaoticky. Ale uvidíme, těžko soudit podle dvou třech článků :)
David Grudl #23
#22 Borku, S tím v podstatě souhlasím. Až na tu chaotičnost – naopak, vyšší flexibilita vede k lepšímu řádu, neboť nemusíme nic „hackovat“.
Vyhněme se akademickým diskusím a porovnávání Nette a ASP.NET. Porovnávat bude možné třeba za rok, až se vše v praxi vyzkouší a objeví slabá místa. Zatím to nemá smysl.
hvge #24
Len taka hnidopisska otazka, nemas tam v jednom z tych prikladov chybu?
V otvaracom tagu je items oddelene pomlckou a v uzatvaracom dvojbodkou.
johno #25
id="grid1"
a inokedyname="grid1"
.#23 Davide Grudle, Asi si prehliadol moju otázku. Kde sa definuje šablóna komponenty?
Borek #26
#23 Davide Grudle, Co naplat, děláš komponentně-událostní framework, tak se asi srovnání s jinými komponentně-událostními frameworky nevyhneš :)
To je hodně odvážné tvrzení, ale vypadá to, že mu opravdu věříš :)
David Grudl #27
#24 hvge, to je samozřejmě překlep.
#25 johno,
id
je jedinečný identifikátor v DOM, zatímconame
je jedinečný identifikátor v COM. Tedyid
mi identifikuje konkrétní místo v dokumentu, zatímconame
určuje jméno komponenty. Proto víc „oblastí“ má stejnéname
.Té otázce ohledně šablony komponenty nerozumím…
#26 Borku, Dobře, zkusme si tedy zrovna onen příklad s datagridem a dvojím stránkováním. Jak se tohle konkrétně udělá v .NET? Vážně nevím, jen se ptám.
johno #28
llook #29
#26 Borku, Já tomu také věřím. Ale je to asi jako spor mezi zastánci dynamického a statického typování (líbí se mi Van Rossumova argumentace: „Jestliže se podíváte na velké programy napsané v silně typovém jazyce, všimněte si, že mnoho času je stráveno právě obcházením typového systému.“).
David Grudl #30
#28 johno, Aha, rozumím.
Každá komponenta může mít tolik šablon, kolik má renderovacích částí. Šablony komponent fungují podobně, jako „velká šablona“ stránky. Nakonec stránka je také komponenta. Šablona se tedy naparsuje z přiloženého .HTML souboru a je komponentě dostupná přes DOM.
Samozřejmě komponenta nemusí vůbec šablonu využívat a sama si generovat vlastní (X)HTML výstup.
Také je možné komponentě vnutit novou šablonu. Třeba u takového Repeateru se to rovnou předpokládá.
Borek #31
#27 Davide Grudle, GridView má vlastnosti PagerSettings, PagerStyle a PagerTemplate, které do značné míry umí řadu potřeb uspokojit. Pokud by bylo opravdu nutné mít jednu část komponenty úplně jinde něž druhou část komponenty, v ASP.NET by se to asi nejlíp řešilo vytvořením nové komponenty (např. Pager), která by po kliknutí na „předchozí“ a „další“ volala odpovídající metody GridView.
Ale jak jsem řekl, nemyslím, že je roztroušení jedné komponenty na více míst častým požadavkem. Kdyby bylo, patrně by to všechny současné komponentové technologie podporovaly (a mně se nevybavuje žádná, která by to dělala).
johno #32
#30 Davide Grudle, Rozumiem. Čo je to ten Repeater?
A ďalšia otázka. Ako sa chystáš cachovať template, v ktorom potom máš
$document->head->title = 'Nette example';
Doteraz som bol v tom, že Nette šablóna sa prekladá do PHP medzikusu, ale toto ma dosť zmätlo.David Grudl #33
#31 Borku, a tohle mi právě připadá chaotičtější. Rozdělování komponent ti jako častý požadavek nepřipadá jen z toho důvodu, že to v ASP.NET nelze řešit elegantně.
Podívej se na to prosím z nadhledem:
Já vycházím s představy, že tyto dva pohledy si mají žít vlastním životem, protože se snaží vyhovět diametrálně jiným požadavkům. Naopak jiné frameworky vnucují souhru – jedna komponenta = jedna oblast v HTML. Mě to připadá velmi omezující.
#32 johno, Kešování funguje na více úrovních. Ta nejmenší odpovídá určitému elementu šablony. „Přepočítává“ se jen „zasažená“ část DOM. Dále je možné kešovat na úrovní komponenty (resp. její části) a tedy i celé stánky.
hvge #34
#33 Davide Grudle, Prepocitava sa len zasazena cast no znie to genialne, ale fakt ze sa tesim na implementaciu :)
johno #35
#33 Davide Grudle, Mám to chápať tak, že šablóna je vlastne plain text a keď zavolám
$document->head->title
, tak až vtedy sa na ňu pustia šialené regexpy, čo sa ktitle
tagu prekúšu a zmenia jeho obsah? Hmm, to sa mi nejako nezdá.Borek #36
#33 Davide Grudle, Aby nedošlo k mýlce, já neříkám, že na to jde Nette špatně. Jde na to jinak, vidím výhody jeho přístupu, ale i drobné nevýhody.
Zpět k tématu: ať už se jedná o webový nebo desktopový vývoj, často je komponenta jednotka zobrazení víc než cokoliv jiného. Existují sice výjimky, jako třeba nevizuální komponenty, ale více méně všude platí, že komponenta je něco, co umí renderovat svou podobu a dělá to na jednom definovaném místě. Delphi, ASP.NET, Windows Forms, XAML, Swing, SWT, … – všichni na to jdou stejně. Nette na to jde jinak.
David Grudl #37
#36 Borku, To máš pravdu. A v podstatě odsud také pramení má tehdejší kritika ASP.NET:
Nebo jinak řečeno, co na desktopu zas tak nevadí, může hodně vadit na webu. Delphi & spol. doslova plývají pamětí, jejich (teoretický) viewstate rychle nabývá obřích rozměrů. Ale nevadí to, protože megabajt paměti je nesrovnatelně „rychlejší a levnější“ než megabajt přenosu přes internet.
#35 johno, Ve skutečnosti je to nádstavba nad DOMNode, což je nejrychlejší způsob práce s XML dokumenty v PHP. Parsování je rychlejší než unserialize nějaké vlastní struktury.
Borek #38
#37 Davide Grudle, Nejde o paměť, nejde o přenášená data, jde o princip. Komponenta v pojetí Nette je něco jiného než komponenta v pojetí zbytku světa, což může znamenat některé výhody proti všem jiným GUI frameworkům, ale taky určité zmatení pro vývojáře.
Nechci Nette nějak dopředu hodnotit, jsem opravdu zvědavý, co z toho nakonec vyleze. Tyhle poznámky píšu jen jako „early feedback“, abys znal co nejvíc názorů na svou práci (asi by ti moc nepomohlo, kdyby ses v komentářích 20× dočetl něco jako „Už se nemůžu dočkat, Nette bude super!“).
MiSHAK #39
Menší rada radši zřiďte samostatné fórum pro Nette, IMHO v komentářích už tyto dotazy nemají co dělat…
noname #40
nejsem kdovíjaký programátor v php, tak se omlouvám za možná blbý dotaz, ale jestli to chápu dobře, tak Nette projde text, najde tam odkazy na své funkce, ty pak třeba regexpem nahradí za jejich ekvivalenty v php a výsledný php kód se provede. Ten framework je tedy jakési „php texy“. Můj dotaz tedy zní – bude možné v nějakém debug módu zjistit ten výsledný php kód, který je realizován?
enoice #41
#40 noname, to jde bez závislosti na Nette…
Tento článek byl uzavřen. Už není možné k němu přidávat komentáře.