Nette Documentation Preview

syntax
Tags in Latte
*************

.[perex]
Resumen y descripción de todas las etiquetas Latte incorporadas.

.[table-latte-tags language-latte]
|## Impresión
| `{$var}`, `{...}` o `{=...}` | [imprime una variable o expresión escapada |#printing]
| `{$var\|filter}` | [imprime con filtros |#filters]
| `{l}` o `{r}` | imprime el carácter `{` or `}`

.[table-latte-tags language-latte]
|## Condiciones
| `{if}`... `{elseif}`... `{else}`... `{/if}` | [condición if |#if-elseif-else]
| `{ifset}`... `{elseifset}`... `{/ifset}` | [condición ifset |#ifset-elseifset]
| `{ifchanged}`... `{/ifchanged}` | [prueba si ha habido un cambio |#ifchanged]
| `{switch}` `{case}` `{default}` `{/switch}` | [condition switch |#switch-case-default]
| `n:else` | [contenido alternativo para las condiciones |#n:else]

.[table-latte-tags language-latte]
|## Bucles
| `{foreach}`... `{/foreach}` | [foreach |#foreach]
| `{for}`... `{/for}` | [for |#for]
| `{while}`... `{/while}` | [while |#while]
| `{continueIf $cond}` | [Continúa en la siguiente iteración |#continueif-skipif-breakif].
| `{skipIf $cond}` | [salta la iteración actual del bucle|#continueif-skipif-breakif]
| `{breakIf $cond}` | [rompe el bucle |#continueif-skipif-breakif]
| `{exitIf $cond}` | [Salida anticipada |#exitif]
| `{first}`... `{/first}` | [¿Es la primera iteración? |#first-last-sep]
| `{last}`... `{/last}` | [¿Es la última iteración? |#first-last-sep]
| `{sep}`... `{/sep}` | [¿Seguirá la siguiente iteración? |#first-last-sep]
| `{iterateWhile}`... `{/iterateWhile}` | [foreach estructurado |#iterateWhile]
| `$iterator` | [Variable especial dentro del bucle foreach |#$iterator]

.[table-latte-tags language-latte]
|## Incluyendo otras Plantillas
| `{include 'file.latte'}` | [incluye una plantilla de otro archivo |#include]
| `{sandbox 'file.latte'}` | [incluye una plantilla en modo sandbox |#sandbox]

.[table-latte-tags language-latte]
|## Bloques, diseños, herencia de plantillas
| `{block}` | [bloque anónimo |#block]
| `{block blockname}` | [definición de bloque |template-inheritance#blocks]
| `{define blockname}` | [definición de bloque para uso futuro |template-inheritance#definitions]
| `{include blockname}` | [imprime un bloque |template-inheritance#printing-blocks]
| `{include blockname from 'file.latte'}` | [imprime un bloque desde un archivo |template-inheritance#printing-blocks]
| `{import 'file.latte'}` | [carga bloques de otra plantilla |template-inheritance#horizontal-reuse]
| `{layout 'file.latte'}` / `{extends}` | [especifica un archivo de diseño |template-inheritance#layout-inheritance]
| `{embed}`... `{/embed}` | [carga la plantilla o el bloque y permite sobrescribir los bloques|template-inheritance#unit-inheritance]
| `{ifset blockname}`... `{/ifset}` | [condiciona si el bloque está definido|template-inheritance#checking-block-existence]

.[table-latte-tags language-latte]
|## Manejo de excepciones
| `{try}`... `{else}`... `{/try}` | [captura de excepciones |#try]
| `{rollback}` | [descarta el bloque try|#rollback]

.[table-latte-tags language-latte]
|## Variables
| `{var $foo = value}` | [creación de variables|#var-default]
| `{default $foo = value}` | [valor por defecto cuando la variable no está declarada |#var-default]
| `{parameters}` | [declara variables, escribe un valor por defecto|#parameters]
| `{capture}`... `{/capture}` | [captura una sección a una variable|#capture]

.[table-latte-tags language-latte]
|## Tipos
| `{varType}` | [declara tipo de variable|type-system#varType]
| `{varPrint}` | [sugiere tipos de variables|type-system#varPrint]
| `{templateType}` | [declara tipos de variables usando clase|type-system#templateType]
| `{templatePrint}` | [genera clase con propiedades |type-system#templatePrint]

.[table-latte-tags language-latte]
|## Traducción
| `{_string}` | [imprime traducido |#Translation]
| `{translate}`... `{/translate}` | [traduce el contenido |#Translation]

.[table-latte-tags language-latte]
|## Otros
| `{contentType}` | [cambia el modo de escape y envía la cabecera HTTP |#contenttype]
| `{debugbreak}` | [establece un punto de interrupción en el código |#debugbreak]
| `{do}` | [evalúa una expresión sin imprimirla |#do]
| `{dump}` | [vuelca variables a la Tracy Bar |#dump]
| `{php}` | [ejecuta cualquier código PHP |#php]
| `{spaceless}`... `{/spaceless}` | [elimina los espacios en blanco innecesarios |#spaceless].
| `{syntax}` | [cambia la sintaxis en tiempo de ejecución |#syntax]
| `{trace}` | [muestra la traza de la pila |#trace]

.[table-latte-tags language-latte]
|## Ayudantes de etiquetas HTML
| `n:class` | [atributo de clase inteligente|#n:class]
| `n:attr` | [atributos HTML inteligentes|#n:attr]
| `n:tag` | [nombre dinámico del elemento HTML|#n:tag]
| `n:ifcontent` | [Omitir etiqueta HTML vacía |#n:ifcontent]

.[table-latte-tags language-latte]
|## Disponible sólo en Nette Framework
| `n:href` | [enlace en elementos HTML `<a>`  |application:creating-links#In the Presenter Template]
| `{link}` | [imprime un enlace |application:creating-links#In the Presenter Template]
| `{plink}` | [imprime un enlace a un [presentador |application:creating-links#In the Presenter Template]
| `{control}` | [imprime un componente |application:components#Rendering]
| `{snippet}`... `{/snippet}` | [un fragmento de plantilla que puede ser enviado por AJAX |application:ajax#snippets-in-latte]
| `{snippetArea}` | [snippets sobre |application:ajax#snippet-areas]
| `{cache}`... `{/cache}` | [almacena en caché una sección de plantilla|caching:#caching-in-latte]

.[table-latte-tags language-latte]
|## Disponible sólo con Nette Forms
| `{form}`... `{/form}` | [imprime un elemento de formulario|forms:rendering#form]
| `{label}`... `{/label}` | [imprime una etiqueta de entrada de formulario|forms:rendering#label-input]
| `{input}` | [imprime un elemento del formulario|forms:rendering#label-input]
| `{inputError}` | [imprime un mensaje de error para el elemento de entrada del formulario|forms:rendering#inputError]
| `n:name` | [activa un elemento de entrada HTML |forms:rendering#n:name]
| `{formContainer}`... `{/formContainer}` | [renderización del contenedor de formularios |forms:rendering#special-cases]


Impresión .[#toc-printing]
==========================


`{$var}` `{...}` `{=...}`
-------------------------

Latte utiliza la etiqueta `{=...}` para imprimir cualquier expresión en la salida. Si la expresión comienza con una variable o llamada a una función, no hay necesidad de escribir un signo igual. Lo que en la práctica significa que casi nunca es necesario escribirlo:

```latte
Name: {$name} {$surname}<br>
Age: {date('Y') - $birth}<br>
```

Puedes escribir cualquier cosa que conozcas de PHP como una expresión. Simplemente no tienes que aprender un nuevo lenguaje. Por ejemplo:


```latte
{='0' . ($num ?? $num * 3) . ', ' . PHP_VERSION}
```

Por favor, no busque ningún significado en el ejemplo anterior, pero si encuentra alguno, escríbanos :-)


Salida de escape .[#toc-escaping-output]
----------------------------------------

¿Cuál es la tarea más importante de un sistema de plantillas? Evitar agujeros de seguridad. Y eso es exactamente lo que Latte hace cada vez que imprimes algo a la salida. Automáticamente escapa todo:

```latte
<p>{='one < two'}</p>   {* prints: '<p>one &lt; two</p>' *}
```

Para ser precisos, Latte utiliza el escape sensible al contexto, que es una característica tan importante y única que le hemos dedicado [un capítulo aparte|safety-first#context-aware-escaping].

¿Y si imprimes contenido codificado en HTML de una fuente de confianza? Entonces puede desactivar fácilmente el escape:

```latte
{$trustedHtmlString|noescape}
```

.[warning]
El uso incorrecto del filtro `noescape` puede dar lugar a una vulnerabilidad XSS. Nunca lo utilices a menos que estés **absolutamente seguro** de lo que estás haciendo y de que la cadena que estás imprimiendo proviene de una fuente de confianza.


Impresión en JavaScript .[#toc-printing-in-javascript]
------------------------------------------------------

Gracias al escape sensible al contexto, es maravillosamente fácil imprimir variables dentro de JavaScript, y Latte las escapará correctamente.

La variable no tiene por qué ser una cadena, cualquier tipo de datos es compatible, que luego se codifica como JSON:

```latte
{var $foo = ['hello', true, 1]}
<script>
	alert({$foo});
</script>
```

Genera:

```latte
<script>
	alert(["hello", true, 1]);
</script>
```

Esta es también la razón por la que **no ponga la variable entre comillas**: Latte las añade alrededor de las cadenas. Y si quieres poner una variable de cadena dentro de otra cadena, simplemente concaténalas:

```latte
<script>
	alert('Hello ' + {$name} + '!');  // OK

	alert({="Hello $name!"});         // OK

	alert('Hello {$name} !');         // ERROR!
</script>
```


Filtros .[#toc-filters]
-----------------------

La expresión impresa puede modificarse [mediante |syntax#filters] filtros. Por ejemplo, este ejemplo convierte la cadena a mayúsculas y la acorta a un máximo de 30 caracteres:

```latte
{$string|upper|truncate:30}
```

También puede aplicar filtros a partes de una expresión de la siguiente manera:

```latte
{$left . ($middle|upper) . $right}
```


Condiciones .[#toc-conditions]
==============================


`{if}` `{elseif}` `{else}`
--------------------------

Las condiciones se comportan de la misma manera que sus equivalentes en PHP. Puedes usar las mismas expresiones que conoces de PHP, no tienes que aprender un nuevo lenguaje.

```latte
{if $product->inStock > Stock::Minimum}
	In stock
{elseif $product->isOnWay()}
	On the way
{else}
	Not available
{/if}
```

Como cualquier etiqueta de par, un par de `{if} ... {/ if}` puede escribirse como [n:atributo |syntax#n:attributes], por ejemplo:

```latte
<p n:if="$count > 0">In stock {$count} items</p>
```

¿Sabe que puede añadir el prefijo `tag-` a n:atributos? Entonces la condición sólo afectará a las etiquetas HTML y el contenido entre ellas se imprimirá siempre:

```latte
<a href="..." n:tag-if="$clickable">Hello</a>

{* prints 'Hello' when $clickable is falsey *}
{* prints '<a href="...">Hello</a>' when $clickable is truthy *}
```

Bien.


`n:else` .{data-version:3.0.11}
-------------------------------

Si escribe la condición `{if} ... {/if}` en forma de [atributo n: |syntax#n:attributes]tiene la opción de especificar una rama alternativa utilizando `n:else`:

```latte
<strong n:if="$count > 0">In stock {$count} items</strong>

<em n:else>not available</em>
```

El atributo `n:else` también puede utilizarse junto con [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent]y [`n:ifchanged` |#ifchanged].


`{/if $cond}`
-------------

Quizá le sorprenda que la expresión de la condición `{if}` también pueda especificarse en la etiqueta final. Esto es útil en situaciones en las que aún no conocemos el valor de la condición cuando se abre la etiqueta. Llamémoslo decisión diferida.

Por ejemplo, empezamos a listar una tabla con registros de la base de datos, y sólo después de completar el informe nos damos cuenta de que no había ningún registro en la base de datos. Entonces ponemos la condición en la etiqueta final `{/if}` y si no hay ningún registro, no se imprimirá ninguno:

```latte
{if}
	<h1>Printing rows from the database</h1>

	<table>
	{foreach $resultSet as $row}
		...
	{/foreach}
	</table>
{/if isset($row)}
```

Práctico, ¿verdad?

También puede utilizar `{else}` en la condición diferida, pero no `{elseif}`.


`{ifset}` `{elseifset}`
-----------------------

.[note]
Véase también [`{ifset block}` |template-inheritance#checking-block-existence]

Utilice la condición `{ifset $var}` para determinar si una variable (o múltiples variables) existe y tiene un valor no nulo. En realidad es lo mismo que `if (isset($var))` en PHP. Como cualquier etiqueta de par, esto puede ser escrito en la forma de [n:attribute |syntax#n:attributes], así que vamos a mostrarlo en el ejemplo:

```latte
<meta name="robots" content="{$robots}" n:ifset="$robots">
```


`{ifchanged}`
-------------

`{ifchanged}` comprueba si el valor de una variable ha cambiado desde la última iteración del bucle (foreach, for o while).

Si especificamos una o más variables en la etiqueta, comprobará si alguna de ellas ha cambiado e imprime el contenido en consecuencia. Por ejemplo, el siguiente ejemplo imprime la primera letra de un nombre como encabezado cada vez que cambia al listar nombres:

```latte
{foreach ($names|sort) as $name}
	{ifchanged $name[0]} <h2>{$name[0]}</h2> {/ifchanged}

	<p>{$name}</p>
{/foreach}
```

Sin embargo, si no se da ningún argumento, el contenido renderizado se comprobará con su estado anterior. Esto significa que en el ejemplo anterior, podemos omitir con seguridad el argumento en la etiqueta. Y, por supuesto, también podemos utilizar [n:attribute |syntax#n:attributes]:

```latte
{foreach ($names|sort) as $name}
	<h2 n:ifchanged>{$name[0]}</h2>

	<p>{$name}</p>
{/foreach}
```

También se puede incluir una cláusula `{else}` dentro de `{ifchanged}`.


`{switch}` `{case}` `{default}`
-------------------------------
Compara el valor con múltiples opciones. Es similar a la estructura `switch` que conoce de PHP. Sin embargo, Latte la mejora:

- utiliza comparación estricta (`===`)
- no necesita un `break`

Así que es el equivalente exacto de la estructura `match` con la que viene PHP 8.0.

```latte
{switch $transport}
	{case train}
		By train
	{case plane}
		By plane
	{default}
		Differently
{/switch}
```

La cláusula `{case}` puede contener múltiples valores separados por comas:

```latte
{switch $status}
{case $status::New}<b>new item</b>
{case $status::Sold, $status::Unknown}<i>not available</i>
{/switch}
```


Bucles .[#toc-loops]
====================

En Latte, todos los bucles que conoces de PHP están a tu disposición: foreach, for y while.


`{foreach}`
-----------

El ciclo se escribe exactamente igual que en PHP:

```latte
{foreach $langs as $code => $lang}
	<span>{$lang}</span>
{/foreach}
```

Además, tiene algunos ajustes útiles de los que hablaremos ahora.

Por ejemplo, Latte comprueba que las variables creadas no sobrescriban accidentalmente las variables globales del mismo nombre. Esto te salvará cuando asumas que `$lang` es el idioma actual de la página, y no te des cuenta de que `foreach $langs as $lang` ha sobrescrito esa variable.

El bucle foreach también puede escribirse de forma muy elegante y económica con [n:attribute |syntax#n:attributes]:

```latte
<ul>
	<li n:foreach="$items as $item">{$item->name}</li>
</ul>
```

¿Sabía que puede anteponer el prefijo `inner-` a n:attributes? Ahora sólo se repetirá en el bucle la parte interior del elemento:

```latte
<div n:inner-foreach="$items as $item">
	<h4>{$item->title}</h4>
	<p>{$item->description}</p>
</div>
```

Así que imprime algo como:

```latte
<div>
	<h4>Foo</h4>
	<p>Lorem ipsum.</p>
	<h4>Bar</h4>
	<p>Sit dolor.</p>
</div>
```


`{else}` .{toc: foreach-else}
-----------------------------

El bucle `foreach` puede tomar una cláusula opcional `{else}` cuyo texto se muestra si la matriz dada está vacía:

```latte
<ul>
	{foreach $people as $person}
		<li>{$person->name}</li>
	{else}
		<li><em>Sorry, no users in this list</em></li>
	{/foreach}
</ul>
```


`$iterator`
-----------

Dentro del bucle `foreach` se inicializa la variable `$iterator`. Contiene información importante sobre el bucle actual.

- `$iterator->first` - ¿es ésta la primera iteración?
- `$iterator->last` - ¿es la última iteración?
- `$iterator->counter` - contador de iteraciones, comienza en 1
- `$iterator->counter0` - contador de iteraciones, comienza en 0
- `$iterator->odd` - ¿es esta iteración impar?
- `$iterator->even` - ¿es esta iteración par?
- `$iterator->parent` - el iterador que rodea al actual
- `$iterator->nextValue` - el siguiente elemento en el bucle
- `$iterator->nextKey` - la clave del siguiente elemento del bucle


```latte
{foreach $rows as $row}
	{if $iterator->first}<table>{/if}

	<tr id="row-{$iterator->counter}">
		<td>{$row->name}</td>
		<td>{$row->email}</td>
	</tr>

	{if $iterator->last}</table>{/if}
{/foreach}
```

El latte es inteligente y `$iterator->last` funciona no sólo para matrices, sino también cuando el bucle se ejecuta sobre un iterador general donde el número de elementos no se conoce de antemano.


`{first}` `{last}` `{sep}`
--------------------------

Estas etiquetas pueden utilizarse dentro del bucle `{foreach}`. El contenido de `{first}` se renderiza en la primera pasada.
El contenido de `{last}` se renderiza... ¿lo adivina? Sí, en la última pasada. En realidad son atajos para `{if $iterator->first}` y `{if $iterator->last}`.

Las etiquetas también pueden escribirse como [n:attributes |syntax#n:attributes]:

```latte
{foreach $rows as $row}
	{first}<h1>List of names</h1>{/first}

	<p>{$row->name}</p>

	<hr n:last>
{/foreach}
```

El contenido de `{sep}` se muestra si la iteración no es la última, por lo que es adecuado para imprimir delimitadores, como comas entre elementos de la lista:

```latte
{foreach $items as $item} {$item} {sep}, {/sep} {/foreach}
```

Es bastante práctico, ¿no?


`{iterateWhile}`
----------------

Simplifica la agrupación de datos lineales durante la iteración en un bucle foreach realizando la iteración en un bucle anidado mientras se cumpla la condición. [Lee las instrucciones en el cookbook |cookbook/iteratewhile].

También puede sustituir elegantemente a `{first}` y `{last}` en el ejemplo anterior:

```latte
{foreach $rows as $row}
	<table>

	{iterateWhile}
	<tr id="row-{$iterator->counter}">
		<td>{$row->name}</td>
		<td>{$row->email}</td>
	</tr>
	{/iterateWhile true}

	</table>
{/foreach}
```


`{for}`
-------

Escribimos el ciclo exactamente igual que en PHP:

```latte
{for $i = 0; $i < 10; $i++}
	<span>Item #{$i}</span>
{/for}
```

La etiqueta también se puede escribir como [n:attribute |syntax#n:attributes]:

```latte
<h1 n:for="$i = 0; $i < 10; $i++">{$i}</h1>
```


`{while}`
---------

De nuevo, escribimos el ciclo exactamente igual que en PHP:

```latte
{while $row = $result->fetch()}
	<span>{$row->title}</span>
{/while}
```

O como [n:attribute |syntax#n:attributes]:

```latte
<span n:while="$row = $result->fetch()">
	{$row->title}
</span>
```

Una variante con una condición en la etiqueta final corresponde al bucle do-while en PHP:

```latte
{while}
	<span>{$item->title}</span>
{/while $item = $item->getNext()}
```


`{continueIf}` `{skipIf}` `{breakIf}`
-------------------------------------

Hay etiquetas especiales que puedes utilizar para controlar cualquier bucle - `{continueIf ?}` y `{breakIf ?}` que saltan a la siguiente iteración y terminan el bucle, respectivamente, si se cumplen las condiciones:

```latte
{foreach $rows as $row}
	{continueIf $row->date < $now}
	{breakIf $row->parent === null}
	...
{/foreach}
```


La etiqueta `{skipIf}` es muy similar a `{continueIf}`, pero no incrementa el contador. Así no hay agujeros en la numeración cuando se imprime `$iterator->counter` y se saltan algunos elementos. Además, la cláusula {else} se mostrará cuando se salten todos los elementos.

```latte
<ul>
	{foreach $people as $person}
		{skipIf $person->age < 18}
		<li>{$iterator->counter}. {$person->name}</li>
	{else}
		<li><em>Sorry, no adult users in this list</em></li>
	{/foreach}
</ul>
```


`{exitIf}` .{data-version:3.0.5}
--------------------------------

Finaliza la renderización de una plantilla o bloque cuando se cumple una condición (es decir, "salida anticipada").

```latte
{exitIf !$messages}

<h1>Messages</h1>
<div n:foreach="$messages as $message">
   {$message}
</div>
```


Inclusión de plantillas .[#toc-including-templates]
===================================================


`{include 'file.latte'}` .{toc: include}
----------------------------------------

.[note]
Véase también [`{include block}` |template-inheritance#printing-blocks]

La etiqueta `{include}` carga y renderiza la plantilla especificada. En nuestro lenguaje PHP favorito es como:

```php
<?php include 'header.phtml'; ?>
```

Las plantillas incluidas no tienen acceso a las variables del contexto activo, pero tienen acceso a las variables globales.

Puede pasar variables a la plantilla insertada de la siguiente manera:

```latte
{include 'template.latte', foo: 'bar', id: 123}
```

El nombre de la plantilla puede ser cualquier expresión PHP:

```latte
{include $someVar}
{include $ajax ? 'ajax.latte' : 'not-ajax.latte'}
```

El contenido insertado puede ser modificado usando [filtros |syntax#filters]. El siguiente ejemplo elimina todo el material HTML y ajusta las mayúsculas y minúsculas:

```latte
<title>{include 'heading.latte' |stripHtml|capitalize}</title>
```

La [herencia de plantillas |template inheritance] **no interviene** en esto por defecto. Aunque puede añadir etiquetas de bloque a las plantillas que se incluyen, no sustituirán a los bloques coincidentes de la plantilla en la que se incluyen. Piense en los includes como partes independientes y blindadas de páginas o módulos. Este comportamiento puede cambiarse utilizando el modificador `with blocks`:

```latte
{include 'template.latte' with blocks}
```

La relación entre el nombre de archivo especificado en la etiqueta y el archivo en disco es una cuestión de [cargador |extending-latte#Loaders].


`{sandbox}`
-----------

Cuando incluya una plantilla creada por un usuario final, debería considerar la posibilidad de ponerla en un sandbox (más información en [la documentación sobre sandbox |sandbox]):

```latte
{sandbox 'untrusted.latte', level: 3, data: $menu}
```


`{block}`
=========

.[note]
Véase también [`{block name}` |template-inheritance#blocks]

Los bloques sin nombre sirven para aplicar [filtros |syntax#filters] a una parte de la plantilla. Por ejemplo, puede aplicar un filtro de [franja |filters#strip] para eliminar los espacios innecesarios:

```latte
{block|strip}
<ul>
	<li>Hello World</li>
</ul>
{/block}
```


Manejo de excepciones .[#toc-exception-handling]
================================================


`{try}`
-------

Estas etiquetas facilitan enormemente la creación de plantillas robustas.

Si se produce una excepción mientras se renderiza el bloque `{try}`, se desecha todo el bloque y la renderización continuará después:

```latte
{try}
	<ul>
		{foreach $twitter->loadTweets() as $tweet}
  			<li>{$tweet->text}</li>
		{/foreach}
	</ul>
{/try}
```

El contenido de la cláusula opcional `{else}` sólo se renderiza cuando se produce una excepción:

```latte
{try}
	<ul>
		{foreach $twitter->loadTweets() as $tweet}
  			<li>{$tweet->text}</li>
		{/foreach}
	</ul>
	{else}
	<p>Sorry, the tweets could not be loaded.</p>
{/try}
```

La etiqueta también puede escribirse como [n:attribute |syntax#n:attributes]:

```latte
<ul n:try>
	...
</ul>
```

También es posible definir [un gestor de excepciones propio |develop#exception handler] para, por ejemplo, el registro:


`{rollback}`
------------

El bloque `{try}` también puede detenerse y omitirse manualmente utilizando `{rollback}`. Así no es necesario comprobar todos los datos de entrada de antemano, y sólo durante el renderizado se puede decidir si tiene sentido renderizar el objeto.

```latte
{try}
<ul>
	{foreach $people as $person}
 		{skipIf $person->age < 18}
 		<li>{$person->name}</li>
	{else}
		{rollback}
	{/foreach}
</ul>
{/try}
```


Variables .[#toc-variables]
===========================


`{var}` `{default}`
-------------------

Crearemos nuevas variables en la plantilla con la etiqueta `{var}`:

```latte
{var $name = 'John Smith'}
{var $age = 27}

{* Multiple declaration *}
{var $name = 'John Smith', $age = 27}
```

La etiqueta `{default}` funciona de forma similar, salvo que crea variables sólo si no existen:

```latte
{default $lang = 'cs'}
```

También puede especificar [tipos de variables |type-system]. Por ahora, son informativas y Latte no las comprueba.

```latte
{var string $name = $article->getTitle()}
{default int $id = 0}
```


`{parameters}`
--------------

Al igual que una función declara sus parámetros, una plantilla puede declarar sus variables al principio:

```latte
{parameters
	$a,
	?int $b,
	int|string $c = 10
}
```

Las variables `$a` y `$b` sin valor por defecto tienen automáticamente un valor por defecto de `null`. Los tipos declarados siguen siendo informativos y Latte no los comprueba.

Aparte de las variables declaradas no se pasan a la plantilla. Esta es una diferencia con respecto a la etiqueta `{default}`.


`{capture}`
-----------

Utilizando la etiqueta `{capture}` puede capturar la salida a una variable:

```latte
{capture $var}
<ul>
	<li>Hello World</li>
</ul>
{/capture}

<p>Captured: {$var}</p>
```

La etiqueta también puede escribirse como [n:attribute |syntax#n:attributes], como cualquier etiqueta de pares:

```latte
<ul n:capture="$var">
	<li>Hello World</li>
</ul>
```

La salida HTML se almacena en la variable `$var` como un objeto `Latte\Runtime\Html` para [evitar escapes no deseados |develop#disabling-auto-escaping-of-variable] al imprimir.


Otros .[#toc-others]
====================


`{contentType}`
---------------

Utilice la etiqueta para especificar qué tipo de contenido representa la plantilla. Las opciones son:

- `html` (tipo por defecto)
- `xml`
- `javascript`
- `css`
- `calendar` (iCal)
- `text`

Su uso es importante porque establece el escape [sensible al contexto |safety-first#context-aware-escaping] y sólo entonces Latte puede escapar correctamente. Por ejemplo, `{contentType xml}` cambia al modo XML, `{contentType text}` desactiva completamente el escape.

Si el parámetro es un tipo MIME completo, como `application/xml`, también envía una cabecera HTTP `Content-Type` al navegador:

```latte
{contentType application/xml}
<?xml version="1.0"?>
<rss version="2.0">
	<channel>
		<title>RSS feed</title>
		<item>
			...
		</item>
	</channel>
</rss>
```


`{debugbreak}`
--------------

Especifica el lugar donde se interrumpirá la ejecución del código. Se utiliza con fines de depuración para que el programador inspeccione el entorno de ejecución y se asegure de que el código se ejecuta según lo esperado. Es compatible con [Xdebug |https://xdebug.org]. Además, puede especificar una condición cuando el código debe romperse.

```latte
{debugbreak}                {* breaks the program *}

{debugbreak $counter == 1}  {* breaks the program if the condition is met *}
```


`{do}`
------

Ejecuta el código PHP y no imprime nada. Al igual que con el resto de etiquetas, el código PHP es una única expresión, consulte las [limitaciones de PHP |syntax#PHP Limitations in Latte].

```latte
{do $num++}
```


`{dump}`
--------

Vuelca una variable o el contexto actual.

```latte
{dump $name} {* dumps the $name variable *}

{dump}       {* dumps all the defined variables *}
```

.[caution]
Requiere el paquete [Tracy |tracy:].


`{php}`
-------

Permite ejecutar cualquier código PHP. La etiqueta debe activarse mediante la extensión [RawPhpExtension |develop#RawPhpExtension].


`{spaceless}`
-------------

Elimina los espacios en blanco innecesarios. Es similar al filtro [sin |filters#spaceless] espacios.

```latte
{spaceless}
	<ul>
		<li>Hello</li>
	</ul>
{/spaceless}
```

Salida:

```latte
<ul> <li>Hello</li> </ul>
```

La etiqueta también puede escribirse como [n:atributo |syntax#n:attributes]:


`{syntax}`
----------

Las etiquetas Latte no tienen por qué ir encerradas únicamente entre llaves. Puede elegir otro separador, incluso en tiempo de ejecución. Esto se hace mediante `{syntax…}`, donde el parámetro puede ser:

- doble: `{{...}}`
- off: desactiva completamente las etiquetas Latte

Utilizando la notación n:attribute podemos desactivar Latte sólo para un bloque JavaScript:

```latte
<script n:syntax="off">
	var obj = {var: 123}; // this isn't a tag any more
</script>
```

Latte se puede utilizar muy cómodamente dentro de JavaScript, sólo hay que evitar construcciones como en este ejemplo, donde la letra sigue inmediatamente a `{`, ver [Latte dentro de JavaScript o CSS |recipes#Latte inside JavaScript or CSS].

Si desactiva Latte con `{syntax off}` (es decir, la etiqueta, no el atributo n:attribute), ignorará estrictamente todas las etiquetas hasta `{/syntax}`.


{trace}
-------

Lanza una excepción `Latte\RuntimeException`, cuya traza de pila sigue el espíritu de las plantillas. Así, en lugar de llamar a funciones y métodos, se trata de llamar a bloques e insertar plantillas. Si utiliza una herramienta para mostrar claramente las excepciones lanzadas, como [Tracy |tracy:], verá claramente la pila de llamadas, incluidos todos los argumentos pasados.


Ayudantes de etiquetas HTML .[#toc-html-tag-helpers]
====================================================


n:clase .[#toc-n-class]
-----------------------

Gracias a `n:class`, es muy fácil generar el atributo HTML `class` exactamente como lo necesita.

Ejemplo: Necesito que el elemento activo tenga la clase `active`:

```latte
{foreach $items as $item}
	<a n:class="$item->isActive() ? active">...</a>
{/foreach}
```

Y además necesito que el primer elemento tenga las clases `first` y `main`:

```latte
{foreach $items as $item}
	<a n:class="$item->isActive() ? active, $iterator->first ? 'first main'">...</a>
{/foreach}
```

Y que todos los elementos tengan la clase `list-item`:

```latte
{foreach $items as $item}
	<a n:class="$item->isActive() ? active, $iterator->first ? 'first main', list-item">...</a>
{/foreach}
```

Asombrosamente sencillo, ¿verdad?


n:attr .[#toc-n-attr]
---------------------

El atributo `n:attr` puede generar atributos HTML arbitrarios con la misma elegancia que [n:class |#n:class].

```latte
{foreach $data as $item}
	<input type="checkbox" n:attr="value: $item->getValue(), checked: $item->isActive()">
{/foreach}
```

En función de los valores devueltos, muestra, por ejemplo

```latte
<input type="checkbox">

<input type="checkbox" value="Hello">

<input type="checkbox" value="Hello" checked>
```


n:tag
-----

El atributo `n:tag` puede cambiar dinámicamente el nombre de un elemento HTML.

```latte
<h1 n:tag="$heading" class="main">{$title}</h1>
```

Si `$heading === null`, la etiqueta `<h1>` se imprime sin cambios. De lo contrario, el nombre del elemento se cambia por el valor de la variable, por lo que para `$heading === 'h3'` escribe:

```latte
<h3 class="main">...</h3>
```

Como Latte es un sistema de plantillas seguro, comprueba que el nuevo nombre de la etiqueta sea válido y no contenga valores no deseados o maliciosos.


n:ifcontent .[#toc-n-ifcontent]
-------------------------------

Evita que se imprima un elemento HTML vacío, es decir, un elemento que sólo contiene espacios en blanco.

```latte
<div>
	<div class="error" n:ifcontent>{$error}</div>
</div>
```

Dependiendo de los valores de la variable `$error` se imprimirá:

```latte
{* $error = '' *}
<div>
</div>

{* $error = 'Required' *}
<div>
	<div class="error">Required</div>
</div>
```


Traducción .[#toc-translation]
==============================

Para que las etiquetas de traducción funcionen, necesitas [configurar el traductor |develop#TranslatorExtension]. También puede utilizar el [`translate` |filters#translate] para la traducción.


`{_...}`
--------

Traduce los valores a otros idiomas.

```latte
<a href="basket">{_'Basket'}</a>
<span>{_$item}</span>
```

También se pueden pasar otros parámetros al traductor:

```latte
<a href="basket">{_'Basket', domain: order}</a>
```


`{translate}`
-------------

Překládá části šablony:

```latte
<h1>{translate}Order{/translate}</h1>

{translate domain: order}Lorem ipsum ...{/translate}
```

La etiqueta también puede escribirse como [n:attribute |syntax#n:attributes], para traducir el interior del elemento:

```latte
<h1 n:translate>Order</h1>
```

Tags in Latte

Resumen y descripción de todas las etiquetas Latte incorporadas.

Impresión
{$var}, {...} o {=...} imprime una variable o expresión escapada
{$var|filter} imprime con filtros
{l} o {r} imprime el carácter { or }
Condiciones
{if}{elseif}{else}{/if} condición if
{ifset}{elseifset}{/ifset} condición ifset
{ifchanged}{/ifchanged} prueba si ha habido un cambio
{switch} {case} {default} {/switch} condition switch
n:else contenido alternativo para las condiciones
Bucles
{foreach}{/foreach} foreach
{for}{/for} for
{while}{/while} while
{continueIf $cond} Continúa en la siguiente iteración.
{skipIf $cond} salta la iteración actual del bucle
{breakIf $cond} rompe el bucle
{exitIf $cond} Salida anticipada
{first}{/first} ¿Es la primera iteración?
{last}{/last} ¿Es la última iteración?
{sep}{/sep} ¿Seguirá la siguiente iteración?
{iterateWhile}{/iterateWhile} foreach estructurado
$iterator Variable especial dentro del bucle foreach
Incluyendo otras Plantillas
{include 'file.latte'} incluye una plantilla de otro archivo
{sandbox 'file.latte'} incluye una plantilla en modo sandbox
Bloques, diseños, herencia de plantillas
{block} bloque anónimo
{block blockname} definición de bloque
{define blockname} definición de bloque para uso futuro
{include blockname} imprime un bloque
{include blockname from 'file.latte'} imprime un bloque desde un archivo
{import 'file.latte'} carga bloques de otra plantilla
{layout 'file.latte'} / {extends} especifica un archivo de diseño
{embed}{/embed} carga la plantilla o el bloque y permite sobrescribir los bloques
{ifset blockname}{/ifset} condiciona si el bloque está definido
Manejo de excepciones
{try}{else}{/try} captura de excepciones
{rollback} descarta el bloque try
Variables
{var $foo = value} creación de variables
{default $foo = value} valor por defecto cuando la variable no está declarada
{parameters} declara variables, escribe un valor por defecto
{capture}{/capture} captura una sección a una variable
Tipos
{varType} declara tipo de variable
{varPrint} sugiere tipos de variables
{templateType} declara tipos de variables usando clase
{templatePrint} genera clase con propiedades
Traducción
{_string} imprime traducido
{translate}{/translate} traduce el contenido
Otros
{contentType} cambia el modo de escape y envía la cabecera HTTP
{debugbreak} establece un punto de interrupción en el código
{do} evalúa una expresión sin imprimirla
{dump} vuelca variables a la Tracy Bar
{php} ejecuta cualquier código PHP
{spaceless}{/spaceless} elimina los espacios en blanco innecesarios.
{syntax} cambia la sintaxis en tiempo de ejecución
{trace} muestra la traza de la pila
Ayudantes de etiquetas HTML
n:class atributo de clase inteligente
n:attr atributos HTML inteligentes
n:tag nombre dinámico del elemento HTML
n:ifcontent Omitir etiqueta HTML vacía
Disponible sólo en Nette Framework
n:href enlace en elementos HTML <a>
{link} imprime un enlace
{plink} imprime un enlace a un [presentador
{control} imprime un componente
{snippet}{/snippet} un fragmento de plantilla que puede ser enviado por AJAX
{snippetArea} snippets sobre
{cache}{/cache} almacena en caché una sección de plantilla
Disponible sólo con Nette Forms
{form}{/form} imprime un elemento de formulario
{label}{/label} imprime una etiqueta de entrada de formulario
{input} imprime un elemento del formulario
{inputError} imprime un mensaje de error para el elemento de entrada del formulario
n:name activa un elemento de entrada HTML
{formContainer}{/formContainer} renderización del contenedor de formularios

Impresión

{$var} {...} {=...}

Latte utiliza la etiqueta {=...} para imprimir cualquier expresión en la salida. Si la expresión comienza con una variable o llamada a una función, no hay necesidad de escribir un signo igual. Lo que en la práctica significa que casi nunca es necesario escribirlo:

Name: {$name} {$surname}<br>
Age: {date('Y') - $birth}<br>

Puedes escribir cualquier cosa que conozcas de PHP como una expresión. Simplemente no tienes que aprender un nuevo lenguaje. Por ejemplo:

{='0' . ($num ?? $num * 3) . ', ' . PHP_VERSION}

Por favor, no busque ningún significado en el ejemplo anterior, pero si encuentra alguno, escríbanos :-)

Salida de escape

¿Cuál es la tarea más importante de un sistema de plantillas? Evitar agujeros de seguridad. Y eso es exactamente lo que Latte hace cada vez que imprimes algo a la salida. Automáticamente escapa todo:

<p>{='one < two'}</p>   {* prints: '<p>one &lt; two</p>' *}

Para ser precisos, Latte utiliza el escape sensible al contexto, que es una característica tan importante y única que le hemos dedicado un capítulo aparte.

¿Y si imprimes contenido codificado en HTML de una fuente de confianza? Entonces puede desactivar fácilmente el escape:

{$trustedHtmlString|noescape}

El uso incorrecto del filtro noescape puede dar lugar a una vulnerabilidad XSS. Nunca lo utilices a menos que estés absolutamente seguro de lo que estás haciendo y de que la cadena que estás imprimiendo proviene de una fuente de confianza.

Impresión en JavaScript

Gracias al escape sensible al contexto, es maravillosamente fácil imprimir variables dentro de JavaScript, y Latte las escapará correctamente.

La variable no tiene por qué ser una cadena, cualquier tipo de datos es compatible, que luego se codifica como JSON:

{var $foo = ['hello', true, 1]}
<script>
	alert({$foo});
</script>

Genera:

<script>
	alert(["hello", true, 1]);
</script>

Esta es también la razón por la que no ponga la variable entre comillas: Latte las añade alrededor de las cadenas. Y si quieres poner una variable de cadena dentro de otra cadena, simplemente concaténalas:

<script>
	alert('Hello ' + {$name} + '!');  // OK

	alert({="Hello $name!"});         // OK

	alert('Hello {$name} !');         // ERROR!
</script>

Filtros

La expresión impresa puede modificarse mediante filtros. Por ejemplo, este ejemplo convierte la cadena a mayúsculas y la acorta a un máximo de 30 caracteres:

{$string|upper|truncate:30}

También puede aplicar filtros a partes de una expresión de la siguiente manera:

{$left . ($middle|upper) . $right}

Condiciones

{if} {elseif} {else}

Las condiciones se comportan de la misma manera que sus equivalentes en PHP. Puedes usar las mismas expresiones que conoces de PHP, no tienes que aprender un nuevo lenguaje.

{if $product->inStock > Stock::Minimum}
	In stock
{elseif $product->isOnWay()}
	On the way
{else}
	Not available
{/if}

Como cualquier etiqueta de par, un par de {if} ... {/ if} puede escribirse como n:atributo, por ejemplo:

<p n:if="$count > 0">In stock {$count} items</p>

¿Sabe que puede añadir el prefijo tag- a n:atributos? Entonces la condición sólo afectará a las etiquetas HTML y el contenido entre ellas se imprimirá siempre:

<a href="..." n:tag-if="$clickable">Hello</a>

{* prints 'Hello' when $clickable is falsey *}
{* prints '<a href="...">Hello</a>' when $clickable is truthy *}

Bien.

n:else

Si escribe la condición {if} ... {/if} en forma de atributo n:tiene la opción de especificar una rama alternativa utilizando n:else:

<strong n:if="$count > 0">In stock {$count} items</strong>

<em n:else>not available</em>

El atributo n:else también puede utilizarse junto con n:ifset, n:foreach, n:try, n:ifcontenty n:ifchanged.

{/if $cond}

Quizá le sorprenda que la expresión de la condición {if} también pueda especificarse en la etiqueta final. Esto es útil en situaciones en las que aún no conocemos el valor de la condición cuando se abre la etiqueta. Llamémoslo decisión diferida.

Por ejemplo, empezamos a listar una tabla con registros de la base de datos, y sólo después de completar el informe nos damos cuenta de que no había ningún registro en la base de datos. Entonces ponemos la condición en la etiqueta final {/if} y si no hay ningún registro, no se imprimirá ninguno:

{if}
	<h1>Printing rows from the database</h1>

	<table>
	{foreach $resultSet as $row}
		...
	{/foreach}
	</table>
{/if isset($row)}

Práctico, ¿verdad?

También puede utilizar {else} en la condición diferida, pero no {elseif}.

{ifset} {elseifset}

Véase también {ifset block}

Utilice la condición {ifset $var} para determinar si una variable (o múltiples variables) existe y tiene un valor no nulo. En realidad es lo mismo que if (isset($var)) en PHP. Como cualquier etiqueta de par, esto puede ser escrito en la forma de n:attribute, así que vamos a mostrarlo en el ejemplo:

<meta name="robots" content="{$robots}" n:ifset="$robots">

{ifchanged}

{ifchanged} comprueba si el valor de una variable ha cambiado desde la última iteración del bucle (foreach, for o while).

Si especificamos una o más variables en la etiqueta, comprobará si alguna de ellas ha cambiado e imprime el contenido en consecuencia. Por ejemplo, el siguiente ejemplo imprime la primera letra de un nombre como encabezado cada vez que cambia al listar nombres:

{foreach ($names|sort) as $name}
	{ifchanged $name[0]} <h2>{$name[0]}</h2> {/ifchanged}

	<p>{$name}</p>
{/foreach}

Sin embargo, si no se da ningún argumento, el contenido renderizado se comprobará con su estado anterior. Esto significa que en el ejemplo anterior, podemos omitir con seguridad el argumento en la etiqueta. Y, por supuesto, también podemos utilizar n:attribute:

{foreach ($names|sort) as $name}
	<h2 n:ifchanged>{$name[0]}</h2>

	<p>{$name}</p>
{/foreach}

También se puede incluir una cláusula {else} dentro de {ifchanged}.

{switch} {case} {default}

Compara el valor con múltiples opciones. Es similar a la estructura switch que conoce de PHP. Sin embargo, Latte la mejora:

  • utiliza comparación estricta (===)
  • no necesita un break

Así que es el equivalente exacto de la estructura match con la que viene PHP 8.0.

{switch $transport}
	{case train}
		By train
	{case plane}
		By plane
	{default}
		Differently
{/switch}

La cláusula {case} puede contener múltiples valores separados por comas:

{switch $status}
{case $status::New}<b>new item</b>
{case $status::Sold, $status::Unknown}<i>not available</i>
{/switch}

Bucles

En Latte, todos los bucles que conoces de PHP están a tu disposición: foreach, for y while.

{foreach}

El ciclo se escribe exactamente igual que en PHP:

{foreach $langs as $code => $lang}
	<span>{$lang}</span>
{/foreach}

Además, tiene algunos ajustes útiles de los que hablaremos ahora.

Por ejemplo, Latte comprueba que las variables creadas no sobrescriban accidentalmente las variables globales del mismo nombre. Esto te salvará cuando asumas que $lang es el idioma actual de la página, y no te des cuenta de que foreach $langs as $lang ha sobrescrito esa variable.

El bucle foreach también puede escribirse de forma muy elegante y económica con n:attribute:

<ul>
	<li n:foreach="$items as $item">{$item->name}</li>
</ul>

¿Sabía que puede anteponer el prefijo inner- a n:attributes? Ahora sólo se repetirá en el bucle la parte interior del elemento:

<div n:inner-foreach="$items as $item">
	<h4>{$item->title}</h4>
	<p>{$item->description}</p>
</div>

Así que imprime algo como:

<div>
	<h4>Foo</h4>
	<p>Lorem ipsum.</p>
	<h4>Bar</h4>
	<p>Sit dolor.</p>
</div>

{else}

El bucle foreach puede tomar una cláusula opcional {else} cuyo texto se muestra si la matriz dada está vacía:

<ul>
	{foreach $people as $person}
		<li>{$person->name}</li>
	{else}
		<li><em>Sorry, no users in this list</em></li>
	{/foreach}
</ul>

$iterator

Dentro del bucle foreach se inicializa la variable $iterator. Contiene información importante sobre el bucle actual.

  • $iterator->first – ¿es ésta la primera iteración?
  • $iterator->last – ¿es la última iteración?
  • $iterator->counter – contador de iteraciones, comienza en 1
  • $iterator->counter0 – contador de iteraciones, comienza en 0
  • $iterator->odd – ¿es esta iteración impar?
  • $iterator->even – ¿es esta iteración par?
  • $iterator->parent – el iterador que rodea al actual
  • $iterator->nextValue – el siguiente elemento en el bucle
  • $iterator->nextKey – la clave del siguiente elemento del bucle
{foreach $rows as $row}
	{if $iterator->first}<table>{/if}

	<tr id="row-{$iterator->counter}">
		<td>{$row->name}</td>
		<td>{$row->email}</td>
	</tr>

	{if $iterator->last}</table>{/if}
{/foreach}

El latte es inteligente y $iterator->last funciona no sólo para matrices, sino también cuando el bucle se ejecuta sobre un iterador general donde el número de elementos no se conoce de antemano.

{first} {last} {sep}

Estas etiquetas pueden utilizarse dentro del bucle {foreach}. El contenido de {first} se renderiza en la primera pasada. El contenido de {last} se renderiza… ¿lo adivina? Sí, en la última pasada. En realidad son atajos para {if $iterator->first} y {if $iterator->last}.

Las etiquetas también pueden escribirse como n:attributes:

{foreach $rows as $row}
	{first}<h1>List of names</h1>{/first}

	<p>{$row->name}</p>

	<hr n:last>
{/foreach}

El contenido de {sep} se muestra si la iteración no es la última, por lo que es adecuado para imprimir delimitadores, como comas entre elementos de la lista:

{foreach $items as $item} {$item} {sep}, {/sep} {/foreach}

Es bastante práctico, ¿no?

{iterateWhile}

Simplifica la agrupación de datos lineales durante la iteración en un bucle foreach realizando la iteración en un bucle anidado mientras se cumpla la condición. Lee las instrucciones en el cookbook.

También puede sustituir elegantemente a {first} y {last} en el ejemplo anterior:

{foreach $rows as $row}
	<table>

	{iterateWhile}
	<tr id="row-{$iterator->counter}">
		<td>{$row->name}</td>
		<td>{$row->email}</td>
	</tr>
	{/iterateWhile true}

	</table>
{/foreach}

{for}

Escribimos el ciclo exactamente igual que en PHP:

{for $i = 0; $i < 10; $i++}
	<span>Item #{$i}</span>
{/for}

La etiqueta también se puede escribir como n:attribute:

<h1 n:for="$i = 0; $i < 10; $i++">{$i}</h1>

{while}

De nuevo, escribimos el ciclo exactamente igual que en PHP:

{while $row = $result->fetch()}
	<span>{$row->title}</span>
{/while}

O como n:attribute:

<span n:while="$row = $result->fetch()">
	{$row->title}
</span>

Una variante con una condición en la etiqueta final corresponde al bucle do-while en PHP:

{while}
	<span>{$item->title}</span>
{/while $item = $item->getNext()}

{continueIf} {skipIf} {breakIf}

Hay etiquetas especiales que puedes utilizar para controlar cualquier bucle – {continueIf ?} y {breakIf ?} que saltan a la siguiente iteración y terminan el bucle, respectivamente, si se cumplen las condiciones:

{foreach $rows as $row}
	{continueIf $row->date < $now}
	{breakIf $row->parent === null}
	...
{/foreach}

La etiqueta {skipIf} es muy similar a {continueIf}, pero no incrementa el contador. Así no hay agujeros en la numeración cuando se imprime $iterator->counter y se saltan algunos elementos. Además, la cláusula {else} se mostrará cuando se salten todos los elementos.

<ul>
	{foreach $people as $person}
		{skipIf $person->age < 18}
		<li>{$iterator->counter}. {$person->name}</li>
	{else}
		<li><em>Sorry, no adult users in this list</em></li>
	{/foreach}
</ul>

{exitIf}

Finaliza la renderización de una plantilla o bloque cuando se cumple una condición (es decir, „salida anticipada“).

{exitIf !$messages}

<h1>Messages</h1>
<div n:foreach="$messages as $message">
   {$message}
</div>

Inclusión de plantillas

{include 'file.latte'}

Véase también {include block}

La etiqueta {include} carga y renderiza la plantilla especificada. En nuestro lenguaje PHP favorito es como:

<?php include 'header.phtml'; ?>

Las plantillas incluidas no tienen acceso a las variables del contexto activo, pero tienen acceso a las variables globales.

Puede pasar variables a la plantilla insertada de la siguiente manera:

{include 'template.latte', foo: 'bar', id: 123}

El nombre de la plantilla puede ser cualquier expresión PHP:

{include $someVar}
{include $ajax ? 'ajax.latte' : 'not-ajax.latte'}

El contenido insertado puede ser modificado usando filtros. El siguiente ejemplo elimina todo el material HTML y ajusta las mayúsculas y minúsculas:

<title>{include 'heading.latte' |stripHtml|capitalize}</title>

La herencia de plantillas no interviene en esto por defecto. Aunque puede añadir etiquetas de bloque a las plantillas que se incluyen, no sustituirán a los bloques coincidentes de la plantilla en la que se incluyen. Piense en los includes como partes independientes y blindadas de páginas o módulos. Este comportamiento puede cambiarse utilizando el modificador with blocks:

{include 'template.latte' with blocks}

La relación entre el nombre de archivo especificado en la etiqueta y el archivo en disco es una cuestión de cargador.

{sandbox}

Cuando incluya una plantilla creada por un usuario final, debería considerar la posibilidad de ponerla en un sandbox (más información en la documentación sobre sandbox):

{sandbox 'untrusted.latte', level: 3, data: $menu}

{block}

Véase también {block name}

Los bloques sin nombre sirven para aplicar filtros a una parte de la plantilla. Por ejemplo, puede aplicar un filtro de franja para eliminar los espacios innecesarios:

{block|strip}
<ul>
	<li>Hello World</li>
</ul>
{/block}

Manejo de excepciones

{try}

Estas etiquetas facilitan enormemente la creación de plantillas robustas.

Si se produce una excepción mientras se renderiza el bloque {try}, se desecha todo el bloque y la renderización continuará después:

{try}
	<ul>
		{foreach $twitter->loadTweets() as $tweet}
  			<li>{$tweet->text}</li>
		{/foreach}
	</ul>
{/try}

El contenido de la cláusula opcional {else} sólo se renderiza cuando se produce una excepción:

{try}
	<ul>
		{foreach $twitter->loadTweets() as $tweet}
  			<li>{$tweet->text}</li>
		{/foreach}
	</ul>
	{else}
	<p>Sorry, the tweets could not be loaded.</p>
{/try}

La etiqueta también puede escribirse como n:attribute:

<ul n:try>
	...
</ul>

También es posible definir un gestor de excepciones propio para, por ejemplo, el registro:

{rollback}

El bloque {try} también puede detenerse y omitirse manualmente utilizando {rollback}. Así no es necesario comprobar todos los datos de entrada de antemano, y sólo durante el renderizado se puede decidir si tiene sentido renderizar el objeto.

{try}
<ul>
	{foreach $people as $person}
 		{skipIf $person->age < 18}
 		<li>{$person->name}</li>
	{else}
		{rollback}
	{/foreach}
</ul>
{/try}

Variables

{var} {default}

Crearemos nuevas variables en la plantilla con la etiqueta {var}:

{var $name = 'John Smith'}
{var $age = 27}

{* Multiple declaration *}
{var $name = 'John Smith', $age = 27}

La etiqueta {default} funciona de forma similar, salvo que crea variables sólo si no existen:

{default $lang = 'cs'}

También puede especificar tipos de variables. Por ahora, son informativas y Latte no las comprueba.

{var string $name = $article->getTitle()}
{default int $id = 0}

{parameters}

Al igual que una función declara sus parámetros, una plantilla puede declarar sus variables al principio:

{parameters
	$a,
	?int $b,
	int|string $c = 10
}

Las variables $a y $b sin valor por defecto tienen automáticamente un valor por defecto de null. Los tipos declarados siguen siendo informativos y Latte no los comprueba.

Aparte de las variables declaradas no se pasan a la plantilla. Esta es una diferencia con respecto a la etiqueta {default}.

{capture}

Utilizando la etiqueta {capture} puede capturar la salida a una variable:

{capture $var}
<ul>
	<li>Hello World</li>
</ul>
{/capture}

<p>Captured: {$var}</p>

La etiqueta también puede escribirse como n:attribute, como cualquier etiqueta de pares:

<ul n:capture="$var">
	<li>Hello World</li>
</ul>

La salida HTML se almacena en la variable $var como un objeto Latte\Runtime\Html para evitar escapes no deseados al imprimir.

Otros

{contentType}

Utilice la etiqueta para especificar qué tipo de contenido representa la plantilla. Las opciones son:

  • html (tipo por defecto)
  • xml
  • javascript
  • css
  • calendar (iCal)
  • text

Su uso es importante porque establece el escape sensible al contexto y sólo entonces Latte puede escapar correctamente. Por ejemplo, {contentType xml} cambia al modo XML, {contentType text} desactiva completamente el escape.

Si el parámetro es un tipo MIME completo, como application/xml, también envía una cabecera HTTP Content-Type al navegador:

{contentType application/xml}
<?xml version="1.0"?>
<rss version="2.0">
	<channel>
		<title>RSS feed</title>
		<item>
			...
		</item>
	</channel>
</rss>

{debugbreak}

Especifica el lugar donde se interrumpirá la ejecución del código. Se utiliza con fines de depuración para que el programador inspeccione el entorno de ejecución y se asegure de que el código se ejecuta según lo esperado. Es compatible con Xdebug. Además, puede especificar una condición cuando el código debe romperse.

{debugbreak}                {* breaks the program *}

{debugbreak $counter == 1}  {* breaks the program if the condition is met *}

{do}

Ejecuta el código PHP y no imprime nada. Al igual que con el resto de etiquetas, el código PHP es una única expresión, consulte las limitaciones de PHP.

{do $num++}

{dump}

Vuelca una variable o el contexto actual.

{dump $name} {* dumps the $name variable *}

{dump}       {* dumps all the defined variables *}

Requiere el paquete Tracy.

{php}

Permite ejecutar cualquier código PHP. La etiqueta debe activarse mediante la extensión RawPhpExtension.

{spaceless}

Elimina los espacios en blanco innecesarios. Es similar al filtro sin espacios.

{spaceless}
	<ul>
		<li>Hello</li>
	</ul>
{/spaceless}

Salida:

<ul> <li>Hello</li> </ul>

La etiqueta también puede escribirse como n:atributo:

{syntax}

Las etiquetas Latte no tienen por qué ir encerradas únicamente entre llaves. Puede elegir otro separador, incluso en tiempo de ejecución. Esto se hace mediante {syntax…}, donde el parámetro puede ser:

  • doble: {{...}}
  • off: desactiva completamente las etiquetas Latte

Utilizando la notación n:attribute podemos desactivar Latte sólo para un bloque JavaScript:

<script n:syntax="off">
	var obj = {var: 123}; // this isn't a tag any more
</script>

Latte se puede utilizar muy cómodamente dentro de JavaScript, sólo hay que evitar construcciones como en este ejemplo, donde la letra sigue inmediatamente a {, ver Latte dentro de JavaScript o CSS.

Si desactiva Latte con {syntax off} (es decir, la etiqueta, no el atributo n:attribute), ignorará estrictamente todas las etiquetas hasta {/syntax}.

{trace}

Lanza una excepción Latte\RuntimeException, cuya traza de pila sigue el espíritu de las plantillas. Así, en lugar de llamar a funciones y métodos, se trata de llamar a bloques e insertar plantillas. Si utiliza una herramienta para mostrar claramente las excepciones lanzadas, como Tracy, verá claramente la pila de llamadas, incluidos todos los argumentos pasados.

Ayudantes de etiquetas HTML

n:clase

Gracias a n:class, es muy fácil generar el atributo HTML class exactamente como lo necesita.

Ejemplo: Necesito que el elemento activo tenga la clase active:

{foreach $items as $item}
	<a n:class="$item->isActive() ? active">...</a>
{/foreach}

Y además necesito que el primer elemento tenga las clases first y main:

{foreach $items as $item}
	<a n:class="$item->isActive() ? active, $iterator->first ? 'first main'">...</a>
{/foreach}

Y que todos los elementos tengan la clase list-item:

{foreach $items as $item}
	<a n:class="$item->isActive() ? active, $iterator->first ? 'first main', list-item">...</a>
{/foreach}

Asombrosamente sencillo, ¿verdad?

n:attr

El atributo n:attr puede generar atributos HTML arbitrarios con la misma elegancia que n:class.

{foreach $data as $item}
	<input type="checkbox" n:attr="value: $item->getValue(), checked: $item->isActive()">
{/foreach}

En función de los valores devueltos, muestra, por ejemplo

<input type="checkbox">

<input type="checkbox" value="Hello">

<input type="checkbox" value="Hello" checked>

n:tag

El atributo n:tag puede cambiar dinámicamente el nombre de un elemento HTML.

<h1 n:tag="$heading" class="main">{$title}</h1>

Si $heading === null, la etiqueta <h1> se imprime sin cambios. De lo contrario, el nombre del elemento se cambia por el valor de la variable, por lo que para $heading === 'h3' escribe:

<h3 class="main">...</h3>

Como Latte es un sistema de plantillas seguro, comprueba que el nuevo nombre de la etiqueta sea válido y no contenga valores no deseados o maliciosos.

n:ifcontent

Evita que se imprima un elemento HTML vacío, es decir, un elemento que sólo contiene espacios en blanco.

<div>
	<div class="error" n:ifcontent>{$error}</div>
</div>

Dependiendo de los valores de la variable $error se imprimirá:

{* $error = '' *}
<div>
</div>

{* $error = 'Required' *}
<div>
	<div class="error">Required</div>
</div>

Traducción

Para que las etiquetas de traducción funcionen, necesitas configurar el traductor. También puede utilizar el translate para la traducción.

{_...}

Traduce los valores a otros idiomas.

<a href="basket">{_'Basket'}</a>
<span>{_$item}</span>

También se pueden pasar otros parámetros al traductor:

<a href="basket">{_'Basket', domain: order}</a>

{translate}

Překládá části šablony:

<h1>{translate}Order{/translate}</h1>

{translate domain: order}Lorem ipsum ...{/translate}

La etiqueta también puede escribirse como n:attribute, para traducir el interior del elemento:

<h1 n:translate>Order</h1>