MVC aplikace & presentery
Seznámíme se s tím, jak se vlastně v Nette Framework tvoří aplikace. Po přečtení budete znát:
- MVC, adresářovou strukturu a soubor
bootstrap.php - co jsou to presentery a akce
- jak se používají šablony
- co jsou persistentní parametry
Model-View-Controller (MVC)
Model-View-Controller je softwarová architektura, která vznikla z potřeby oddělit u aplikací s grafickým rozhraním kód obsluhy (controller) od kódu aplikační logiky (model) a od kódu zobrazujícího data (view). Tím jednak aplikaci zpřehledňuje, usnadňuje budoucí vývoj a umožňuje testování jednotlivých části zvlášť.
Model
Model je datový a zejména funkční základ celé aplikace. Je v něm obsažena aplikační logika. Jakákoliv akce uživatele (přihlášení, vložení zboží do košíku, změna hodnoty v databázi) představuje akci modelu. Model si spravuje svůj vnitřní stav a ven nabízí pevně dané rozhraní. Voláním funkcí tohoto rozhraní můžeme zjišťovat či měnit jeho stav. Model o existenci view nebo kontroleru neví.
Pojem Model představuje celou vrstvu, nikoliv samostatnou třídu.
View
View, tedy pohled, je vrstva aplikace, která má na starost zobrazení výsledku požadavku. Obvykle používá šablonovací systém a ví, jak se má zobrazit ta která komponenta nebo výsledek získaný z modelu.
Controller
Řadič, který zpracovává požadavky uživatele a na jejich základě pak volá patřičnou aplikační logiku (tj. model) a poté požádá view o vykreslení dat. Obdobou kontrolerů v Nette Framework jsou presentery.
Adresářová struktura
Když se po stažení distribuce Nette Framework podíváte do adresáře
sandbox, uvidíte doporučovanou adresářovou strukturu:
sandbox/
app/ ← adresář s aplikací
config/ ← konfigurační soubory
config.neon ← hlavní konfigurační soubor
models/ ← modelová vrstva a její třídy
presenters/ ← třídy presenterů
HomepagePresenter.php ← třída presenteru Homepage
templates/ ← adresář se šablonami
@layout.latte ← šablona společného layoutu
Homepage/ ← šablony presenteru Homepage
default.latte ← šablona akce default
bootstrap.php ← zaváděcí soubor aplikace
libs/ ← adresář na knihovny (např. třetích stran)
Nette/ ← oblíbený framework
...
log/ ← obsahuje logy, error logy atd.
temp/ ← pro dočasné soubory, cache, ...
www/ ← veřejný adresář, document root projektu
.htaccess ← pravidla pro mod_rewrite
index.php ← který spouští aplikaci
images/ ← další adresáře, třeba pro obrázky
Krom toho se v některých složkách nacházejí soubory
.htaccess resp. web.config, které zakazují přístup
z prohlížeče (pro Apache resp. IIS). Ujistěte se, že to funguje a že se
skutečně z prohlížeče do složky app/ nebo libs/
nedostanete.
Adresářům log/ a temp/ nezapomeňte
nastavit práva pro zápis (chmod 0777).
index.php & bootstrap.php
Všechny požadavky posílá prohlížeč přes jediný PHP soubor, který se
ve veřejném adresáři www/ nachází, a tím je soubor
index.php. V jeho těle se neděje takřka nic. Definují se zde
pouze konstanty popisující adresářovou strukturu aplikace
(WWW_DIR, APP_DIR) a předává řízení do aplikace
(tj. do adresáře app/) zaváděcímu souboru
bootstrap.php.
Nette Framework jednotně všechny cesty ukládá bez pravostranného lomítka.
Výše uvedená adresářová struktura je tak skutečně jen doporučená,
protože ji můžeme snadno jakkoliv změnit nebo složky přejmenovat a bude
stačit pouze přenastavit cesty v souborech index.php nebo
bootstrap.php.
Soubor bootstrap.php nejprve načte Nette Framework:
require LIBS_DIR . '/Nette/loader.php';
Aktivuje debugger a logger ve striktním režimu:
use Nette\Diagnostics\Debugger;
Debugger::$logDirectory = __DIR__ . '/../log';
Debugger::$strictMode = TRUE;
Debugger::enable();
Třída Configurator vytvoří tzv. systémový DI kontejner. Nejprve se však
aktivuje autoloading,
který zajistí automatické načínání všech souborů se
zdrojovými kódy:
$configurator = new Nette\Config\Configurator;
$configurator->setTempDirectory(__DIR__ . '/../temp');
$configurator->createRobotLoader()
->addDirectory(APP_DIR)
->addDirectory(LIBS_DIR)
->register();
A podle konfiguračního souboru config.neon se generuje
systémový DI kontejner. Od něj se bude odvíjet všechno další.
$configurator->addConfig(__DIR__ . '/config/config.neon');
$container = $configurator->createContainer();
Nastaví pravidla pro routování, aby
bylo možné překládat URL adresy na akce presenterů. Toto pravidlo mimo
jiné říká, že výchozí akcí presenteru bude
Homepage:default.
$router = $container->router;
$router[] = new Route('index.php', 'Homepage:default', Route::ONE_WAY);
$router[] = new Route('<presenter>/<action>[/<id>]', 'Homepage:default');
Nastaví parametry aplikace, např. error-presenter, který se bude v produkčním prostředí starat o zobrazování hlášek při výskytu chyby:
$application = $container->application;
$application->errorPresenter = 'Error';
Pokud bychom chtěli provést nějaké další úlohy, jako je třeba
připojení k databázi, je vhodné to přidat do události
onStartup aplikace: (pozn.: připojení k databázi je obecně
lepší nechat na DI kontejneru).
$application->onStartup[] = function() {
... připojíme se k databázi ...
};
A aplikaci spustíme:
$application->run();
To je vše.
Moduly
U složitějších aplikací můžeme složky s presentery a šablonami
rozčlenit do podadresářů, kterým říkáme moduly. Pokud by naše aplikace
obsahovala například moduly Front a Admin, její
struktura by mohla vypadat takto:
sandbox/
app/ ← adresář s aplikací
config/ ← konfigurační soubory
config.neon ← hlavní konfigurační soubor
models/ ← modelová vrstva a její třídy
AdminModule/ ← modul Admin
presenters/ ← a jeho presentery
templates/ ← a šablony
FrontModule/ ← modul Front
presenters/ ← a jeho presentery
templates/ ← a šablony
bootstrap.php ← zaváděcí soubor aplikace
...
Moduly nemusí tvořit jen plochou strukturu, lze vytvářet i submoduly atd.
Zpracování akce presenteru
Nyní prosím zbystřete. Každý požadavek na naši aplikaci se dostane
přes soubory index.php a bootstap.php do objektu
$application. Ten ale HTTP požadavkům nerozumí, proto požádá
router, aby mu ho přeložil do řeči,
které už rozumí. Tedy aby mu řekl, pro který presenter je požadavek
určen a kterou akci s ním chce vykonat. Router kupříkladu odpoví,
že uživatel chce akci show presenteru Product (je
dobrý zvykem to zapisovat jako Product:show) a dále předává
parametr id = 123. Česky by se řeklo: uživatele chce zobrazit
produkt s id=123.
Tomu už $application rozumí a přistoupí k plnění
přání. Vyrobí objekt třídy ProductPresenter, která
reprezentuje presenter Product. (Abychom byli zcela přesní,
o výrobu objektu presenteru požádá službu presenterFactory).
A pak presenter požádá o provedení akce (show a parametrem
id).
Presenter je objekt, který vezme požadavek přeložený routerem a vymyslí
odpověď. Odpovědí může být HTML stránka, obrázek, XML dokument, soubor
na disku, JSON, přesměrování nebo cokoliv potřebujete. Konkrétně
ProductPresenter požádá model o data a ty poté předá do šablony
k vykreslení. Tohle se zpravidla odehraje v metodě renderShow,
kde slovo Show odpovídá názvu akce a parametr požadavku
id bude předán jako parametr této metodě:
class ProductPresenter extends Nette\Application\UI\Presenter
{
public function renderShow($id)
{
// získáme data z modelu a předáme do šablony
$this->template->product = $this->model->getProduct($id);
}
}
Pole všech parametrů odeslaných aplikaci požadavkem GET najdete v
$this->request->getParameters(). V běžných případech
byste je ale neměli potřebovat, využívejte routování a parametrů akce.
Obdobně pole všech hodnot přijatých přes POST naleznete v
$this->request->getPost(). Ani to byste neměli potřebovat,
pokud nezpracováváte požadavek z jiné aplikace. Pro běžné případy
(odeslané formuláře vaší vlastní aplikace) používejte callback
onSuccess.
Následně přistoupí presenter k vykreslení šablony.
Šablony
Cestu k souboru se šablonou odvodí presenter podle jednoduché logiky. Pro
presenter Product a akci show zkusí, zda existuje
jeden z těchto souborů:
- templates/Product/show.latte - templates/Product.show.latte
Kromě přípony .latte lze také použít příponu
.phtml.
Taktéž se pokusí dohledat layout (ten je nepovinný):
- templates/Product/@layout.latte - templates/Product.@layout.latte - templates/@layout.latte layout společný pro více presenterů
(Způsob dohledávání šablon můžeme změnit přepsáním metod formatTemplateFiles nebo formatLayoutTemplateFiles.)
Presentery a jejich komponenty předávají do šablon několik užitečných proměnných:
$basePathje absolutní URL cesta ke kořenovému adresáři (např./CD-collection)$baseUrlje absolutní URL ke kořenovému adresáři (např.http://localhost/CD-collection)$userje objekt reprezentující uživatele$presenterje aktuální presenter$controlje aktuální komponenta nebo presenter$flashespole zpráv zaslaných funkcíflashMessage()
O vykreslování šablon podrobněji v samostatné kapitole.
Ono to vlastně není nic těžkého! Pokud požaduji akci například
Homepage:default, tak se
- vytvoří objekt třídy
HomepagePresenter - zavolá se metoda
renderDefault()(existuje-li, ale nemusí) - vykreslí se šablona např.
templates/Homepage/default.lattes layoutem např.templates/@layout.latte
a v šabloně pak můžeme vytvořit
odkaz na zmíněný Product:show($id), zhruba takto:
<a n:href="Product:show $productId">detail produktu</a>
Nechci to zakřiknout, ale tvorba aplikací v Nette bude pohodička.
Moduly
U složitějších aplikací, které presentery rozčleňují do modulů,
funguje vše velmi podobně. Opět dejme tomu, že naše aplikace obsahuje modul
Front, jehož součástí je presenter Product. Akce
show se pak zapíše jako Front:Product:show a třída
ProductPresenter se umístí do jmenného prostoru
FrontModule:
namespace FrontModule;
class ProductPresenter extends \Nette\Application\UI\Presenter
{
...
Vytváření odkazů
Vytvoření odkazů patří mezi nejsilnější místa Nette Frameworku. Díky obousměrnému routování není potřeba do šablon či kódu natvrdo zapisovat URL nebo je komplikovaně skládat. Stačí se odkazovat na akce presenterů, předávat jim parametry a framework už URL vygeneruje sám. Vytvořit odkaz je pak stejně snadné, jako zavolat funkci. To se vám bude tuze líbit!
Během programování a vytváření šablon nás nemusí zajímat tvar URL
adres, budeme se totiž odkazovat přímo na akci presenteru, tj. například na
již zmíněnou Product:show.
Odkazy v šablonách
Nejčastěji vytváříme odkazy v šablonách. Aby to bylo co
nejjednodušší, nabízí nám framework hned tři makra. Nejšikovnější
z nich je makro n:href
<a n:href="Product:show $productId">detail produktu</a>
Všimněte si, že místo HTML atributu href jsme použili n:makra n:href. Jeho
hodnotou pak není URL, jak by tomu bylo v případě atributu
href, ale rovnou akce presenteru. Tam má tvar
[Presenter:]action [,] [arg1] [, arg2] [, ...]
Po kliknutí na odkaz se dostane ke slovu metoda
ProductPresenter::renderShow() a jako parametr $id ji
bude předána hodnota proměnné $productId. Parametrů bychom
mohli předat i víc, stejně jako když voláme metodu. Mohlo by to být snad
jednodušší?
Je lepší dodržovat konvenci velkého písmenka pro název presenteru a malého pro akci. Jako oddělovač slouží právě jedna dvojtečka.
Kromě toho je možné předávat i pojmenované parametry. Následující
odkaz předává parametr lang s hodnotou cs:
<a n:href="Product:show $productId, lang => cs">detail produktu</a>
Ačkoliv metoda renderShow nemá $lang ve své
hlavičce, může hodnotu parametru zjistit voláním $lang =
$this->getParam('lang').
Máme-li všechny parametry v poli, můžeme jej rozvinout operátorem
(expand):
{var $args = [$productId, lang => cs]}
<a n:href="Product:show (expand) $args">detail produktu</a>
Pokud je šablona, ve které vytváříme odkaz, také součástí
Product presenteru, můžeme název presenteru vynechat a psát
přímo n:href="show $productId". Nebo obráceně, vede-li odkaz na
akci nazvanou default, lze tuto vynechat a napsat
n:href="Product: $id" (nezapomeňte na dvojtečku).
Odkazy mohou také směřovat do jiných modulů.
Zde se rozlišuje, zda se odkazujeme „relativně“ do zanořeného submodulu,
nebo „absolutně“ do jiného modulu – pak cesta začne dvojtečkou. Pro
ukázku předpokládejme, že aktuální presenter je součástí modul
Front, potom zapíšeme:
<a n:href="Shop:Product:show">odkaz na Front:Shop:Product:show</a>
<a n:href=":Admin:Product:show">odkaz na Admin:Product:show</a>
Speciálním případem je odkaz na sebe sama, kdy jako cíl uvedeme
this.
Vygenerovaný odkaz má podobu relativní cesty. Pokud potřebujeme
absolutní odkaz včetně domény např.
http://example.com/product/show/123, přidáme na začátek dvě
lomítka n:href="//show $productId". Je také možné přepnout
generování absolutních odkazů pro všechny odkazy, které od té chvíle
budete generovat, pomocí proměnné $absoluteUrls presenteru nebo komponenty.
Obvyklým případem je přepnutí pro celou aplikaci, kterého nejlépe
docílíte v BasePresenteru v metodě startup.
protected function startup()
{
parent::startup();
$this->absoluteUrls = TRUE;
}
Odkazovat můžeme na určitou část na stránce přes tzv. fragment za
znakem křížky #:
<a n:href="show#comments">odkaz na Product:show a fragment #comments</a>
Makro n:href je velmi šikovné, pokud vytváříme HTML značku
<a>. Pokud chceme odkaz vypsat jinde, například v textu
šablony, použijeme makro {link} se stejnou vnitřní
syntaxí:
Adresa je: {link Product:show $productId}
Přečtěte si další podrobnosti o syntaxi Latte šablon.
Odkazování v presenteru
Presenter a komponenta
disponují metodou link(), pomocí které lze vytvářet odkazy
podobně jako v šabloně. Prvním parametrem je cílová akce presenteru,
následují předávané argumenty:
$url = $this->link(destination [,arg [,arg ...]]);
Ty lze předat také pomocí pole. Příklady:
$url = $this->link('Product:show', $productId);
$url = $this->link('Product:show', array($productId, 'lang' => 'en'));
Neplatné odkazy
Může se stát, že vytvoříme neplatný odkaz – buď proto, že vede na
neexistující presenter, proto, že předává víc parametrů, než které
cílová metoda přijímá ve své definici, nebo když pro cílovou akci nelze
vygenerovat URL. Jak naložit s neplatnými odkazy určuje statická proměnná
Presenter::$invalidLinkMode. Ta může nabývat těchto hodnot
(konstant):
Presenter::INVALID_LINK_SILENT– tichý režim, jako URL se vrátí znak #Presenter::INVALID_LINK_WARNING– vizuální varováníPresenter::INVALID_LINK_EXCEPTION– vyhodí se výjimka InvalidLinkException
Výchozí nastavení je INVALID_LINK_SILENT v produkčním režimu a
INVALID_LINK_WARNING ve vývojovém. INVALID_LINK_WARNING pracuje tak, že jako
URL vrátí chybovou zprávu, která začíná znaky error:. Aby
takové odkazy byly na první pohled patrné, doplníme si do CSS:
a[href^="error:"] {
background: red;
color: white;
}
Persistentní parametry
Krom klasických parametrů, které jsme používali nyní, existují i tzv. perzistentní parametry. Ty se liší v jediné avšak zásadní věci: přenášejí se automaticky. To znamená, že je nemusíme v odkazech explicitně uvádět, ale přesto se přenesou.
Pokud má vaše aplikace dvě jazykové mutace, bylo by neskutečně únavné
v každém odkazu přenášet i aktuální jazyk. To není s Nette Framework
potřeba. Prostě si parametr $lang označíme jako persistentní a
to tímto způsobem:
class ProductPresenter extends Presenter
{
/** @persistent */
public $lang;
...
Pokud aktuální hodnota parametru $lang bude 'en',
tak do odkazu
<a n:href="Product:show $productId">detail produktu</a>
se automaticky doplní i lang => en. Paráda!
Samozřejmě můžeme lang uvést a jeho hodnotu změnit:
<a n:href="Product:show $productId, lang => cs">detail v češtině</a>
Zároveň v proměnné třídy $lang objektu
ProductPresenter budeme mít hodnotu parametru k dispozici,
můžeme k ní přistoupit přes $this->lang. Můžeme
v definici třídy uvést i výchozí hodnotu persistentního parametru.
Bude-li mít parametr tuto výchozí hodnotou, pak nebude přenášen
v URL.
Persistentní proměnná musí být deklarovaná jako public.
Perzistence zohledňuje hierarchii tříd presenterů, tedy parametr definovaný v určitém presenteru je poté automaticky přenášen do každého presenteru z něj dědícího.
Životní cyklus presenteru
Už víme, že tzv. akce presenteru způsobí zavolání metody
render<Akce>, tedy například renderShow. Ale
to není zdaleka jediná metoda, která se volá. Při psaní presenterů
můžeme mimo jiné vytvořit i následující metody:
Životní cyklus presenteru
startup()
Ihned po vytvoření presenteru se zavolá metoda startup(). Ta
inicializuje proměnné nebo oveří uživatelská oprávnění.
Pokud si píšete vlastní metodu startup(),
nezapomeňte zavolat předka parent::startup().
action<Action>()
Obdoba metody render<View>(). Jsou situace, kdy presenter
provede určitý úkon (přihlásí uživatele, zapíše data do databáze) a
poté přesměruje jinam. Dávat název render metodě, která nic
nekreslí, by bylo nepěkné, proto existuje alternativa s názvem
action.
Důležité je vědět, že action<Action>() se volá
dříve, než metoda render<View>(). Může tedy
i rozhodnout, aby se zavolala jiná metoda render pomocí
příkazu $this->setView('jineView') (zavolá se
renderJineView()).
handle<Signal>()
Metoda zpracovává tzv. signály neboli subrequesty. Určeno zejména pro komponenty a zpracování AJAXových požadavků.
beforeRender()
Metoda beforeRender, jak už název napovídá, se volá před
nám známou metodou render<View>() a může obsahovat
například nastavení šablony, předání proměnných společných pro více
view a podobně.
render<View>()
Obvykle nasype do šablony potřebná data.
shutdown()
Je vyvolána při ukončení životního cyklu presenteru.
Přesnější by bylo říci, že jsme si povídali o životním cyklu třídy Nette\Application\UI\Presenter, ze které se presentery dědí nejčastěji. Obecně je totiž presenter jakákoliv třída implementující trivální rozhraní Nette\Application\IPresenter a jeden takový alternativní používá Mikro-framework.
Ukončení presenteru
Presenter můžeme během jeho životního cyklu kdykoliv ukončit. Obvykle tak učiníme proto, že chceme zamezit vykreslování šablony.
- presenter rovnou ukončíme metodou
$presenter->terminate() - presenter ukončíme a hned vyrenderujeme šablonu:
$presenter->sendTemplate() - presenter ukončíme a odešleme payload:
$presenter->sendPayload()(pro AJAX) - presenter ukončíme a odešleme vlastní odpověď:
$presenter->sendResponse($response)
Presenter lze také ukončit přesměrováním či vyhozením výjimky BadRequestException.
Přesměrování
K přechodu na jiný presenter slouží metody redirect() a
forward(), které mají velmi podobnou syntax jako zmíněná
funkce link(). Například po
odeslání formuláře a zápisu dat do databáze přesměrujeme na detail
produktu zavoláním:
$this->redirect('Product:show', $id);
Zatímco forward() přejde na novou akci bez přesměrování,
metoda redirect() přesměruje prohlížeč HTTP kódem 302 nebo
303. Chceme-li zvolit jiný kód, uvedeme jej ještě před názvem akce
presenteru:
$this->redirect(301, 'Product:show', $id);
Na jinou URL mimo rozsah aplikace lze přesměrovat metodou redirectUrl()
$this->redirectUrl('http://nette.org');
Přesměrování okamžitě ukončí činnost presenteru vyhozením tzv.
ukončovací výjimky Nette\Application\AbortException.
Před přesměrováním si občas chceme odeslat tzv. flash message, tedy zprávu, která se objeví po přesměrování v šabloně.
Chyba 404 a spol.
Pokud nemůžeme splnit požadavek z důvodu, že například záznam
neexistuje v databázi, vyhodíme výjimku
Nette\Application\BadRequestException, která představuje HTTP
chybu 404:
public function renderShow($id)
{
$product = $this->model->getProduct($id);
if (!$product) {
throw new Nette\Application\BadRequestException;
}
...
}
Pokud uživatel nemá oprávnění stránku vidět, vyhodíme výjimku
Nette\Application\ForbiddenRequestException (chyba 403). Další
chybové kódy lze uvést jako kód výjimky
Nette\Application\BadRequestException.
Flash zprávy
Jde o zprávy obvykle informující o výsledku nějaké operace. Důležitým rysem flash zpráv je to, že jsou v šabloně k dispozici i po přesměrování. I po zobrazení zůstanou živé ještě další 3 sekundy – například pro případ, že by z důvodu chybného přenosu uživatel dal stránku obnovit – zpráva mu tedy hned nezmizí.
Předání do šablony obstarává metoda flashMessage.
Prvním parametrem je text zprávy a nepovinným druhým parametrem její typ
(error, warning, info apod.). Metoda flashMessage() vrací instanci
flash zprávy, které je možné přidávat další informace.
public function deleteFormSubmitted($form)
{
... požádáme model o smazání záznamu ...
// předáme flash zprávu
$this->flashMessage('Položka byla smazána.');
$this->redirect(...); // a přesměrujeme
}
Šabloně jsou tyto zprávy k dispozici v proměnné $flashes
jako anonymní objekty, které obsahují vlastnosti message (text
zprávy), type (typ zprávy) a mohou obsahovat již zmíněné
uživatelské informace. Vykreslíme je třeba takto:
{foreach $flashes as $flash}
<div class="flash {$flash->type}">{$flash->message}</div>
{/foreach}
Presenter a komponenty
Bavíme-li se o presenterech, tak pod pojmem komponenty obvykle myslíme potomky třídy Control. Přesnější by tedy bylo používat termín „controls“ (tj. ovládací prvky), ale „kontrola“ má v češtině zcela jiný význam a spíš se ujaly „komponenty“.
Sám presenter Nette\Application\UI\Presenter je přitom
potomkem třídy Control, takže je tu velká podobnost mezi komponentami a
presenterem. Především však UI\Control (a tím pádem i
UI\Presenter) je tzv. komponent container, což znamená, že do
něj lze vkládat další komponenty. Podobně, jako třeba do komponenty formuláře vkládáme formulářové prvky
(textové políčko, tlačítko, …). A stejně jako u formulářů lze
k prvkům přistupovat přes hranaté závorky:
// připojíme komponentu do presenteru
$presenter['mymenu'] = new MenuControl;
// získáme komponentu z presenteru a vykreslíme
$presenter['mymenu']->render();
Připojením komponenty do presenteru (jejich svázáním) získáte možnost:
- vytvářet v komponentě odkazy
- používat signály
- používat v komponentě perzistentní parametry
Pokud nic z toho nepotřebujeme, není potřeba komponentu s presenterem vázat.
Továrničky na komponenty
Továrna na komponenty představuje elegantní způsob, jak komponenty
vytvářet teprve ve chvíli, kdy jsou skutečně potřeba (lazy / on demand).
Celé kouzlo spočívá v implementaci metody s názvem
createComponent<Name>(), kde <Name> je
název vytvářené komponenty, a která komponentu vytvoří a vrátí.
Komponenta je následně připojena k presenteru. Metodě
createComponent<Name> je předáván volitelný parametr
s názvem komponenty, kterou vytváří.
class DefaultPresenter extends Nette\Application\UI\Presenter
{
public function renderDefault()
{
$menu = $this['menu']; // přistoupíme ke komponentě
// a pokud to bylo poprvé, zavolá se createComponentMenu()
...
}
protected function createComponentMenu()
{
// vytvoříme a nakonfigurujeme komponentu
$menu = new MenuControl;
$menu->items = $this->item;
// a vrátíme ji
return $menu;
}
}
Názvy komponent začínají vždy malým písmenem, přestože se v názvu továrničky píší s velkým.
Díky tomu, že jsou všechny komponenty vytvářeny v samostatné metodě, získává kód na přehlednosti.
Továrničky nikdy nevoláme přímo, zavolá se sama ve chvíli, kdy komponentu poprvé použijeme. Díky tomu je komponenta vytvořena ve správný okamžik a pouze v případě, když je skutečně potřeba. Pokud komponentu nepoužijeme (třeba při AJAXovém požadavku, kdy se přenáší jen část stránky, nebo při cachování šablony), nevytvoří se vůbec a ušetříme výkon serveru.
V šabloně je možné získat a vykreslit komponentu pomocí makra {control}. Není proto potřeba manuálně komponenty předávat do šablony.
<h2>Editační formulář</h2>
{control editForm}
Podrobnější informace o komponentách najdete na samostatné stránce.
Persistentní komponenty
Nejen parametry, ale také komponenty mohou být perzistentní. Jejich stav
se pak přenáší při přechodu na jiný presenter podobně, jako
v případě perzistentních
parametrů. Perzistentní komponenty značíme touto anotací: (zde
značíme komponenty calendar a menu):
/**
* @persistent(calendar, menu)
*/
class DefaultPresenter extends Presenter
{
...
}
Podkomponenty uvnitř těchto komponent není třeba nijak značit, jsou perzistentní samy o sobě.
Kde mohu získat komponenty?
Na stránce Doplňky, pluginy a komponenty můžete najít open-source komponenty, které sem umístili dobrovolníci z komunity okolo Nette Framework. Nette Foundation za ně neručí.

Josef Kašpar | 27. 6. 2011, 23:43 | comment
Nápady pro zlepšení dokumentace:
Bylo by dobré přeformulovat toto: http://doc.nette.org/cs/presenters#… „Rozdíl se projeví v šablonách komponent, kde zápis {link Home:default} nevygeneruje odkaz, ale signál na komponentu“ – Takový signál-odkaz je ovšem nesmysl – to v návodu chybí, že odkaz na komponenty mohou být jen odkazy – resp se o tom píše v jiné sekci.
ukázka neplatného odkazu Warning
http://doc.nette.org/cs/presenters#… zdůraznit, že Presentery si píšeme samy
http://doc.nette.org/cs/presenters#… " a vizuální komponenty dědící od Control (a ty se při přijetí signálu automaticky invalidují," to už dávno neplatí
„Jeho formát je buď {signal}, nebo {signalReceiver}-{signal}“. Vysvětlit, že v prvním případě jde o signál na root komponentně, tedy presenteru. Tak mě napadá, je někde popsáno, že komponenty tvoří strom a že se oddělují právě pomlčkou? Myslím že ve staré dokumentaci předposlední věc byla