Latte: jak korzystać z systemu typów?

4 lata temu Ze strony David Grudl  

System typów to główna rzecz przy tworzeniu solidnych aplikacji. Typy w PHP mają przewagę nad innymi dynamicznymi językami takimi jak Python, Ruby czy JavaScript. Nette Framework prowadzi programistów do tworzenia typowanego i ścisłego kodu od samego początku. Latte 2.7 wprowadziło obsługę typów również do szablonów.

Wiedza o tym, jakim typem danych lub obiektu jest każda zmienna pozwala

  • IDE na poprawne autouzupełnianie
  • analizę statyczną w celu wykrycia błędów

Dwa punkty, które znacznie poprawiają jakość i wygodę rozwoju.

Jak deklarować typy po stronie PHP?

Dane do szablonu będziemy przekazywać jako obiekt klasy, która definiuje wszystkie zmienne i ich typy. Korzystając z nowych możliwości PHP 7.4, mogłoby to wyglądać tak:

class MailTemplate
{
	public string $lang = 'cs';
	public Address $address;
	public string $subject;
	public ?float $price = null;
}

Usage:

$template = new MailTemplate;
$template->price = $this->getPrice();
...
$latte->render('mail.latte', $template);

Dodatek: dzięki nowym funkcjom PHP 8, przykład można napisać ciekawiej np:

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 deklarować typy w szablonie?

Możemy teraz powiązać tę klasę z szablonem. Wystarczy, że podamy to na początku:

{templateType MailTemplate}

I tym sposobem zdefiniowaliśmy, że szablon będzie zawierał kwartet zmiennych $lang, $address, $subject i $price wraz z ich odpowiednimi typami.

Alternatywą jest zdefiniowanie typów poszczególnych zmiennych bezpośrednio w szablonie, czyli bez tworzenia klasy. Do tego celu służy znacznik {varType}:

{varType string $lang}
{varType Address $address}

Oczywiście można połączyć oba sposoby. Utworzyć klasę, bo to zapewni kompletność po stronie prezentera, powiązać ją z szablonem za pomocą {templateType} i użyć {varType} dla innych zmiennych lokalnych w blokach itp. Można to rozumieć jako analogię /** @var type $variable */, czyli komentarz, którego czasem używamy w kodzie PHP, aby poinstruować IDE lub narzędzie do analizy statycznej.

Również typ może być określony w {var}, {default} lub {define}:

{var Model\Page $page = $items['page']}
{define form, string $name}
	...
{/define}

Uwaga: z powodów historycznych możliwe było pisanie zmiennych w znacznikach {var} i {default} bez wiodącego znaku dolara. Ponieważ tworzy to niejednoznaczność, czy jest to typ czy zmienna, ta składnia jest zdeprecjonowana, a Latte ostrzeże cię, gdy jej użyjesz.

W jaki sposób upraszczasz swoją pracę?

Jak najłatwiej napisać klasę szablonową lub {varType}? Uzyskać ich wygenerowanie. Dokładnie to robi para tagów {templatePrint} i {varPrint}.

Jeśli umieścisz jeden z tych znaczników w szablonie, zamiast normalnego renderingu zostanie wyświetlony kod klasy lub szablonu. Następnie wystarczy zaznaczyć i skopiować kod do swojego projektu.

Nette/application 3.1 (beta) zawiera przeciążony znacznik {templatePrint}, który generuje kod lepiej nadający się dla prezenterów.

Znacznik {varPrint} wylicza zmienne lokalne, które nie są parametrami szablonu. Jeśli chcesz wylistować wszystkie zmienne, użyj {varPrint all}.

Uzupełnianie kodu IDE

Najnowsza wersja wtyczki PhpStorm Latte może skorzystać z powyższych znaczników, a następnie sugerować w oparciu o typy. Wtyczka zna również typy standardowych zmiennych, takich jak $user, $presenter, $basePath, itp.

Analiza statyczna

Ostatecznym celem jest, aby wszystkie zadeklarowane typy mogły być również używane do analizy statycznej. Na przykład, aby użyć PHPStan do sprawdzania szablonów tak samo łatwo jak innych plików PHP.

Pracujemy nad tym i zobaczysz to w jednej z kolejnych wersji Latte.