Latte: jak na typový systém?
Typový systém. Klíčová záležitost pro vývoj robustních aplikací, ve které získalo PHP velký náskok před dynamickými jazyky jako je Python, Ruby nebo JavaScript. Framework Nette od počátku programátory k typovému a striktnímu programování vede. Latte 2.7 přineslo podporou typů i do šablon.
Díky tomu, že víme, jaký datový či objektový typ je v každé proměnné, může
- IDE správně našeptávat
- statická analýza odhalit chyby
Dva body, které zásadním způsobem zvyšují kvalitu a pohodlí vývoje.
Jak deklarovat typy na straně PHP?
Data budeme do šablony předávat jako objekt třídy, která definuje všech proměnné a jejich typy. S využitím nových vlastností PHP 7.4 by mohla vypadat třeba takto:
class MailTemplate
{
public string $lang = 'cs';
public Address $address;
public string $subject;
public ?float $price = null;
}
Použití:
$template = new MailTemplate;
$template->price = $this->getPrice();
...
$latte->render('mail.latte', $template);
Doplnění: díky novým vlastnostem PHP 8 lze příklad zapsat ještě zajímavěji takto:
class MailTemplate
{
public function __construct(
public string $lang = 'cs',
public Address $address,
public string $subject,
public ?float $price = null,
) {}
}
$latte->render('mail.latte', new MailTemplate(
lang: $this->lang,
subject: $title,
price: $this->getPrice(),
address: $userAddress,
));
Jak deklarovat typy v šabloně?
Uvedenou třídu můžeme nyní spojit se šablonou. Stačí uvést na začátek:
{templateType MailTemplate}
A tím jsme definovali, že v šabloně bude čtveřice proměnných
$lang
, $address
, $subject
a
$price
včetně příslušných typů.
Alternativou je definovat typy jednotlivých proměnných přímo
v šabloně, tj. bez vytváření třídy. K tomu slouží značka
{varType}
:
{varType string $lang}
{varType Address $address}
Samozřejmě lze kombinovat obojí. Vytvořit třídu, protože tím
zajistíme našeptávání na straně presenteru, propojit ji se šablonou
pomocí {templateType}
a pro ostatní lokální proměnné
v blocích apod. používat {varType}
. Které můžeme chápat
jako obdobu /** @var type $variable */
, což je komentář, kterým
občas v PHP kódu instruujeme IDE nebo statický analyzér.
Nově lze typ uvést také ve značkách {var}
,
{default}
nebo {define}
:
{var Model\Page $page = $items['page']}
{define form, string $name}
...
{/define}
Poznámka: z historických důvodů bylo možné ve značkách
{var}
a {default}
psát proměnné i bez úvodního
dolaru (a šipkou místo rovnítka). Protože to vytváří nejednoznačnost,
zda jde o typ nebo proměnnou, je tato syntaxe zapovězená a Latte vás bude
při jejím použití varovat. Jednoduchý způsob jak prohledat své šablony,
jestli tam tento starý zápis nemáte, je hledat regulární výrazy
/\{(var|default) [^$]/
a
/\{(var|default) [^}]*=>/
.
Jak si ušetřit práci?
Jak co nejsnáze napsat třídu šablony nebo značky {varType}
?
Nechte si je vygenerovat. Právě od toho existuje dvojice značek
{templatePrint}
a {varPrint}
.
Pokud některou z těchto značek umístíte do šablony, místo běžného
vykreslení se zobrazí návrh kódu třídy resp. seznam značek
{varPrint}
. Kód pak stačí jedním kliknutím označit a
zkopírovat do projektu.
Součástí nette/application 3.1 (v beta verzi) je přetížená značka
{templatePrint}
, která generuje kód lépe uzpůsobený pro
presentery.
Značka {varPrint}
vypisuje lokální proměnné, které nejsou
parametry šablony. Pokud chcete vypsat všechny proměnné, použijte
{varPrint all}
.
Našeptávání v IDE
Nejnovější verze Latte pluginu pro PhpStorm umí využít výše
uvedených značek a poté napovídat na základě typů. Plugin zároveň zná
typy standardních proměnných jako je třeba $user
,
$presenter
, $basePath
atd.
Viz také rozhovor s Matoušem o novinkách v pluginech pro PhpStorm.
Statická analýza
Cílem je, aby se daly všechny deklarované typy použít také pro statickou analýzu. Aby například pomocí PHPStan bylo možné kontrolovat šablony stejně snadno, jako jiné PHP soubory.
Na tomhle pracujeme a dočkáte se v některé z příštích verzí Latte.
Komentáře
Rychlá kontrola
{var}
a{default}
z CLI:Doplnění typů do maker
{var}
apod. je super. Stálo by za zmínku, že umí obě nullable syntaxe:?int
iint|null
.Funguje i něco takového
{varType TranslatorModule\Data\Task[] $tasks}
nebo jak se zapisují pole objektů?Zdravím, půjde někdy něco takovéhoto?
`{varType array<int,Libs\Menu\MenuItem> $menuList}
`nebo
`{var array<int,string> $menuItems = $menu->getMenuItems()}
`jde o to určit typy hodnot v poli
Chcete-li odeslat komentář, přihlaste se