Add namespace to compiled latte files?
- bernhard
- Member | 54
TL;DR: Is there a way to add “namespace ProcessWire” to compiled latte php files?
Background:
I've created RockFronted, a module for the ProcessWire CMS that makes it easy to use Latte for frontend development.
In ProcessWire, we have the ProcessWire API, which consists of several API variables to access several functionalities, examples are $wire for the main ProcessWire object, or $modules to access modules, $files, $session, etc.
I've made all these API variables available to any latte file, which is great :)
The problem arises, when we try to use the “functions API”, which is accessible through functions in the ProcessWire namespace, like wire(), modules(), etc.
In latte, I have to write {ProcessWire\modules()->get(‘MyModule’)} instead of <? modules()->get(‘MyModule’) ?>
I don't really have a problem with that, but some users have: https://processwire.com/…ne-by-nette/?…
It's understandable, that if you are a frontend dev, you are not really familiar with the concept of namespaces or even more understandable that you don't know what latte does behind the scenes (compile latte to php).
I did experiment a little with adding a custom extension to expose all available API functions to latte files like this:
<?php
namespace ProcessWire;
use Latte\Extension;
final class CustomLatteExtension extends Extension
{
/**
* Define functions available in all Latte files
* These can be anything ProcessWire related or not, any functions defined here will be available everywhere
*/
public function getFunctions(): array
{
$functions = [];
foreach (wire('all')->getArray() as $key => $value) {
if (!is_object($value)) continue;
$functions[$key] = fn() => $value;
}
return $functions;
}
}
But this is not a reliable solution, because some functions might take arguments, some might not. The next problem is that not all available functions are listed in wire(‘all’), because anyone could develop a module and add a custom function foo() and this would be available via ProcessWire\foo() but it would not be listed in wire(‘all’)
I have looked into compiled latte php files and I see that they don't have a namespace. So I'm wondering if it is possible to add a namespace to these files? I'm a little afraid, that this would have unintended side effects though ^^
Maybe you have better ideas? Maybe we could add exception handlers that kicks in whenever a function is called that does not exist (like wire()->… ) and then tries to call the same function with a “ProcessWire” namespace?
Thx for your help and ideas!
PS: Could the subscribe checkbox be moved to the send button? It's so easy to miss! Or even better make it checked by default!

- David Grudl
- Nette Core | 8282
In Latte 3, you can do absolutely anything, it's perfectly configurable. But
the easiest way would be to use getFunctions()
. I don't know what
wire('all')->getArray()
is for, but in 2024, I would handle it
this way:
- Open https://chatgpt.com
- Type: “Create a class
ProcessWire\CustomLatteExtension
that extends fromLatte\Extension
and has a methodgetFunctions()
. This method will create a list of all defined PHP functions that are located in theProcessWire
namespace. It will return an array where the key will be the function name (without the namespace) and the value will be a callback to that function.”
:-)
- bernhard
- Member | 54
Hey @DavidGrudl
today I realised that in {embed}ed files I don't have access to ProcessWire's API variables. I basically didn't realise this because I was always using {include} and in the first render() call I was passing all get_defined_vars() to the render call. That made all ProcessWire API variables (like $page, $sanitizer, $input, etc) available in all my latte template files.
Now I just found out about how to use {embed} properly (shame on me!!!) and according to the docs “Embedded templates do not have access to the variables of the active context, but they do have access to global variables.”
I would consider ProcessWire's API variables global variables, but obviously Latte does not know that yet.
So this is what I tried to not only expose processwire functions like wire(), pages(), sanitizer() etc but also their variable alter egos:
<?php
use Latte\Extension;
use Latte\Runtime\Template;
use function ProcessWire\rockfrontend;
use function ProcessWire\wire;
final class ExposeFunctionsExtension extends Extension
{
/**
* Initializes before template is rendered.
*/
public function beforeRender(Template $template): void
{
// expose all ProcessWire API variables to latte
$apiVars = wire('all')->getArray();
// Use reflection to access the protected $params property
$reflection = new \ReflectionClass($template);
$paramsProperty = $reflection->getProperty('params');
$paramsProperty->setAccessible(true);
// Get current parameters and merge with API variables
$currentParams = $paramsProperty->getValue($template);
$newParams = array_merge(
$apiVars, // lowest priority
rockfrontend()->definedVars,
$currentParams, // highest priority
);
// Set the merged parameters back
$paramsProperty->setValue($template, $newParams);
}
/**
* This method will create a list of all defined PHP functions
* It will return an array where the key will be the function name
* (without the namespace) and the value will be a callback to that
* function.
*/
public function getFunctions(): array
{
$functions = get_defined_functions()['user'];
$result = [];
foreach ($functions as $function) {
if (!str_starts_with($function, 'processwire\\')) continue;
$name = str_replace('processwire\\', '', $function);
$result[$name] = $function;
}
return $result;
}
}
It works, but I don't think it is the best or most elegant solution, is it?
Would you mind helping me in improving that implementation for my module, please? Thx in advance!
PS: In the docs (https://latte.nette.org/…ending-latte#…) I think the parameter type is wrong: “beforeCompile (Latte\Engine $engine): void” – should be a Template, not Engine, no?
PPS: {embed}s are great! What do you think of adding a shorthand for this:
{embed whatever}
{block foo}<h1>Foo!</h1>{/block}
{/embed}
And make it work like this if only one block is defined in the file “whatever”:
{embed whatever}<h1>Shorter Foo!</h1>{/embed}
PPPS: My first try was to use getProviders() and just return an array of all PW API variables, but that didn't work. $wire/$page/$sanitzer etc. all were NULL
Last edited by bernhard (2025-07-13 23:05)
- markmanwithlatte
- Member | 3
I know this is not directed at me, and Im not even sure Im fulling understanding the issue, but here is what I do when I need a variable within an included template
{$whatIneed = 123456;}
{include file ‘myinclude’}
and now myinclude
has access to $whatIneed
A more advanced version of this is a template that processes an array repetitively:
{foreach $mylist['news'] as $individualnewsitem}
{include file 'newstemplate'}
{/foreach}