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
En los presentadores, no es necesario especificar qué plantilla debe renderizarse; el framework determinará automáticamente la ruta, facilitándole la codificación.
Si utiliza una estructura de directorios donde cada presentador tiene su propio directorio, simplemente coloque la plantilla en
este directorio bajo el nombre de la acción (es decir, vista). Por ejemplo, para la acción default
, utilice la
plantilla default.latte
:
app/ └── UI/ └── Home/ ├── HomePresenter.php └── default.latte
Si utiliza una estructura en la que los presentadores están juntos en un directorio y las plantillas en una carpeta
templates
, guárdela en un archivo <Presenter>.<view>.latte
o en
<Presenter>/<view>.latte
:
app/ └── Presenters/ ├── HomePresenter.php └── templates/ ├── Home.default.latte ← 1st variant └── Home/ └── default.latte ← 2nd variant
El directorio templates
también puede colocarse un nivel más arriba, al mismo nivel que el directorio con las
clases de presentador.
Si no se encuentra la plantilla, el presentador responde con el error 404 – página no encontrada.
Puede cambiar la vista utilizando $this->setView('anotherView')
. También es posible especificar directamente
el archivo de plantilla con $this->template->setFile('/path/to/template.latte')
.
Los archivos en los que se buscan las plantillas pueden cambiarse anulando el método formatTemplateFiles(), que devuelve una matriz de posibles nombres de archivo.
Búsqueda de plantillas de diseño
Nette también busca automáticamente el archivo de diseño.
Si utiliza una estructura de directorios en la que cada presentador tiene su propio directorio, coloque la maqueta en la carpeta con el presentador, si es específica sólo para él, o en un nivel superior si es común a varios presentadores:
app/ └── UI/ ├── @layout.latte ← common layout └── Home/ ├── @layout.latte ← only for Home presenter ├── HomePresenter.php └── default.latte
Si utiliza una estructura en la que los presentadores están agrupados en un directorio y las plantillas se encuentran en una
carpeta templates
, la maquetación se esperará en los siguientes lugares:
app/ └── Presenters/ ├── HomePresenter.php └── templates/ ├── @layout.latte ← common layout ├── Home.@layout.latte ← only for Home, 1st variant └── Home/ └── @layout.latte ← only for Home, 2nd variant
Si el presentador está en un módulo, también buscará más arriba en el árbol de directorios según el anidamiento del módulo.
El nombre de la presentación puede cambiarse utilizando $this->setLayout('layoutAdmin')
y entonces se
esperará en el archivo @layoutAdmin.latte
. También puede especificar directamente el archivo de plantilla de
presentación utilizando $this->setLayout('/path/to/template.latte')
.
El uso de $this->setLayout(false)
o de la etiqueta {layout none}
dentro de la plantilla desactiva
la búsqueda de diseños.
Los archivos en los que se buscan las plantillas de diseño pueden modificarse modificando el método formatLayoutTemplateFiles(), que devuelve una matriz de posibles nombres 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\UI\Article\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 ejemplohttp://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étodoflashMessage()
Si utilizas una clase de plantilla personalizada, estas variables se pasan si creas una propiedad para ellas.
Creación de enlaces
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\UI\Accessory;
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\UI\Accessory\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(@Nette\Localization\Translator)
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.