Latte: how to use type system?

4 years ago by David Grudl  

Type system is main thing for the development of robust applications. Types in PHP have a superiority over other dynamic languages such as Python, Ruby or JavaScript. Nette Framework leads programmers to produce typed and strict code from the beginning. Latte 2.7 brought the type support to templates as well.

To knowing what data or object type each variable is allows

  • IDE to correctly autocomplete
  • static analysis to detect errors

Two points that significantly improve the quality and convenience of development.

How to declare types on PHP side?

We will pass data to the template as an object of a class that defines all variables and their types. Using the new features of PHP 7.4, it could look like this:

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);

Addition: thanks to the new features of PHP 8, the example can be written more interestingly like this:

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,
));

How to declare types in a template?

We can now associate that class with the template. We just need to state it at the beginning:

{templateType MailTemplate}

And with that, we have defined that the template will contain a quartet of variables $lang, $address, $subject and $price including their respective types.

The alternative is to define the types of each variable directly in the template, i.e. without creating a class. The tag {varType} is used for this purpose:

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

Of course, both can be combined. Create a class, as this will ensure completion on the presenter side, link it to the template using {templateType} and use {varType} for other local variables in blocks, etc. This can be understood as an analogy /** @var type $variable */, which is a comment that we sometimes use in PHP code to instruct IDE or static analysis tool.

Also, the type can be specified in {var}, {default} or {define}:

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

Note: for historical reasons, it was possible to write variables in the {var} and {default} tags without the leading dollar sign. Because this creates ambiguity whether it is a type or a variable, this syntax is deprecated and Latte will warn you when you use it.

How do you simplify your work?

How to write a template class or {varType} as easy as possible? Get them generated. That is precisely what pair of tags {templatePrint} and {varPrint} do.

If you place one of these tags in a template, the code of class or template is displayed instead of the normal rendering. Then simply select and copy the code into your project.

Nette/application 3.1 (beta) includes an overloaded tag {templatePrint} that generates code that is better suitable for presenters.

The {varPrint} tag lists local variables that are not template parameters. If you want to list all variables, use {varPrint all}.

IDE code completion

The latest version of the PhpStorm Latte plugin can take advantage of the above tags and then suggest based on types. The plugin also knows the types of standard variables such as $user, $presenter, $basePath, etc.

Static analysis

The final goal is that all declared types can also be used for static analysis. For example, to use PHPStan to check templates as easily as other PHP files.

We are working on this and you will see it in one of the next versions of Latte.

Comments (RSS)

  1. Nice, I'm using it just for a few weeks, and it's awesome, now, there is no template system what could compete with Latte. 😍

    4 years ago
  2. ♥️ ♥️ ♥️ This is the feature of the year!

    4 years ago

Sign in to submit a comment