Plantillas

Nette utiliza el sistema de plantillas Latte. Se utiliza Latte porque es el sistema de plantillas más seguro para PHP, y al mismo tiempo el sistema más intuitivo. Usted no tiene que aprender mucho nuevo, sólo necesita saber PHP y algunas etiquetas Latte.

Lo habitual es que la página se complete a partir de la plantilla layout + la plantilla action. Este es el aspecto que podría tener una plantilla de maquetación, fíjate en los bloques {block} y la etiqueta {include}:

<!DOCTYPE html>
<html>
<head>
	<title>{block title}My App{/block}</title>
</head>
<body>
	<header>...</header>
	{include content}
	<footer>...</footer>
</body>
</html>

Y esta podría ser la plantilla de acción:

{block title}Homepage{/block}

{block content}
<h1>Homepage</h1>
...
{/block}

Define el bloque content, que se inserta en lugar de {include content} en el diseño, y también redefine el bloque title, que sobrescribe {block title} en el diseño. Intenta imaginar el resultado.

Búsqueda de plantillas

La ruta a las plantillas se deduce según una lógica simple. Se intenta ver si uno de estos archivos de plantilla existe en relación con el directorio donde se encuentra la clase de presentador, donde <Presenter> es el nombre del presentador actual y <view> es el nombre de la acción actual:

  • templates/<Presenter>/<view>.latte
  • templates/<Presenter>.<view>.latte

Si no se encuentra la plantilla, se intentará buscar en el directorio templates un nivel más arriba, es decir, al mismo nivel que el directorio con la clase presentadora.

Si la plantilla tampoco se encuentra allí, la respuesta es un error 404.

También puede cambiar la vista utilizando $this->setView('otherView'). O, en lugar de buscar, especifique directamente el nombre del archivo de plantilla utilizando $this->template->setFile('/path/to/template.latte').

Puede cambiar las rutas donde se buscan las plantillas anulando el método formatTemplateFiles, que devuelve una matriz de posibles rutas de archivo.

El diseño se espera en los siguientes archivos:

  • templates/<Presenter>/@<layout>.latte
  • templates/<Presenter>.@<layout>.latte
  • templates/@<layout>.latte diseño común a varios presentadores

<Presenter> es el nombre del presentador actual y <layout> es el nombre de la maquetación, que por defecto es 'layout'. El nombre puede cambiarse con $this->setLayout('otherLayout'), de modo que se intentarán los archivos @otherLayout.latte.

También puede especificar directamente el nombre de archivo de la plantilla de maquetación con $this->setLayout('/path/to/template.latte'). El uso de $this->setLayout(false) desactivará la búsqueda de diseños.

Puede cambiar las rutas donde se buscan las plantillas anulando el método formatLayoutTemplateFiles, que devuelve una matriz de posibles rutas de archivo.

Variables en la plantilla

Las variables se pasan a la plantilla escribiéndolas en $this->template y luego están disponibles en la plantilla como variables locales:

$this->template->article = $this->articles->getById($id);

De esta forma podemos pasar fácilmente cualquier variable a las plantillas. Sin embargo, cuando desarrollamos aplicaciones robustas, a menudo es más útil limitarnos. Por ejemplo, definiendo explícitamente una lista de variables que la plantilla espera y sus tipos. Esto permitirá a PHP comprobar los tipos, al IDE autocompletar correctamente, y al análisis estático detectar errores.

¿Y cómo definimos tal enumeración? Simplemente en forma de una clase y sus propiedades. La nombramos de forma similar a presenter, pero con Template al final:

/**
 * @property-read ArticleTemplate $template
 */
class ArticlePresenter extends Nette\Application\UI\Presenter
{
}

class ArticleTemplate extends Nette\Bridges\ApplicationLatte\Template
{
	public Model\Article $article;
	public Nette\Security\User $user;

	// y otras variables
}

El objeto $this->template en el presentador será ahora una instancia de la clase ArticleTemplate. Así que PHP comprobará los tipos declarados cuando se escriban. Y a partir de PHP 8.2 también advertirá sobre la escritura en una variable no existente, en versiones anteriores se puede lograr lo mismo usando el rasgo Nette\SmartObject.

La anotación @property-read es para IDE y análisis estático, hará que funcione el autocompletado, vea PhpStorm y el completado de código para $this->template.

Puedes permitirte el lujo de susurrar en las plantillas también, simplemente instala el plugin Latte en PhpStorm y especifica el nombre de la clase al principio de la plantilla, ver el artículo “Latte: cómo escribir sistema:https://blog.nette.org/…ema-de-tipos”:

{templateType App\Presenters\ArticleTemplate}
...

Así es también como funcionan las plantillas en los componentes, sólo tienes que seguir la convención de nomenclatura y crear una clase de plantilla FifteenTemplate para el componente, por ejemplo FifteenControl.

Si necesitas crear un $template como una instancia de otra clase, utiliza el método createTemplate():

public function renderDefault(): void
{
	$template = $this->createTemplate(SpecialTemplate::class);
	$template->foo = 123;
	// ...
	$this->sendTemplate($template);
}

Variables por defecto

Los presentadores y componentes pasan varias variables útiles a las plantillas de forma automática:

  • $basePath es una ruta URL absoluta al directorio raíz (por ejemplo /CD-collection)
  • $baseUrl es una URL absoluta al directorio raíz (por ejemplo http://localhost/CD-collection)
  • $user es un objeto que representa al usuario
  • $presenter es el presentador actual
  • $control es el componente o presentador actual
  • $flashes lista de mensajes enviados por el método flashMessage()

Si utilizas una clase de plantilla personalizada, estas variables se pasan si creas una propiedad para ellas.

En la plantilla creamos enlaces a otros presentadores y acciones de la siguiente manera:

<a n:href="Product:show">detail</a>

Atributo n:href es muy útil para etiquetas HTML <a>. Si queremos imprimir el enlace en otro lugar, por ejemplo en el texto, utilizamos {link}:

URL is: {link Home:default}

Para más información, véase Creación de enlaces.

Filtros personalizados, etiquetas, etc.

El sistema de plantillas Latte puede ampliarse con filtros personalizados, funciones, etiquetas, etc. Esto puede hacerse directamente en el método render<View> o en el método beforeRender():

public function beforeRender(): void
{
	// adding a filter
	$this->template->addFilter('foo', /* ... */);

	// or configure the Latte\Engine object directly
	$latte = $this->template->getLatte();
	$latte->addFilterLoader(/* ... */);
}

La versión 3 de Latte ofrece una forma más avanzada creando una extensión para cada proyecto web. He aquí un ejemplo aproximado de una clase de este tipo:

namespace App\Templating;

final class LatteExtension extends Latte\Extension
{
	public function __construct(
		private App\Model\Facade $facade,
		private Nette\Security\User $user,
		// ...
	) {
	}

	public function getFilters(): array
	{
		return [
			'timeAgoInWords' => $this->filterTimeAgoInWords(...),
			'money' => $this->filterMoney(...),
			// ...
		];
	}

	public function getFunctions(): array
	{
		return [
			'canEditArticle' =>
				fn($article) => $this->facade->canEditArticle($article, $this->user->getId()),
			// ...
		];
	}

	// ...
}

La registramos usando configuration:

latte:
	extensions:
		- App\Templating\LatteExtension

Traducir

Si estás programando una aplicación multilingüe, es probable que necesites mostrar parte del texto de la plantilla en diferentes idiomas. Para ello, Nette Framework define una interfaz de traducción Nette\Localization\Translator, que tiene un único método translate(). Éste acepta el mensaje $message, que normalmente es una cadena, y cualquier otro parámetro. La tarea consiste en devolver la cadena traducida. No existe una implementación por defecto en Nette, puede elegir según sus necesidades entre varias soluciones ya preparadas que puede encontrar en Componette. Su documentación le indica cómo configurar el traductor.

Las plantillas se pueden configurar con un traductor, que nos habrán pasado, utilizando el método setTranslator():

protected function beforeRender(): void
{
	// ...
	$this->template->setTranslator($translator);
}

Alternativamente, el traductor se puede establecer utilizando la configuración:

latte:
	extensions:
		- Latte\Essential\TranslatorExtension

El traductor puede utilizarse, por ejemplo, como un filtro |translate, con parámetros adicionales pasados al método translate() (véase foo, bar):

<a href="basket">{='Basket'|translate}</a>
<span>{$item|translate}</span>
<span>{$item|translate, foo, bar}</span>

O como una etiqueta de subrayado:

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

Para la traducción de secciones de plantillas, existe una etiqueta emparejada {translate} (desde Latte 2.11, antes se utilizaba la etiqueta {_} ):

<a href="order">{translate}Order{/translate}</a>
<a href="order">{translate foo, bar}Order{/translate}</a>

Translator se llama por defecto en tiempo de ejecución al renderizar la plantilla. La versión 3 de Latte, sin embargo, puede traducir todo el texto estático durante la compilación de la plantilla. Esto ahorra rendimiento porque cada cadena se traduce sólo una vez y la traducción resultante se escribe en el formulario compilado. Esto crea múltiples versiones compiladas de la plantilla en el directorio caché, una para cada idioma. Para ello, sólo tiene que especificar el idioma como segundo parámetro:

protected function beforeRender(): void
{
	// ...
	$this->template->setTranslator($translator, $lang);
}

Por texto estático entendemos, por ejemplo, {_'hello'} o {translate}hello{/translate}. El texto no estático, como {_$foo}, seguirá compilándose sobre la marcha.

versión: 4.0