Plugins Smarty de generación de HTML
1Introducción
Al crear plantillas Smarty, puedes usar estructuras de control (condiciones {if}, bucles {foreach}, etc.), etiquetas personalizadas ({cycle}, {mailto}, {math}, etc.), y modificadores (default, date_format, escape, replace, etc.) proporcionados por Smarty.
Para facilitar el desarrollo, puedes crear tus propias etiquetas y modificadores personalizados. Aquí tienes un ejemplo de cada uno.
2Crear un modificador personalizado
Vamos a crear un modificador que traduce una cadena de texto a otro idioma.
(consulta la documentación de Smarty sobre cómo escribir modificadores)
Por ejemplo, escribiendo esto en una plantilla Smarty:
{* traducción directa de una cadena de texto *}
{"Título del artículo"|translate:'en'}
{* traducción del contenido de variables *}
{$product1.type|translate:'en'}
{$product2.type|translate:'en'}
Podrías obtener el siguiente resultado:
Article title
Computer
Screen
Para desarrollar este modificador, usaremos la fuente de datos que se conecta a la API de Deepl, que vimos en el
tutorial anterior. El código del modificador presupone la presencia de
esta fuente de datos en el archivo de configuración, bajo el nombre transl.
Aquí está el código del modificador, que se guardará en el archivo lib/smarty-plugins/modifier.translate.php:
<?php
/**
* Modificador Smarty para traducir textos.
* @param string $text Cadena de texto a traducir.
* @param string $lang Idioma al que se traducirá el texto.
* @return string El texto traducido.
*/
function smarty_modifier_translate(string $text, string $lang) : string {
// obtención de la fuente de datos
global $temma;
$datasource = $temma->getLoader()->dataSources->transl ?? null;
if (!$datasource)
return ($text);
// llama a la API de Deepl para traducir la cadena
try {
$result = $datasource->translate($text, $lang);
} catch (\Exception $e) {
$result = null;
}
return ($result ?: $text);
}
- Línea 9: Definición de la función smarty_modifier_translate().
- Línea 11: Definición de la variable global $temma, que contiene el objeto principal del framework.
- Línea 12: Uso de la variable global para recuperar el componente de inyección de dependencias (con el método getLoader()), luego recuperar el array de fuentes de datos, y a partir de ahí recuperar la fuente de datos conectada a la API de Deepl.
- Líneas 13 y 14: Si la fuente de datos no está definida, se devuelve el texto original (sin traducir).
- Líneas 17 a 21: Llamada a la fuente de datos para traducir el texto.
- Línea 23: Devuelve el texto traducido. Si está vacío, se devuelve el texto original.
3Crear una etiqueta personalizada
Imaginemos que quieres crear una etiqueta Smarty para facilitar la creación de títulos.
(consulta la documentación de Smarty sobre cómo escribir etiquetas personalizadas).
Por ejemplo, escribiendo esto en tu plantilla:
{title text="Primer título" level="1"}
{title text="Primer subtítulo" level="2"}
<p>Bla bla</p>
{title text="Segundo subtítulo" level="2"}
<p>Bla bla</p>
{title text="Segundo título" level="1"}
{title text="Primer subtítulo" level="2"}
<p>Bla bla</p>
{title text="Segundo subtítulo" level="2"}
<p>Bla bla</p>
Obtendrías el siguiente código HTML:
<h1 id="1-primer-titulo">1 Primer título</h1>
<h2 id="1-1-primer-subtitulo">1.1 Primer subtítulo</h2>
<p>Bla bla</p>
<h2 id="1-2-segundo-subtitulo">1.2 Segundo subtítulo</h2>
<p>Bla bla</p>
<h1 id="2-segundo-titulo">2 Segundo título</h1>
<h2 id="2-1-primer-subtitulo">2.1 Primer subtítulo</h2>
<p>Bla bla</p>
<h2 id="2-2-segundo-subtitulo">2.2 Segundo subtítulo</h2>
<p>Bla bla</p>
Aquí está el código de una etiqueta personalizada como esta, que se guardará en el archivo lib/smarty-plugins/function.title.php:
<?php
/**
* Etiqueta Smarty usada para insertar títulos HTML.
* @param array $params Array asociativo con los parámetros proporcionados a la etiqueta.
* @param \Smarty\Template $template Objeto que representa la plantilla procesada.
* @return string El código HTML generado.
*/
function smarty_tag_title($params, $template) {
// inicializa la variable estática $levelsCount,
// que contiene la profundidad de cada nivel de título
static $levelsCount = [0];
// recuperación de los parámetros
$text = trim($params['text'] ?? null);
$level = intval($params['level'] ?? 1) ?: 1;
// verificación
if (!$text)
return ('');
// gestión de la variable estática
$levelsCount = array_slice($levelsCount, 0, $level);
$levelsCount[$level - 1] ??= 0;
$levelsCount[$level - 1]++;
// preparación del resultado
$title = implode('.', $levelsCount) . ' ' . $text;
$id = \Temma\Utils\Text::urlize($title);
return sprintf('<h%d id="%s">%s</h%d>', $level, $id, $title, $level);
}
- Línea 9: Declaración de la función smarty_tag_title(). Recibe dos parámetros, un array asociativo con los parámetros definidos en la plantilla, y un objeto que representa la plantilla en la que se usó la etiqueta (no vamos a usar este objeto).
- Línea 12: Definición de una variable estática inicializada con un array que contiene un entero igual a cero. El hecho de que sea una variable estática significa que conservará su valor entre cada llamada a la función. Esta variable contiene la profundidad de cada nivel de título, es decir, el número de títulos conocidos para cada nivel de título actual.
- Líneas 15 y 16: Recupera los parámetros proporcionados a la etiqueta en la plantilla. Se gestionan los valores ausentes o incorrectos.
- Líneas 19 y 20: Gestión del texto vacío.
- Línea 23: El array $levelsCount se reduce si es necesario, cuando el nivel de título pasado como parámetro es inferior al anterior.
- Líneas 24 y 25: En el array $levelsCount, la entrada correspondiente al nivel de título pasado como parámetro se incrementa (después de inicializarse en cero si es necesario).
- Líneas 28 y 29: Definición del título que se insertará en el código HTML, y del identificador asociado. Para generar el identificador, se aplica la función urlize() al título.
- Línea 31: Devuelve la cadena HTML formada por la etiqueta <Hn>, con el identificador como atributo y el título como contenido.
4Crear una etiqueta de bloque personalizada
Las etiquetas de bloque son estructuras de control que tienen un elemento de apertura ({tag_name}) y un elemento
de cierre ({/tag_name}), y que pueden actuar sobre el contenido colocado entre estos dos elementos.
(consulta la documentación de Smarty sobre cómo escribir etiquetas de bloque personalizadas)
Para ilustrar cómo funciona esto, vamos a escribir una etiqueta de bloque equivalente a la etiqueta {title} vista anteriormente. Verás las diferencias, tanto en el código Smarty como en la implementación PHP.
Por ejemplo, si escribes lo siguiente en tu plantilla:
{title level="1"}Primer título{/title}
{title level="2"}Primer subtítulo{/title}
<p>Bla bla</p>
{title level="2"}Segundo subtítulo{/title}
<p>Bla bla</p>
{title level="1"}Segundo título{/title}
{title level="2"}Primer subtítulo{/title}
<p>Bla bla</p>
{title level="2"}Segundo subtítulo{/title}
<p>Bla bla</p>
Obtendrías el siguiente código HTML:
<h1 id="1-primer-titulo">1 Primer título</h1>
<h2 id="1-1-primer-subtitulo">1.1 Primer subtítulo</h2>
<p>Bla bla</p>
<h2 id="1-2-segundo-subtitulo">1.2 Segundo subtítulo</h2>
<p>Bla bla</p>
<h1 id="2-segundo-titulo">2 Segundo título</h1>
<h2 id="2-1-primer-subtitulo">2.1 Primer subtítulo</h2>
<p>Bla bla</p>
<h2 id="2-2-segundo-subtitulo">2.2 Segundo subtítulo</h2>
<p>Bla bla</p>
Aquí está el código de una etiqueta de bloque personalizada como esta, que se guardará en el archivo lib/smarty-plugins/block.title.php:
<?php
/**
* Etiqueta de bloque Smarty usada para insertar títulos HTML.
* @param array $params Array asociativo con los parámetros proporcionados a la etiqueta.
* @param string $content Contenido colocado entre las etiquetas de apertura y cierre.
* @param \Smarty\Template $template Objeto que representa la plantilla procesada.
* @param bool $repeat False para la etiqueta de cierre.
* @return ?string El código HTML generado.
*/
function smarty_block_title($params, $content, $template, &$repeat) {
if ($repeat)
return (null);
// inicializa la variable estática $levelsCount,
// que contiene la profundidad de cada nivel de título
static $levelsCount = [0];
// recuperación de los parámetros
$content = trim($content ?? '');
$level = intval($params['level'] ?? 1) ?: 1;
// verificación
if (!$content)
return ('');
// gestión de la variable estática
$levelsCount = array_slice($levelsCount, 0, $level);
$levelsCount[$level - 1] ??= 0;
$levelsCount[$level - 1]++;
// preparación del resultado
$title = implode('.', $levelsCount) . ' ' . $content;
$id = \Temma\Utils\Text::urlize($title);
return sprintf('<h%d id="%s">%s</h%d>', $level, $id, $title, $level);
}
- Línea 11: Declaración de la función smarty_block_title(). Recibe cuatro parámetros: un array asociativo con los parámetros definidos en la plantilla, el texto contenido entre las etiquetas de apertura y cierre, un objeto que representa la plantilla en la que se usó la etiqueta (no vamos a usar este objeto), y un booleano que indica si la función se llama al leer la etiqueta de apertura o la de cierre.
- Líneas 12 y 13: Si la llamada a la función es para la etiqueta de apertura, se devuelve null, ya que el texto contenido entre las etiquetas de apertura y cierre aún no está disponible. Todo el procesamiento se realizará cuando la función se llame para la etiqueta de cierre.
- Línea 17: Definición de una variable estática inicializada con un array que contiene un entero igual a cero. El hecho de que sea una variable estática significa que conservará su valor entre cada llamada a la función. Esta variable contiene la profundidad de cada nivel de título, es decir, el número de títulos conocidos para cada nivel de título actual.
- Líneas 20 y 21: Recupera los parámetros proporcionados a la etiqueta en la plantilla. Se gestionan los valores ausentes o incorrectos.
- Líneas 24 y 25: Gestión del texto vacío.
- Línea 28: El array $levelsCount se reduce si es necesario, cuando el nivel de título pasado como parámetro es inferior al anterior.
- Líneas 29 y 30: En el array $levelsCount, la entrada correspondiente al nivel de título pasado como parámetro se incrementa (después de inicializarse en cero si es necesario).
- Líneas 33 y 34: Definición del título que se insertará en el código HTML, y del identificador asociado. Para generar el identificador, se aplica la función urlize() al título.
- Línea 36: Devuelve la cadena HTML formada por la etiqueta <Hn>, con el identificador como atributo y el título como contenido.