Latte: как насчет системы типов?

5 лет назад от David Grudl  

Система типов. Ключевой аспект для разработки надежных приложений, в котором PHP значительно опередил динамические языки, такие как Python, Ruby или JavaScript. Фреймворк Nette с самого начала направлял программистов к типизированному и строгому программированию. Latte 2.7 принес поддержку типов и в шаблоны.

Благодаря тому, что мы знаем, какой тип данных или объекта находится в каждой переменной,

  • IDE может правильно подсказывать
  • статический анализ может выявлять ошибки

Два пункта, которые кардинально повышают качество и удобство разработки.

Как объявлять типы на стороне PHP?

Мы будем передавать данные в шаблон как объект класса, который определяет все переменные и их типы. С использованием новых возможностей PHP 7.4 он мог бы выглядеть так:

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

Использование:

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

Дополнение: благодаря новым возможностям PHP 8 пример можно записать еще интереснее:

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

Как объявлять типы в шаблоне?

Теперь мы можем связать указанный класс с шаблоном. Достаточно указать в начале:

{templateType MailTemplate}

И этим мы определили, что в шаблоне будет четыре переменных $lang, $address, $subject и $price с соответствующими типами.

Альтернативой является определение типов отдельных переменных прямо в шаблоне, то есть без создания класса. Для этого служит тег {varType}:

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

Конечно, можно комбинировать оба подхода. Создать класс, чтобы обеспечить подсказки на стороне презентера, связать его с шаблоном с помощью {templateType} и для остальных локальных переменных в блоках и т.д. использовать {varType}. Которые можно рассматривать как аналог /** @var type $variable */, комментария, которым мы иногда инструктируем IDE или статический анализатор в PHP коде.

Теперь тип можно указать также в тегах {var}, {default} или {define}:

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

Примечание: по историческим причинам в тегах {var} и {default} можно было писать переменные и без начального знака доллара (и со стрелкой вместо знака равенства). Поскольку это создает неоднозначность, является ли это типом или переменной, этот синтаксис запрещен, и Latte будет предупреждать вас при его использовании. Простой способ найти в своих шаблонах эту старую запись — это поиск по регулярным выражениям /\{(var|default) [^$]/ и /\{(var|default) [^}]*=>/.

Как сэкономить время?

Как проще всего написать класс шаблона или теги {varType}? Позвольте им сгенерироваться. Именно для этого существуют два тега: {templatePrint} и {varPrint}.

Если вы разместите один из этих тегов в шаблоне, вместо обычного рендеринга отобразится предложение кода класса или список тегов {varPrint} соответственно. Затем достаточно одного клика, чтобы выделить код и скопировать его в проект.

В nette/application 3.1 (в бета-версии) включен перегруженный тег {templatePrint}, который генерирует код, лучше адаптированный для презентеров.

Тег {varPrint} выводит локальные переменные, которые не являются параметрами шаблона. Если вы хотите вывести все переменные, используйте {varPrint all}.

Автодополнение в IDE

Последняя версия плагина Latte для PhpStorm умеет использовать вышеупомянутые теги и затем подсказывать на основе типов. Плагин также знает типы стандартных переменных, таких как $user, $presenter, $basePath и т.д.

Статический анализ

Цель состоит в том, чтобы все объявленные типы можно было использовать также для статического анализа. Чтобы, например, с помощью PHPStan можно было проверять шаблоны так же легко, как и другие PHP-файлы.

Мы работаем над этим, и вы увидите это в одной из следующих версий Latte.

David Grudl Founder of Uměligence and creator of Nette Framework, the popular PHP framework. Since 2021, he's been fully immersed in artificial intelligence, teaching practical AI applications. He discusses weekly tech developments on Tech Guys with his co-hosts and writes for phpFashion and La Trine. He believes AI isn't science fiction—it's a practical tool for improving life today.