
Vlastní komponenty v Nette
Komponenty v Nette dokáží bránit opakování stejného kódu.
Jedna z programátorských zásad zní: Don't repeat yourself – zkratka DRY – česky: Neopakujte se. Podle ní by se neměl v programu opakovat kód.
Nette Framework má pro opakovaně používaný kód tzv. komponenty.
Kdy se komponenty hodí
Typickým případem jsou formuláře, kdy tentýž formulář může být potřeba vypsat ve více šablonách.
- Martin Zlámal: Znovupoužitelný formulář – příklad formulářové komponenty
Podle mého názoru se ale komponenty hodí i pro různé výpisy.
Třeba na tomto webu se na mnoha místech vypisuje seznam článků:
- nejnovější články na hlavní straně,
- nejoblíbenější články na hlavní straně,
- související články vedle otevřeného článku,
- články v kategorii
Všechny výpisy jsou si dost podobné, takže se nabízí mít jejich kód na jednom místě.
Vlastní komponenta
Šablona
V šabloně se na místě, kde má být komponenta použita, napíše prosté {control nazevKomponenty, $parametr}.
Parametr je nepovinný, ale pokud je potřeba předávat do komponenty nějaká data, tak je potřeba (parametrů může být i více).
Cílem je tedy původní zápis typu:
{foreach $articles as $article}
<h2>{$article->nazev}<h2>
<p>{$article->popis}<p>
{/foreach}
Nahradit něčím jako:
{foreach $articles as $article}
{control article, $article}
{/foreach}
Presenter
Komponentu pro použití napříč celou aplikací/modulem je vhodné přidat do BasePresenteru:
protected function createComponentArticle()
{
$control = new \ArticleControl;
return $control;
}
Zde se vytvoří komponenta article na základě zvláštní třídy ArticleControl.
To lomítko před názvem třídy je zásadní, bez něj Nette tuto třídu nenajde.
Komponenta
Komponenty se dávají třeba do složky app/components, ale není to podmínka. V případě používání hodně komponent se ještě mohou zanořovat do podsložek. Název souboru potom odpovídá názvu třídy.
Stěžejní je metoda render, která zajistí vykreslení. Přijímá parametry z {control nazevKomponenty, $parametr} v šabloně.
Na rozdíl od presenterů si komponenta nehledá šablonu automaticky, ale musí se jí přiřadit přes $template->setFile.
<?php
use Nette\Application\UI\Control;
class ArticleControl extends Control
{
public function render($article)
{
$template = $this->template;
// nastavení šablony
$template->setFile(__DIR__ . '/article.latte');
// nastavení proměnné z parametru
$template->article = $article;
$template->render();
}
}
Šablona komponenty
Šablona komponenty article.latte potom bude obsahovat společný HTML kód, takže ho půjde elegantně upravovat na jednom místě.
Filtry v komponentě
V komponentě nebudou fungovat vlastní Latte filtry.
Nicméně jdou zprovoznit stejným kódem jako v souboru BasePresenter.php:
protected function createTemplate($class = NULL)
{
$template = parent::createTemplate($class);
$template->addFilter(NULL, 'Filters::common');
return $template;
}
Odkazy v komponentě
V komponentě nefungují odkazy v n:href stejným způsobem jako v šabloně presenteru:
<a n:href="Article:default">
Odkaz
</a>
Výše uvedený kód skončí chybou:
Component with name 'Article' does not exist
Řešení je použít normální href a {plink}:
<a href="{plink Article:default}">
Odkaz
</a>
Vložení *.latte šablony
Jiná možnost předcházení opakujícímu se kódu, než používat komponenty, je přímo vložit šablonu. Následující kód vloží šablonu article.latte a předá jí proměnnou $article:
{include "article.latte", article => $article}
Příkaz include nefunguje v Latte stejně jako v PHP, tj. vkládaná šablona nemá k disposici proměnné své nadřazené šablony, takže se jí to takto musí předávat.
V případě, že se šablona article.latte používá v různých presenterech, bude trochu problém se sestavením cesty. Cesta k includované šabloně je (nejspíš) relativní vůči šabloně, která ji vkládá.
Související články
Generátor náhodného čísla
Jak vygenerovat náhodné číslo z určitého rozsahu (v JavaScriptu, PHP atd.)
Výpis náhodného textu
Jak na stránce náhodně vypsat obrázek, odkaz, reklamu, text nebo cokoliv jiného.
Instalace Apache, PHP a MySQL za 30 vteřin
Jak si ve Windows spustit vlastní Apache, PHP a MySQL na svém PC za půl minuty.