Nette Documentation Preview

syntax
Creación de funciones personalizadas
************************************

.[perex]
Añada fácilmente sus propias funciones auxiliares a las plantillas de Latte. Llame a lógica PHP directamente dentro de las expresiones para hacer cálculos, acceder a servicios o generar contenido dinámico, manteniendo sus plantillas limpias y potentes.


¿Qué son las funciones?
=======================

Las funciones de Latte permiten ampliar el conjunto de funciones que se pueden llamar dentro de las expresiones de la plantilla (`{...}`). Piense en ellas como **funciones PHP propias disponibles solo dentro de sus plantillas de Latte**. Esto ofrece varias ventajas:

**Comodidad:** puede definir lógica auxiliar (cálculos, formateo o acceso a datos de la aplicación) y llamarla con una sintaxis de función sencilla y familiar directamente en la plantilla, igual que llamaría a `strlen()` o `date()` en PHP.

```latte
{var $userInitials = initials($userName)} {* p. ej. 'J. D.' *}

{if hasPermission('article', 'edit')}
    <a href="...">Edit</a>
{/if}
```

**Sin contaminar el ámbito global:** a diferencia de definir una verdadera función global en PHP, las funciones de Latte existen solo en el contexto del renderizado de plantillas. No necesita llenar el espacio de nombres global de PHP con auxiliares específicos de las plantillas.

**Integración con la lógica de la aplicación:** el callable de PHP que hay detrás de una función de Latte puede ser cualquier cosa: un closure, un método estático o un método de instancia. Esto significa que sus funciones de plantilla pueden acceder fácilmente a servicios de la aplicación, bases de datos, configuración o cualquier otra lógica necesaria, capturando variables (en los closures) o mediante inyección de dependencias (en los objetos). El ejemplo anterior de `hasPermission` lo demuestra con claridad: probablemente llama a un servicio de autorización en segundo plano.

**Sobrescribir funciones nativas (opcional):** incluso puede definir una función de Latte con el mismo nombre que una función nativa de PHP. Dentro de la plantilla se llamará a su versión propia. Esto puede servir para dar un comportamiento específico de las plantillas o garantizar un tratamiento coherente (por ejemplo, que `strlen` sea siempre seguro con multibyte). Use esta posibilidad con prudencia para evitar confusiones.

De forma predeterminada, Latte permite llamar a *todas* las funciones nativas de PHP (salvo que lo restrinja el [Sandbox|sandbox]). Las funciones personalizadas amplían esa biblioteca integrada con las necesidades concretas de su proyecto.

Si lo que hace es transformar un único valor, quizá resulte más idiomático un [filtro personalizado|custom filters].


Crear y registrar funciones
===========================

Igual que con los filtros, hay varias formas de definir y registrar funciones personalizadas.


Registro directo con `addFunction()`
------------------------------------

El método más sencillo es usar `addFunction()` sobre el objeto `Latte\Engine`. Indique el nombre de la función (tal como aparecerá en la plantilla) y el callable de PHP correspondiente.

```php
$latte = new Latte\Engine;

// Función auxiliar simple
$latte->addFunction('initials', function (string $name): string {
	preg_match_all('#\b\w#u', $name, $m);
	return implode('. ', $m[0]) . '.';
});
```

**Uso en la plantilla:**

```latte
{var $userInitials = initials($userName)}
```

Los argumentos de la función en la plantilla se pasan directamente al callable de PHP en el mismo orden. Las características de PHP, como las declaraciones de tipo, los valores predeterminados y los parámetros variádicos (`...`), funcionan como cabe esperar.


Registro mediante una extensión
-------------------------------

Para una mejor organización y reutilización, registre las funciones dentro de una [extensión de Latte |extending-latte#Latte Extension]. Es el enfoque recomendado para aplicaciones no triviales o bibliotecas compartidas.

```php
namespace App\Templating;

use Latte\Extension;
use Nette\Security\Authorizator;

class MyLatteExtension extends Extension
{
	public function __construct(
		// Suponemos que existe el servicio Authorizator
		private Authorizator $authorizator,
	) {
	}

	public function getFunctions(): array
	{
		// Registra los métodos como funciones de Latte
		return [
			'hasPermission' => $this->hasPermission(...),
		];
	}

	public function hasPermission(string $resource, string $action): bool
	{
		return $this->authorizator->isAllowed($resource, $action);
	}
}

// Registro (suponiendo que $container contiene el DIC)
$extension = $container->getByType(MyLatteExtension::class);
$latte = new Latte\Engine;
$latte->addExtension($extension);
```

Este enfoque muestra con claridad cómo las funciones definidas en Latte pueden apoyarse en métodos de objetos que, a su vez, pueden tener sus propias dependencias gestionadas por el contenedor de inyección de dependencias o por una factory de su aplicación. Así, la lógica de sus plantillas se mantiene conectada al núcleo de la aplicación sin perder organización.


Funciones mediante una clase con atributos .{toc: Functions Using the Class}
-----------------------------------------------------------------------------

Igual que los filtros, las funciones pueden definirse como métodos dentro de su [clase de parámetros de la plantilla |develop#Parámetros como clase] usando el atributo `#[Latte\Attributes\TemplateFunction]`.

```php
use Latte\Attributes\TemplateFunction;

class TemplateParameters
{
	public function __construct(
		public string $userName,
		// otros parámetros...
	) {}

	// Este método queda disponible como {initials(...)} en la plantilla
	#[TemplateFunction]
	public function initials(string $name): string
	{
		preg_match_all('#\b\w#u', $name, $m);
		return implode('. ', $m[0]) . '.';
	}
}

// Pasa el objeto a la plantilla
$params = new TemplateParameters(userName: 'John Doe', /* ... */);
$latte->render('template.latte', $params);
```

Latte descubre y registra automáticamente los métodos marcados con este atributo cuando se pasa a la plantilla el objeto de parámetros. El nombre de la función en la plantilla coincide con el nombre del método.

```latte
{* Usa la función definida en la clase de parámetros *}
{var $inits = initials($userName)}
```

**¿Funciones contextuales?**

A diferencia de los filtros, las funciones no reciben un objeto `FilterInfo`. Aun así, una función puede acceder al contexto de la plantilla: si su primer parámetro está declarado con el tipo `Latte\Runtime\Template`, Latte le pasa automáticamente el objeto de la plantilla actual. Así están implementadas exactamente las funciones integradas `hasBlock()` y `hasTemplate()`.

Creación de funciones personalizadas

Añada fácilmente sus propias funciones auxiliares a las plantillas de Latte. Llame a lógica PHP directamente dentro de las expresiones para hacer cálculos, acceder a servicios o generar contenido dinámico, manteniendo sus plantillas limpias y potentes.

¿Qué son las funciones?

Las funciones de Latte permiten ampliar el conjunto de funciones que se pueden llamar dentro de las expresiones de la plantilla ({...}). Piense en ellas como funciones PHP propias disponibles solo dentro de sus plantillas de Latte. Esto ofrece varias ventajas:

Comodidad: puede definir lógica auxiliar (cálculos, formateo o acceso a datos de la aplicación) y llamarla con una sintaxis de función sencilla y familiar directamente en la plantilla, igual que llamaría a strlen() o date() en PHP.

{var $userInitials = initials($userName)} {* p. ej. 'J. D.' *}

{if hasPermission('article', 'edit')}
    <a href="...">Edit</a>
{/if}

Sin contaminar el ámbito global: a diferencia de definir una verdadera función global en PHP, las funciones de Latte existen solo en el contexto del renderizado de plantillas. No necesita llenar el espacio de nombres global de PHP con auxiliares específicos de las plantillas.

Integración con la lógica de la aplicación: el callable de PHP que hay detrás de una función de Latte puede ser cualquier cosa: un closure, un método estático o un método de instancia. Esto significa que sus funciones de plantilla pueden acceder fácilmente a servicios de la aplicación, bases de datos, configuración o cualquier otra lógica necesaria, capturando variables (en los closures) o mediante inyección de dependencias (en los objetos). El ejemplo anterior de hasPermission lo demuestra con claridad: probablemente llama a un servicio de autorización en segundo plano.

Sobrescribir funciones nativas (opcional): incluso puede definir una función de Latte con el mismo nombre que una función nativa de PHP. Dentro de la plantilla se llamará a su versión propia. Esto puede servir para dar un comportamiento específico de las plantillas o garantizar un tratamiento coherente (por ejemplo, que strlen sea siempre seguro con multibyte). Use esta posibilidad con prudencia para evitar confusiones.

De forma predeterminada, Latte permite llamar a todas las funciones nativas de PHP (salvo que lo restrinja el Sandbox). Las funciones personalizadas amplían esa biblioteca integrada con las necesidades concretas de su proyecto.

Si lo que hace es transformar un único valor, quizá resulte más idiomático un filtro personalizado.

Crear y registrar funciones

Igual que con los filtros, hay varias formas de definir y registrar funciones personalizadas.

Registro directo con addFunction()

El método más sencillo es usar addFunction() sobre el objeto Latte\Engine. Indique el nombre de la función (tal como aparecerá en la plantilla) y el callable de PHP correspondiente.

$latte = new Latte\Engine;

// Función auxiliar simple
$latte->addFunction('initials', function (string $name): string {
	preg_match_all('#\b\w#u', $name, $m);
	return implode('. ', $m[0]) . '.';
});

Uso en la plantilla:

{var $userInitials = initials($userName)}

Los argumentos de la función en la plantilla se pasan directamente al callable de PHP en el mismo orden. Las características de PHP, como las declaraciones de tipo, los valores predeterminados y los parámetros variádicos (...), funcionan como cabe esperar.

Registro mediante una extensión

Para una mejor organización y reutilización, registre las funciones dentro de una extensión de Latte. Es el enfoque recomendado para aplicaciones no triviales o bibliotecas compartidas.

namespace App\Templating;

use Latte\Extension;
use Nette\Security\Authorizator;

class MyLatteExtension extends Extension
{
	public function __construct(
		// Suponemos que existe el servicio Authorizator
		private Authorizator $authorizator,
	) {
	}

	public function getFunctions(): array
	{
		// Registra los métodos como funciones de Latte
		return [
			'hasPermission' => $this->hasPermission(...),
		];
	}

	public function hasPermission(string $resource, string $action): bool
	{
		return $this->authorizator->isAllowed($resource, $action);
	}
}

// Registro (suponiendo que $container contiene el DIC)
$extension = $container->getByType(MyLatteExtension::class);
$latte = new Latte\Engine;
$latte->addExtension($extension);

Este enfoque muestra con claridad cómo las funciones definidas en Latte pueden apoyarse en métodos de objetos que, a su vez, pueden tener sus propias dependencias gestionadas por el contenedor de inyección de dependencias o por una factory de su aplicación. Así, la lógica de sus plantillas se mantiene conectada al núcleo de la aplicación sin perder organización.

Funciones mediante una clase con atributos

Igual que los filtros, las funciones pueden definirse como métodos dentro de su clase de parámetros de la plantilla usando el atributo #[Latte\Attributes\TemplateFunction].

use Latte\Attributes\TemplateFunction;

class TemplateParameters
{
	public function __construct(
		public string $userName,
		// otros parámetros...
	) {}

	// Este método queda disponible como {initials(...)} en la plantilla
	#[TemplateFunction]
	public function initials(string $name): string
	{
		preg_match_all('#\b\w#u', $name, $m);
		return implode('. ', $m[0]) . '.';
	}
}

// Pasa el objeto a la plantilla
$params = new TemplateParameters(userName: 'John Doe', /* ... */);
$latte->render('template.latte', $params);

Latte descubre y registra automáticamente los métodos marcados con este atributo cuando se pasa a la plantilla el objeto de parámetros. El nombre de la función en la plantilla coincide con el nombre del método.

{* Usa la función definida en la clase de parámetros *}
{var $inits = initials($userName)}

¿Funciones contextuales?

A diferencia de los filtros, las funciones no reciben un objeto FilterInfo. Aun así, una función puede acceder al contexto de la plantilla: si su primer parámetro está declarado con el tipo Latte\Runtime\Template, Latte le pasa automáticamente el objeto de la plantilla actual. Así están implementadas exactamente las funciones integradas hasBlock() y hasTemplate().