Prácticas de desarrollo
Instalación
La mejor manera de instalar Latte es usando Composer:
composer require latte/latte
Versiones de PHP soportadas (se aplica a las últimas versiones menores de Latte):
versión | compatible con PHP |
---|---|
Latte 3.0 | PHP 8.0 – 8.2 |
Cómo renderizar una plantilla
¿Cómo renderizar una plantilla? Basta con este simple código:
$latte = new Latte\Engine;
// directorio para la caché
$latte->setTempDirectory('/path/to/tempdir');
$params = [ /* variables de plantilla */ ];
// o $params = new TemplateParameters(/* ... */);
// renderizar en la salida
$latte->render('template.latte', $params);
// renderizar en una variable
$output = $latte->renderToString('template.latte', $params);
Los parámetros pueden ser arrays o, mejor aún, un objeto, que asegurará la comprobación de tipos y el autocompletado en los editores.
También puede encontrar ejemplos de uso en el repositorio Latte examples.
Rendimiento y caché
Las plantillas en Latte son extremadamente rápidas, ya que Latte las compila directamente a código PHP y las almacena en caché en el disco. Por lo tanto, no tienen ninguna sobrecarga adicional en comparación con las plantillas escritas en PHP puro.
La caché se regenera automáticamente cada vez que cambia el archivo fuente. Durante el desarrollo, puede editar cómodamente las plantillas en Latte y ver los cambios inmediatamente en el navegador. Puede desactivar esta función en el entorno de producción para ahorrar un poco de rendimiento:
$latte->setAutoRefresh(false);
Al desplegar en un servidor de producción, la generación inicial de la caché, especialmente en aplicaciones más grandes, puede tardar comprensiblemente un momento. Latte tiene una prevención incorporada contra la estampida de caché. Esta es una situación en la que un gran número de solicitudes concurrentes que inician Latte coinciden, y como la caché aún no existe, todas comenzarían a generarla simultáneamente. Lo que sobrecargaría desproporcionadamente el servidor. Latte es inteligente y, en caso de múltiples solicitudes concurrentes, solo el primer hilo genera la caché, los demás esperan y luego la utilizan.
Parámetros como clase
Mejor que pasar variables a la plantilla como un array es crear una clase. Obtendrá así una escritura segura de tipos, un agradable autocompletado en IDE y una forma de registro de filtros y funciones.
class MailTemplateParameters
{
public function __construct(
public string $lang,
public Address $address,
public string $subject,
public array $items,
public ?float $price = null,
) {}
}
$latte->render('mail.latte', new MailTemplateParameters(
lang: $this->lang,
subject: $title,
price: $this->getPrice(),
items: [],
address: $userAddress,
));
Desactivar el auto-escapado de variables
Si una variable contiene una cadena en HTML, puede marcarla para que Latte no la escape automáticamente (y por lo tanto
doblemente). Evitará así la necesidad de indicar |noescape
en la plantilla.
La forma más sencilla es envolver la cadena en un objeto Latte\Runtime\Html
:
$params = [
'articleBody' => new Latte\Runtime\Html($article->htmlBody),
];
Latte además no escapa todos los objetos que implementan la interfaz Latte\HtmlStringable
. Puede así crear su
propia clase cuyo método __toString()
devuelva código HTML que no se escapará automáticamente:
class Emphasis extends Latte\HtmlStringable
{
public function __construct(
private string $str,
) {
}
public function __toString(): string
{
return '<em>' . htmlspecialchars($this->str) . '</em>';
}
}
$params = [
'foo' => new Emphasis('hello'),
];
El método __toString
debe devolver HTML correcto y asegurar el escapado de los parámetros, de lo
contrario puede producirse una vulnerabilidad XSS.
Cómo extender Latte con filtros, etiquetas, etc.
¿Cómo añadir a Latte su propio filtro, función, etiqueta, etc.? De eso trata el capítulo Extender Latte. Si desea reutilizar sus modificaciones en diferentes proyectos o compartirlas con otros, debería crear una extensión.
Código arbitrario en la plantilla {php ...}
Dentro de la etiqueta {do}
solo se pueden escribir
expresiones PHP, no puede, por ejemplo, insertar construcciones como if ... else
o sentencias terminadas con punto
y coma.
Sin embargo, puede registrar la extensión RawPhpExtension
, que añade la etiqueta {php ...}
. Con
ella se puede insertar cualquier código PHP. No se le aplican ninguna de las reglas del modo sandbox, por lo que su uso es
responsabilidad del autor de la plantilla.
$latte->addExtension(new Latte\Essential\RawPhpExtension);
Comprobación del código generado
Latte compila las plantillas en código PHP. Por supuesto, se asegura de que el código generado sea sintácticamente válido.
Sin embargo, al usar extensiones de terceros o RawPhpExtension
, Latte no puede garantizar la corrección del archivo
generado. También es posible escribir en PHP código que, aunque sintácticamente correcto, está prohibido (por ejemplo, asignar
un valor a la variable $this
) y causa un PHP Compile Error. Si escribe tal operación en la plantilla, también
llegará al código PHP generado. Dado que en PHP existen unas doscientas operaciones prohibidas diferentes, Latte no tiene la
ambición de detectarlas. El propio PHP las señalará al renderizar, lo que normalmente no importa.
Sin embargo, hay situaciones en las que desea saber ya en el momento de la compilación de la plantilla que no contiene ningún
PHP Compile Error. Especialmente si las plantillas pueden ser editadas por los usuarios, o si utiliza Sandbox. En tal caso, haga que las plantillas se comprueben ya en el momento de la
compilación. Esta funcionalidad se activa con el método Engine::enablePhpLint()
. Dado que para la comprobación
necesita llamar al binario de PHP, pase la ruta a él como parámetro:
$latte = new Latte\Engine;
$latte->enablePhpLinter('/path/to/php');
try {
$latte->compile('home.latte');
} catch (Latte\CompileException $e) {
// captura errores en Latte y también Compile Error en PHP
echo 'Error: ' . $e->getMessage();
}
Configuración regional
Latte permite establecer la configuración regional, que afecta al formato de números, fechas y ordenación. Se establece
mediante el método setLocale()
. El identificador de entorno sigue el estándar IETF language tag, que utiliza la
extensión PHP intl
. Se compone del código de idioma y, opcionalmente, del código de país, p. ej.,
en_US
para inglés en Estados Unidos, de_DE
para alemán en Alemania, etc.
$latte = new Latte\Engine;
$latte->setLocale('es_ES');
La configuración del entorno afecta a los filtros localDate, sort, number y bytes.
Requiere la extensión PHP intl
. La configuración en Latte no afecta a la configuración global de
locale en PHP.
Modo estricto
En el modo estricto de análisis sintáctico, Latte comprueba si faltan etiquetas HTML de cierre y también prohíbe el uso de
la variable $this
. Se activa así:
$latte = new Latte\Engine;
$latte->setStrictParsing();
La generación de plantillas con la cabecera declare(strict_types=1)
se activa así:
$latte = new Latte\Engine;
$latte->setStrictTypes();
Traducción en plantillas
Usando la extensión TranslatorExtension
, añade a la plantilla las etiquetas {_...}
, {translate}
y el filtro translate
. Sirven para traducir valores o partes de la
plantilla a otros idiomas. Como parámetro, especificamos el método (PHP callable) que realiza la traducción:
class MyTranslator
{
public function __construct(private string $lang)
{}
public function translate(string $original): string
{
// creamos $translated a partir de $original según $this->lang
return $translated;
}
}
$translator = new MyTranslator($lang);
$extension = new Latte\Essential\TranslatorExtension(
$translator->translate(...), // [$translator, 'translate'] en PHP 8.0
);
$latte->addExtension($extension);
El traductor se llama en tiempo de ejecución al renderizar la plantilla. Sin embargo, Latte puede traducir todos los textos estáticos ya durante la compilación de la plantilla. Esto ahorra rendimiento, ya que cada cadena se traduce solo una vez y la traducción resultante se escribe en la forma compilada. En el directorio de caché se crean así múltiples versiones compiladas de la plantilla, una para cada idioma. Para ello, basta con indicar el idioma como segundo parámetro:
$extension = new Latte\Essential\TranslatorExtension(
$translator->translate(...),
$lang,
);
Texto estático significa, por ejemplo, {_'hola'}
o {translate}hola{/translate}
. Los textos no
estáticos, como {_$foo}
, seguirán traduciéndose en tiempo de ejecución.
También se pueden pasar parámetros adicionales al traductor desde la plantilla usando {_$original, foo: bar}
o
{translate foo: bar}
, que obtendrá como array $params
en el segundo (y siguientes) argumento(s) de la
función translate
:
public function translate(string $original, ...$params): string
{
// $params['foo'] === 'bar'
}
Depuración y Tracy
Latte intenta facilitarle el desarrollo tanto como sea posible. Directamente para fines de depuración existen tres etiquetas
{dump}
, {debugbreak}
y {trace}
.
Obtendrá la mayor comodidad si además instala la excelente herramienta de depuración Tracy y activa el complemento para Latte:
// activa Tracy
Tracy\Debugger::enable();
$latte = new Latte\Engine;
// activa la extensión para Tracy
$latte->addExtension(new Latte\Bridges\Tracy\TracyExtension);
Ahora todos los errores se mostrarán en una pantalla roja clara, incluidos los errores en las plantillas con resaltado de línea y columna (vídeo). Al mismo tiempo, en la esquina inferior derecha, en la llamada Tracy Bar, aparecerá una pestaña para Latte, donde se ven claramente todas las plantillas renderizadas y sus relaciones mutuas (incluida la posibilidad de hacer clic para ir a la plantilla o al código compilado) y también las variables:

Dado que Latte compila las plantillas en código PHP claro, puede recorrerlas cómodamente en su IDE.
Linter: validación de la sintaxis de las plantillas
La herramienta Linter le ayuda a recorrer todas las plantillas y comprobar si contienen errores de sintaxis. Se ejecuta desde la consola:
vendor/bin/latte-lint <ruta>
Con el parámetro --strict
activa el modo estricto.
Si utiliza etiquetas personalizadas, cree también su propia versión de Linter, p. ej., custom-latte-lint
:
#!/usr/bin/env php
<?php
// introduzca la ruta real al archivo autoload.php
require __DIR__ . '/vendor/autoload.php';
$path = $argv[1] ?? '.';
$linter = new Latte\Tools\Linter;
$latte = $linter->getEngine();
// añada aquí sus extensiones individuales
$latte->addExtension(/* ... */);
$ok = $linter->scanDirectory($path);
exit($ok ? 0 : 1);
Alternativamente, puede pasar su propio objeto Latte\Engine
al Linter:
$latte = new Latte\Engine;
// aquí configuramos el objeto $latte
$linter = new Latte\Tools\Linter(engine: $latte);
Carga de plantillas desde una cadena
¿Necesita cargar plantillas desde cadenas en lugar de archivos, por ejemplo, para fines de prueba? Le ayudará StringLoader:
$latte->setLoader(new Latte\Loaders\StringLoader([
'main.file' => '{include other.file}',
'other.file' => '{if true} {$var} {/if}',
]));
$latte->render('main.file', $params);
Manejador de excepciones
Puede definir su propio manejador para excepciones esperadas. Se le pasarán las excepciones que surjan dentro de {try}
y en el sandbox.
$loggingHandler = function (Throwable $e, Latte\Runtime\Template $template) use ($logger) {
$logger->log($e);
};
$latte = new Latte\Engine;
$latte->setExceptionHandler($loggingHandler);
Búsqueda automática de layout
Usando la etiqueta {layout}
,
la plantilla determina su plantilla padre. También es posible dejar que el layout se busque automáticamente, lo que
simplificará la escritura de plantillas, ya que no será necesario indicar la etiqueta {layout}
en ellas.
Se logra de la siguiente manera:
$finder = function (Latte\Runtime\Template $template) {
if (!$template->getReferenceType()) {
// devuelve la ruta al archivo de layout
return 'automatic.layout.latte';
}
};
$latte = new Latte\Engine;
$latte->addProvider('coreParentFinder', $finder);
Si la plantilla no debe tener layout, lo indica con la etiqueta {layout none}
.