Latte 2.10: A joy to debug
It has become a tradition that once every quarter a new version of Latte with a ton of hot new features is releases. This time, the most important features are related to debugging templates. Come take a look at a quick overview.
Tracy panel
Latte has a completely new panel for Tracy, which in combination with nette/application 3.1 turns on automatically:
In the panel, you can see all templates, starting with the basic presenter
template, through layout templates, to all imported, included and embedded
templates. You can click through directly into the template, but also into the
compiled PHP code. The order of the templates themselves also carries useful
information, as it shows the priority of the inheriting block hierarchy, which
otherwise may not be obvious at all. If each of the templates defines a block
with the same name, the one of the above template will be drawn, and using
{include parent}
the block of the same name from the following
template it will be inserted.
{trace}
Another novelty is closely related to Tracy. This is a {trace}
tag that you can place anywhere in the template and it will throw an exception.
Special one exceptions, because its callstack is generated from a template
perspective. So instead of calling methods, we see blocks and
{include}
, {extends}
, {import}
or
{embed}
. And also the passed arguments.
This tweak is useful, for example, when tuning complex compositions, when you need to find out how the rendering got to a certain point.
By the way Latte compiles templates into clear PHP code, which you can step
through in the usual way in the IDE, you can set breakpoints, etc. Version
2.10 adds many more comments /* line 123 */
to the code referring
to the line number in the source template, also methods representing blocks have
a new explanatory phpDoc comment.
n:tag
The n:tag
attribute can dynamically change the name of an HTML
element. This can be useful in situations where we change the importance of a
header based on the value of a variable:
<h1 n:tag="$heading" class="main">{$title}</h1>
If $heading === null
, the tag <h1>
is
displayed without change. Otherwise, the name of the element is changed to the
value of the variable, so for $heading === 'h3'
this is
written:
<h3 class="main">...</h3>
{iterateWhile}
The tag` {iterateWhile}` is suitable for various tricks in foreach cycles,
which are otherwise extremely complicated. It can also replace
{first}
and {last}
. Its description is given in a separate chapter in
the documentation.
{embed block}
The previous version of Latte came up with the important tag {embed},
which fundamentally shifts the possibilities of writing components in Latte. In
addition to files {embed file.latte}
, blocks can now be embedded
directly {embed blockname}
.
Modern syntax
[key: value]
The previous version Latte came with support for named
arguments from PHP 8.0 in tags like {include}
or
{link}
:
before
{include 'file.latte' arg1 => 1, arg2 => 2}
now
{include 'file.latte' arg1: 1, arg2: 2}
Now you can also use this modern syntax to write arrays (which is not possible directly in PHP):
before
{[a => active, s => suspended][$user->status]}
now
{[a: active, s: suspended][$user->status]}
New filters and features
In Latte 2.10 you will find a plethora of new functions (even()
,
odd()
, divisibleBy()
, first()
,
last()
) and filters (|first
,
|last
, |random
, |round
,
|floor
, |ceil
, |join
,
|slice
, |explode
, |split
,
|spaceless
and |query
).
It further extends the filter |sort
with the possibility to pass
own comparison function as a parameter:
{var $sorted = ($names|sort: fn($a, $b) => $b <=> $a)}
The filter |replace
can make several changes at once:
{='hello world'|replace: [h => l, l => h]} {* prints 'lehho worhd' *}
Engine::addFilterLoader()
The method addFilterLoader($loader)
replaces the universal
filter addFilter(null, ....)
, whose API was not very clear. The
task of the loader is to return the callback of the filter or
null
:
class Filters
{
public function loader(string $filter): ?callable
{
if (method_exists($this, $filter)) {
return [$this, $filter];
}
return null;
}
public function shortify($s, $len = 10)
{
return mb_substr($s, 0, $len);
}
...
}
PHP attributes
TemplateFunction
& TemplateFilter
You can register filters and functions in Latte in another way: by creating
methods in the template class and giving them annotations
/** @filter */
or /** @function */
. You can now
replace the annotations with PHP
8.0 attributes:
class HomepageTemplate
{
#[Latte\Attributes\TemplateFilter]
public function shortify(string $s, int $len = 10): string
{
return mb_substr($s, 0, $len);
}
#[Latte\Attributes\TemplateFunction]
public function random(...$args)
{
return $args[array_rand($args)];
}
}
One more thing
Write, run, test and save templates in the new online playground. Technical curiosity: it all runs purely in the browser.
If you are converting an old project written in pure PHP to Nette, or a project using Twig to Latte, you will appreciate the brand new converter library. You can try their online version at https://php2latte.nette.org and https://twig2latte.nette.org.
It is not about simple regular expressions, on the contrary, PHP or Twig parser is used directly, so the converter can handle any complicated syntax.
The conversion from Twig requires manual adjustment of the result, because
the conversion cannot be performed unambiguously. Twig uses a dot syntax, where
{{ a.b }}
can mean $a->b
, $a['b']
or
$a->getB()
, which can only be distinguished at runtime, not at
compile time. The converter therefore converts everything to
$a->b
. Also, some functions, filters or tags may behave slightly
differently in Latte.
Sign in to submit a comment