Luminova Framework

PHP Luminova: Smarty Template Engine Extension

Last updated: 2025-12-05 07:21:50

Render templates efficiently with Luminova’s Smarty extension helpers that reduce unnecessary class loading and keep your application fast and easy to maintain.

Luminova Smarty template extension helps you use the Smarty template engine smoothly inside your Luminova application. Luminova adds a few built-in helpers such as static, new, fn, and const. These helpers make your templates faster, reduce repeated class initialization, and cut down on long-term maintenance work.

The goal is simple: make Smarty easy to use in Luminova so you can focus on building your application, not fighting your tools.

Note:

Luminova Smarty uses {{ and }} as its default delimiters, and Auto Literal is disabled.

This keeps the syntax consistent with Twig Template and allows clean spacing inside delimiters, and prevents Smarty from interpreting single curly braces as template tags (e.g., it requires {{ foo }}, not {foo}).


Smarty Support

Luminova’s Smarty extension works with Smarty Version: 5.7, if you use a newer version and your application begins to break, downgrade back to version 5.7.For full Smarty documentation, see the official website: https://smarty-php.github.io/smarty

Install Smarty with Composer:

composer require "smarty/smarty"

Template Context Object

In Luminova Smarty, the template context is exposed through a single $self object.This works much like Luminova’s default PHP template system, where your view options and the view object itself are isolated and accessed through $self.

So anything you pass from your controller—plus default view options, can be reached using $self->property or $self.method().

Example:

namespace App\Controllers\Http;

use Luminova\Base\Controller;

class MainController extends Controller
{
    public function index(): int 
    {
        return $this->view('index', [
            'name' => 'Peter',
            'age' => 34
        ]);
    }
}

Accessing passed options in the template

{{ $self.name }}
{{ $self.age }}

Default options always available

{{ $self.title }}
{{ $self.asset }}
{{ $self.href }}

Accessing the view object

{{ $self->getOptions() }}
{{ $self->getOption('title') }}
{{ $self.app.session->isOnline() }}

Deep Object Chaining

In standard Smarty, you cannot freely chain through nested objects unless you first assign each level to its own Smarty variable. For example, accessing the session username normally requires multiple assignments:

{{ $self.app assign='app' }}
{{ $app.session assign='session' }}

{{ $session->get('username') }}

Luminova’s Smarty Proxy removes this limitation.You can access deep objects and call their methods directly, without assigning anything:

{{ $self.app.session->get('username') }}

In regular Smarty, this direct chaining is not possible, you must assign each object to a variable before you can reach the next level.

Note:Deep object chaining only works with public properties and methods on the App\Application class, Exported classes, template options, and the Luminova\Template\View object.External classes registered as globals, or standard Smarty plugins do not use the Luminova template proxy, so they will not support this extended chaining behavior.


Exporting Properties and Classes

If you still use the older “export to view” style, you can expose any class to all templates through the application boot process.

namespace App;

use App\Utils\Example;
use App\Utils\StaticExample;
use Luminova\Foundation\Core\Application as CoreApplication;

class Application extends CoreApplication 
{
    protected function onCreate(): void
    {
        $this->view->export(Example::class, 'example'); 
        $this->view->export(StaticExample::class);
    }
}

Accessing exported classes in Smarty templates

{{ $self.example->getValue() }}
{{ $self.StaticExample::getValue() }}

Calling Static Classes

In Luminova Smarty, you can call static methods in two ways:

  1. Register the class inside App\Config\Templates\Smarty\ExtensionsregisterClasses().This lets you call it using an alias.

  2. Call it directly using the static helper with the full namespace.This does not require registration, avoids unnecessary class initialization, and is usually the leaner choice.

The helper follows this signature:

function static(string $class, string $member, mixed ...$arguments): mixed

Parameters

ParameterTypeDescription
$classstringFully qualified class name or registered alias.
$memberstringThe static property or method name to call.
$argumentsmixedOptional method arguments.

Notestatic() is not a real PHP function.It only exists inside Smarty templates. You cannot call it in PHP code.

Examples:

Calling a registered class (from registerClasses in/app/Config/Templates/Smarty/Extensions.php)**

{{ static('Example', 'getName') }}

Set a value and assign it

{{ static('Example', 'setName', 'Peter') assign='example' }}
{{ $example->getName() }}

Call a static method directly using the full namespace

{{ static('App\\Utils\\Example', 'getName') }}
{{ static('\\App\\Utils\\Example' 'setName', 'names') assign = 'example' }}
{{ $example->getName() }}

Instantiate a Class Object

In Luminova Smarty, you can create a new class instance inside a template in two ways:

  1. Register the class inside App\Config\Templates\Smarty\ExtensionsregisterObjects().This lets you use a short alias.

  2. Use the full namespace with the new helper.This avoids registration and resolves the class directly if it exists. It’s also the more efficient option.

The helper follows this signature:

function new(string $class, mixed ...$arguments): object

Parameters

ParameterTypeDescription
$classstringFully qualified class name or registered alias.
$argumentsmixedConstructor arguments to pass to the class.

Notenew() is not a PHP function.It works only inside Smarty templates and cannot be used in PHP code.

Examples:

Initialize an object using a registered alias

{{ new('Example', 'param') assign='example' }}

Initialize an object using the full namespace

{{ new('\\App\\Utils\\Example') assign='example' }}

Use the created object

{{ $example->getName() }}

Or access its public properties:

{{ $example->name }}

Call Functions

In Luminova Smarty, you can call functions in two ways:

  1. Register them inside App\Config\Templates\Smarty\ExtensionsregisterFunctions().This allows you to expose functions as filters, modifiers, plugins, or custom Smarty functions.

  2. Call them directly using the fn helper.Luminova includes a built-in helper class,Luminova\Template\Extensions\SmartyFunction,which behaves much like Twig’s \Twig\TwigFunction to keep everything consistent.

NoteEven if you don’t wrap the function name with fn, Luminova will still resolve the correct function—including Luminova-namespaced helpers and core PHP functions.The fn helper is only needed when you explicitly want this behavior inside templates.

Aliases:func, function behave exactly the same as fn.

The helper signature:

function fn(string $function, mixed ...$arguments): mixed

Parameters

ParameterTypeDescription
$functionstringThe function name (e.g., Luminova\\Funcs\\escape, strlen).
$argumentsmixedOptional function arguments.

Notefn() is not a PHP function.It only works inside Smarty templates.

Examples:

Call registered or global function

{{ myFunction() }}
{{ root('path/to/file', 'filename.json') }}

Call a regular function

{{ fn('myFunction') }}

Call a namespaced Luminova helper

{{ fn('Luminova\\Funcs\\root', 'path/to/file', 'filename.json') }}

Or call Luminova functions without namespace

{{ fn('root', 'path/to/file', 'filename.json') }}

This gives you a simple, uniform way to use PHP and Luminova helper functions directly in your templates without extra setup.


Get Constants

You can access constants in Smarty using the built-in syntax:

{{ $smarty.const.APP_NAME }}

Luminova also provides a const helper that retrieves any globally defined constant.This helper is recommended because it keeps your templates future-proof and easier to maintain.

function const(string $name): mixed

Parameters

ParameterTypeDescription
$namestringThe constant name to retrieve (e.g., APP_NAME, STATUS_SUCCESS).

Example:

To print your application name:

{{ const('APP_NAME') }}

Both methods work, but using the const helper keeps your templates consistent with other Luminova helpers.


Smarty Extensions Registration Pattern

Namespace: App\Config\Templates\Smarty\Extensions

Luminova allows you to register custom functions for Smarty by returning an array of SmartyFunction objects inside your Smarty extension class. Each SmartyFunction maps a name used in templates to a callable handler in PHP.

Basic Function

Here are common ways to define functions using the Luminova\Template\Extensions\SmartyFunction class.

Example:

// /app/Config/Templates/Smarty/Extensions.php

namespace App\Config\Templates\Smarty\Extensions;

use Luminova\Template\Extensions\SmartyFunction;

// In registerFunctions()
return [
    new SmartyFunction('hello', static fn(string $value): string => "Hello $value")
];

No matter how the function is registered, it can be called in both ways:

Function-style:

{{ hello('World') }}

Smarty-style:

{{ hello value='World' }}

This will output:

Hello World

The only thing that changes is how your callback receives the arguments.


Functions with Parameters

Your function can receive parameters in two different ways.It depends on how you register it and how you plan to call it.

Luminova allows you to choose between:

  1. Positional arguments – each value is passed as a normal function argument.
  2. Named arguments – Smarty-style: parameters arrive as one associative array.

Both styles work; you just pick what your function expects.

When positional: true

Your callback receives each parameter in order, just like a normal PHP function.

// In Extensions::registerFunctions()

return [
    new SmartyFunction(
        'greet',
        function(string $name, int $age, array $tools): string {
            return "Hi, am {$name}, {$age} years. Tools: " . var_export($tools, true);
        },
        positional: true
    )
];

When positional: false

Your callback receives one array containing all parameters.

If you call the function using Smarty-style named parameters, Luminova passes them as key–value pairs.

// In Extensions::registerFunctions()

return [
    new SmartyFunction(
        'greet',
        function(array $data): string {
            // You can pick values however you like:
            // Use e.g, $data['name'], $data['age'], $data['tools'] for smarty style
            [$name, $age, $tools] = array_values($data);

            return "Hi, am {$name}, {$age} years. Tools: " . var_export($tools, true);
        },
        positional: false
    )
];

Both result in your PHP callback receiving something like:

// PHp Function-style
['0' => 'Peter', '1' => 20, '2' => ['PHP','JS','JAVA','SWIFT']]
// Smarty-style
['name' => 'Peter', 'age' => 20, 'tools' => ['PHP','JS','JAVA','SWIFT']]

Calling function in template:

Function-style:

{{ greet('Peter', 20, ['PHP', 'JS', 'JAVA', 'SWIFT']) }}

Smarty-style:

{{ greet name='Peter' age=20 tools=['PHP', 'JS', 'JAVA', 'SWIFT'] }}

Output:

Hi, am Peter, 20 years. Tools: [0 => 'PHP', 1 => 'JS', 2 => 'JAVA', 3 => 'SWIFT']

Registering a Modifiers

Modifiers work like |upper, |lower, etc.

// In Extensions::registerFunctions()

return [
    new SmartyFunction('upper', 'strtoupper', SmartyFunction::MODIFIER),
    new SmartyFunction('lower', 'strtolower', SmartyFunction::MODIFIER)
];

Smarty template:

{{ $self.name|upper }}

Block Function

Block functions wrap the content between {tag} and {/tag}.

// In Extensions::registerFunctions()

return [
    new SmartyFunction(
        'bold',
        fn($params, $content) => '<strong>' . $content . '</strong>',
        SmartyFunction::BLOCK
    )
];

Smarty template:

{{ bold }}
This text will be bold.
{{ /bold }}

Exposing Object Methods

If you want to expose some methods of a class for Smarty to call:

// In Extensions::registerFunctions()

return [
    new SmartyFunction(
        'example',
        new App\Utils\Example(),
        type: SmartyFunction::OBJECT,
        allowedMethodsProperties: ['getName', 'setName']
    )
];

Template usage:

{{ example->setName('Peter') }}
{{ $example->getName() }}