Creating Custom Functions
Easily add your own helper functions to Latte templates. Call PHP logic directly within expressions for calculations, accessing services, or generating dynamic content, keeping your templates clean and powerful.
What are Functions?
Latte functions allow you to extend the set of functions callable within template expressions ({...}
). Think of
them as custom PHP functions that are available only inside your Latte templates. This provides several advantages:
Convenience: You can define helper logic (like calculations, formatting, or accessing application data) and call it
using a simple, familiar function syntax directly in the template, just like you would call strlen()
or
date()
in PHP.
{var $userInitials = initials($userName)} {* e.g., 'J. D.' *}
{if hasPermission('article', 'edit')}
<a href="...">Edit</a>
{/if}
No Global Scope Pollution: Unlike defining a true global function in PHP, Latte functions exist only within the context of template rendering. You don't need to clutter the global PHP namespace with template-specific helpers.
Integration with Application Logic: The PHP callable behind a Latte function can be anything – a closure, a static
method, or an instance method. This means your template functions can easily access application services, databases,
configuration, or any other necessary logic by capturing variables (in closures) or through dependency injection (in objects). The
hasPermission
example above clearly demonstrates this, likely calling an authorization service in the background.
Override Native Functions (Optional): You can even define a Latte function with the same name as a native PHP function.
Within the template, your custom version will be called instead. This can be useful for providing template-specific behavior or
ensuring consistent handling (e.g., making strlen
always multibyte-safe). Use this feature with caution to avoid
confusion.
By default, Latte allows calling all native PHP functions (unless restricted by the Sandbox). Custom functions augment this built-in library with your project's specific needs.
If you are transforming a single value, a custom filter might be more idiomatic.
Creating and Registering Functions
Similar to filters, there are several ways to define and register custom functions.
Direct Registration via addFunction()
The simplest method is using addFunction()
on the Latte\Engine
object. You provide the function name
(as it will appear in the template) and the corresponding PHP callable.
$latte = new Latte\Engine;
// Simple helper function
$latte->addFunction('initials', function (string $name): string {
preg_match_all('#\b\w#u', $name, $m);
return implode('. ', $m[0]) . '.';
});
Usage in Template:
{var $userInitials = initials($userName)}
Function arguments in the template are passed directly to the PHP callable in the same order. PHP features like type hints,
default values, and variadic parameters (...
) work as expected.
Registration via Extension
For better organization and reusability, register functions within a Latte Extension. This is the recommended approach for non-trivial applications or shared libraries.
namespace App\Latte;
use Latte\Extension;
use Nette\Security\Authorizator;
class MyLatteExtension extends Extension
{
public function __construct(
// Assume Authorizator service exists
private Authorizator $authorizator,
) {
}
public function getFunctions(): array
{
// Register methods as Latte functions
return [
'hasPermission' => $this->hasPermission(...),
];
}
public function hasPermission(string $resource, string $action): bool
{
return $this->authorizator->isAllowed($resource, $action);
}
}
// Registration (assuming $container holds the DIC)
$extension = $container->getByType(App\Latte\MyLatteExtension::class);
$latte = new Latte\Engine;
$latte->addExtension($extension);
This approach clearly demonstrates how functions defined in Latte can be backed by object methods which, in turn, can have their own dependencies managed by your application's dependency injection container or factory. This keeps your template logic connected to your application's core while maintaining organization.
Functions Using a Class with Attributes
Just like filters, functions can be defined as methods within your template parameters class using the
#[Latte\Attributes\TemplateFunction]
attribute.
use Latte\Attributes\TemplateFunction;
class TemplateParameters
{
public function __construct(
public string $userName,
// other parameters...
) {}
// This method becomes available as {initials(...)} in the template
#[TemplateFunction]
public function initials(string $name): string
{
preg_match_all('#\b\w#u', $name, $m);
return implode('. ', $m[0]) . '.';
}
}
// Pass the object to the template
$params = new TemplateParameters(userName: 'John Doe', /* ... */);
$latte->render('template.latte', $params);
Latte automatically discovers and registers methods marked with this attribute when the parameters object is passed to the template. The function name in the template matches the method name.
{* Use the function defined in the parameters class *}
{var $inits = initials($userName)}
Contextual Functions?
Unlike filters, there isn't a direct concept of “contextual functions” that receive a FilterInfo
-like object.
Functions operate within expressions and typically don't need direct access to the rendering context or content type information
in the same way filters applied to blocks do.