Less Boilerplate, More Types: Introducing #[TemplateVariable]

3 hours ago by David Grudl  

Sometimes a presenter works with a specific domain object (like an article, order, or user) and naturally keeps it in a property. You also need that same object in your Latte template. Until now, that required an extra line with $this->template->…

In Nette Framework 3.2.9, a neat little feature was introduced: the #[TemplateVariable] attribute. Simply mark a presenter property with this attribute (it can't be private), and it automatically becomes available in your template under the same name:

<?php
declare(strict_types=1);

namespace App\Presentation\Article;

use Nette\Application\Attributes\TemplateVariable;
use Nette\Application\UI\Presenter;

final class ArticlePresenter extends Presenter
{
	#[TemplateVariable]
	public string $siteName = 'My blog';

	#[TemplateVariable]
	public ?Model\Article $article = null;

	public function actionShow(int $id): void
	{
		$this->article = $this->articleFacade->getById($id);
	}
}

In your template, you can then just use $siteName and $article directly—no extra wiring needed.

If you do assign a variable with the same name via $this->template->…, though, #[TemplateVariable] won't override it. In other words, when a variable already exists in the template, the attribute leaves it alone.

The Easiest Path to Typed Templates

Another nice thing about #[TemplateVariable] is that it naturally encourages using typed properties as your template's data source. Types are checked by PHP itself (and picked up by IDEs and static analysis), so instead of dynamically stuffing values into $this->template, you're working with proper, strongly-typed values (Article, bool, string…).

Nette offers a complete solution for type-safe templates through custom template classes, where variable types are explicitly defined and $this->template becomes a well-defined object instead of a generic container.

That said, #[TemplateVariable] can be a nice lightweight alternative for small to medium-sized use cases: you don't want the overhead of creating a dedicated template class, but you still want clean code with proper type safety. And when your project grows, you can always migrate to the full strictly-typed template approach.

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.