Prácticas para desarrolladores
Instalación
La mejor manera de instalar Latte es utilizar un Compositor:
composer require latte/latte
Versiones PHP soportadas (se aplica a las últimas versiones del parche Latte):
versión | compatible con PHP |
---|---|
Latte 3.0 | PHP 8.0 – 8.2 |
Cómo renderizar una plantilla
¿Cómo renderizar una plantilla? Utilice este sencillo código:
$latte = new Latte\Engine;
// directorio caché
$latte->setTempDirectory('/path/to/tempdir');
$params = [ /* template variables */ ];
// o $params = new TemplateParameters(/* ... */);
// renderizar a la salida
$latte->render('template.latte', $params);
// o renderizar a variable
$output = $latte->renderToString('template.latte', $params);
Los parámetros pueden ser matrices o incluso mejor objeto, que proporcionará la comprobación de tipo y sugerencia en el editor.
También puedes encontrar ejemplos de uso en el repositorio Latte examples.
Rendimiento y caché
Las plantillas Latte son extremadamente rápidas, porque Latte las compila directamente en código PHP y las almacena en caché en disco. Por lo tanto, no tienen sobrecarga adicional en comparación con las plantillas escritas en PHP puro.
La caché se regenera automáticamente cada vez que se modifica el fichero fuente. Así que puede editar cómodamente sus plantillas Latte durante el desarrollo y ver los cambios inmediatamente en el navegador. Puede desactivar esta característica en un entorno de producción y ahorrar un poco de rendimiento:
$latte->setAutoRefresh(false);
Cuando se despliega en un servidor de producción, la generación inicial de caché, especialmente para aplicaciones grandes, puede tardar un poco. Latte tiene incorporada una prevención contra la estampida de caché. Esta es una situación en la que el servidor recibe un gran número de peticiones concurrentes y debido a que la caché de Latte aún no existe, todas ellas la generarían al mismo tiempo. Lo que dispara la CPU. Latte es inteligente, y cuando hay múltiples peticiones concurrentes, sólo el primer hilo genera la caché, los demás esperan y luego la usan.
Parámetros como clase
Mejor que pasar variables a la plantilla como arrays es crear una clase. Obtienes notación de tipo seguro, buena sugerencia en IDE y una forma de registrar 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,
));
Deshabilitando Auto-Escaping de Variable
Si la variable contiene una cadena HTML, puede marcarla para que Latte no la escape automáticamente (y por tanto doblemente).
Esto evita la necesidad de especificar |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 tampoco escapa todos los objetos que implementan la interfaz Latte\HtmlStringable
. Así que puedes crear tu
propia clase cuyo método __toString()
devuelva código HTML que no será escapado 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 proporcionar escapado de parámetros, ¡de lo
contrario puede producirse una vulnerabilidad XSS!
Cómo extender Latte con filtros, etiquetas, etc.
¿Cómo añadir un filtro personalizado, función, etiqueta, etc. a Latte? Descúbrelo en el capítulo Extendiendo Latte. Si quieres reutilizar tus cambios en diferentes proyectos o si quieres compartirlos con otros, entonces debes crear una extensión.
Cualquier código en la plantilla {php ...}
Dentro de la etiqueta {do}
por lo que no puede, por ejemplo,
insertar construcciones como if ... else
o sentencias terminadas en punto y coma.
Sin embargo, puede registrar la extensión RawPhpExtension
, que añade la etiqueta {php ...}
. Puede
utilizarla para insertar cualquier código PHP. No está sujeta a ninguna regla 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 plantillas en código PHP. Por supuesto, se asegura de que el código generado es sintácticamente válido. Sin embargo, cuando se usan extensiones de terceros o RawPhpExtension, Latte no puede garantizar la corrección del fichero generado. Además, en PHP, puede escribir código que sea sintácticamente correcto pero que esté prohibido (por ejemplo, asignar un valor a la variable $this) y cause un Error de Compilación PHP. Si escribe una operación de este tipo en una plantilla, también se incluirá en el código PHP generado. Dado que existen más de doscientas operaciones prohibidas diferentes en PHP, Latte no pretende detectarlas. El propio PHP las marcará al renderizar, lo que normalmente no es un problema.
Sin embargo, hay situaciones en las que se desea saber durante la compilación de la plantilla que no contiene errores de compilación de PHP. Especialmente cuando las plantillas pueden ser editadas por usuarios, o usted usa Sandbox. En tal caso, haga que las plantillas se comprueben durante la compilación. Puede activar esta funcionalidad usando el método Engine::enablePhpLint(). Ya que necesita llamar al binario PHP para la comprobación, pase su ruta como parámetro:
$latte = new Latte\Engine;
$latte->enablePhpLinter('/path/to/php');
try {
$latte->compile('home.latte');
} catch (Latte\CompileException $e) {
// atrapa errores Latte y también Compile Error en PHP
echo 'Error: ' . $e->getMessage();
}
Localidad
Latte le permite establecer la configuración regional, que afecta al formato de los números, las fechas y la ordenación. Se
establece usando el método setLocale()
. El identificador de configuración regional sigue el estándar de etiquetas
de idioma IETF, que utiliza la extensión PHP intl
. Consiste en un código de idioma y posiblemente un código de
país, por ejemplo, en_US
para inglés en los Estados Unidos, de_DE
para alemán en Alemania, etc.
$latte = new Latte\Engine;
$latte->setLocale('cs');
La configuración regional afecta a los filtros localDate, sort, number y bytes.
Requiere la extensión PHP intl
. La configuración de Latte no afecta a la configuración regional
global de PHP.
Modo estricto
En el modo de análisis sintáctico estricto, Latte comprueba si faltan etiquetas HTML de cierre y también desactiva el uso de
la variable $this
. Para activarlo
$latte = new Latte\Engine;
$latte->setStrictParsing();
Para generar plantillas con la cabecera declare(strict_types=1)
, haga lo siguiente:
$latte = new Latte\Engine;
$latte->setStrictTypes();
Traducción en plantillas
Utilice la extensión TranslatorExtension
para añadir {_...}
, {translate}
y filtrar translate
a la plantilla. Se utilizan para traducir
valores o partes de la plantilla a otros idiomas. El parámetro es el método (PHP callable) que realiza la traducción:
class MyTranslator
{
public function __construct(private string $lang)
{}
public function translate(string $original): string
{
// crear $traducido 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 es llamado en tiempo de ejecución cuando la plantilla es renderizada. Sin embargo, Latte puede traducir todos los textos estáticos 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 archivo 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:
$extension = new Latte\Essential\TranslatorExtension(
$translator->translate(...),
$lang,
);
Por texto estático entendemos, por ejemplo, {_'hello'}
o {translate}hello{/translate}
. El texto no
estático, como {_$foo}
, seguirá traduciéndose en tiempo de ejecución.
La plantilla también puede pasar parámetros adicionales al traductor a través de {_$original, foo: bar}
o
{translate foo: bar}
, que recibe como matriz $params
:
public function translate(string $original, ...$params): string
{
// $params['foo'] === 'bar'
}
Depuración y Tracy
Latte intenta que el desarrollo sea lo más agradable posible. A efectos de depuración, existen tres etiquetas {dump}
, {debugbreak}
y {trace}
.
Obtendrás la mayor comodidad si instalas la gran herramienta de depuración Tracy y activas el plugin Latte:
// activa Tracy
Tracy\Debugger::enable();
$latte = new Latte\Engine;
// activa la extensión de Tracy
$latte->addExtension(new Latte\Bridges\Tracy\TracyExtension);
Ahora verás todos los errores en una pulcra pantalla roja, incluidos los errores en plantillas con resaltado de filas y columnas (vídeo). Al mismo tiempo, en la esquina inferior derecha, en la llamada Tracy Bar, aparece una pestaña para Latte, donde puedes ver claramente todas las plantillas renderizadas y sus relaciones (incluyendo la posibilidad de hacer clic en la plantilla o en el código compilado), así como las variables:
Dado que Latte compila las plantillas en código PHP legible, puede recorrerlas cómodamente en su IDE.
Linter: Validando la Sintaxis de la Plantilla
La herramienta Linter le ayudará a revisar todas las plantillas y comprobar si hay errores de sintaxis. Se ejecuta desde la consola:
vendor/bin/latte-lint <path>
Utilice el parámetro --strict
para activar el modo estricto.
Si utiliza etiquetas personalizadas, cree también su Linter personalizado, por ejemplo 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 a partir de cadenas en lugar de archivos, quizás con fines de prueba? StringLoader le ayudará:
$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 las excepciones esperadas. Las excepciones que se produzcan dentro de {try}
y en el sandbox se le pasan.
$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 diseños
Mediante la etiqueta {layout}
la plantilla determina su plantilla padre. También es posible que el diseño se busque automáticamente, lo que simplificará la
escritura de plantillas, ya que no tendrán que incluir la etiqueta {layout}
.
Esto se consigue de la siguiente manera:
$finder = function (Latte\Runtime\Template $template) {
if (!$template->getReferenceType()) {
// devuelve la ruta al archivo de plantilla padre
return 'automatic.layout.latte';
}
};
$latte = new Latte\Engine;
$latte->addProvider('coreParentFinder', $finder);
Si la plantilla no debe tener diseño, lo indicará con la etiqueta {layout none}
.