Latte: як користуватися системою типів?

4 рік тому Від David Grudl  

Система типів – це головне для розробки надійних додатків. Типи в PHP мають перевагу над іншими динамічними мовами, такими як Python, Ruby або JavaScript. Nette Framework з самого початку змушує програмістів створювати типізований і строгий код. 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 */, що є коментарем, який ми іноді використовуємо в PHP-коді для інструкцій IDE або інструменту статичного аналізу.

Також тип можна вказати в {var}, {default} або {define}:

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

Примітка: з історичних причин можна було писати змінні в тегах {var} і {default} без знаку долара. Оскільки це створює неоднозначність, чи це тип, чи змінна, цей синтаксис є застарілим, і Latte попередить вас, коли ви будете його використовувати.

Як ви спрощуєте свою роботу?

Як максимально спростити написання шаблонного класу або {varType}? Згенерувати їх. Це саме те, що робить пара тегів {templatePrint} та {varPrint}.

Якщо ви помістите один з цих тегів у шаблон, замість звичайного рендерингу відобразиться код класу або шаблону. Потім просто виберіть і скопіюйте код у свій проект.

Nette/application 3.1 (бета-версія) містить перевантажений тег {templatePrint}, який генерує код, що краще підходить для доповідачів.

Тег {varPrint} перераховує локальні змінні, які не є параметрами шаблону. Якщо ви хочете перерахувати всі змінні, використовуйте {varPrint all}.

Завершення коду IDE

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

Статичний аналіз

Кінцева мета полягає в тому, що всі оголошені типи також можна використовувати для статичного аналізу. Наприклад, використовувати PHPStan для перевірки шаблонів так само легко, як і інших PHP-файлів.

Ми працюємо над цим, і ви побачите це в одній з наступних версій Latte.