Macro loader

This short tutorial will show you, how to create and register custom macros.

Create macro

First, we create macroSet and add all our macros. How to register macros to template will be shown later.

Note: in Nette 2.1 and older, you have to use Nette\Latte namespace instead of Latte.

$set = Latte\Macros\MacroSet::install($latte->getCompiler());
$nMacro <<<'EOT'
if ($_l->tmp = array_filter(%node.array)) {
    echo ' id="' . %escape(implode("_", $_l->tmp)) . '"';
$set->addMacro('id', null, null, $nMacro);

$_l is a simple local storage object, which you can use to store temporary variables.

Use case in template:

<div n:id="show, true ? success : error">Id success</div>
<div n:id="show, false ? success : error">Id error</div>


<div id="show_success">Id success</div>
<div id="show_error">Id error</div>


Macro has few basic parameters

addMacro($name, $begin, $end = null, $attr = null);

Parameters $begin and $end are used to create classic macro, parameter $attr is used for n:macro.

For deeper knowledge about those parameters you can check Classic vs n:macro section.

This should seem more clear now:

$set->addMacro('id', null, null,
    'if ($_l->tmp = array_filter(%node.array))
    echo \' id="\' . %escape(implode("_", $_l->tmp)) . \'"\'

We can use special aliases like %node.word, %node.array, %node.args, %escape(), %modify(), %var and %raw while writing content code of macro. For more see documentation. For example, when we write in macro %escape($_template->var), it will have same result as {$var} in template.

For better understanding, you can check some examples in Nette: CoreMacros and FormMacros

$attr as callback

In case of long method you can register callback to standalone method.

$set->addMacro('id', null, null, [$this, 'macroId']);

// ...

 * n:id="..."
public function macroId(MacroNode $node, PhpWriter $writer)
    return $writer->write('if ($_l->tmp = array_filter(%node.array)) echo \' id="\' . %escape(implode("_", $_l->tmp)) . \'"\'');


As mentioned in the first part, after creating macroSet, we have have to register it. Only after registration macros can be used in template.

First we create separate class and place it o libs folder.


use Latte\MacroNode;
use Latte\PhpWriter;

class CustomMacros extends Latte\Macros\MacroSet

    public static function install(Latte\Compiler $compiler)
        $set = new static($compiler);
        $set->addMacro('id', null, null, [$set, 'macroId']);

     * n:id="..."
    public function macroId(MacroNode $node, PhpWriter $writer)
        return $writer->write('if ($_l->tmp = array_filter(%node.array)) echo \' id="\' . %escape(implode("_", $_l->tmp)) . \'"\'');


Then we add our class to latte compilation in config.neon

        class: Latte\Engine
            - CustomMacros::install(::$service->getCompiler())

Since Nette 2.1-dev there exists special section for macros:

            - CustomMacros::install

Classic macro vs. n:macro

addMacro($name, $begin, $end = null, $attr = null);

Using only $begin and $end parameters we create classic macro.

Using only $attr parameter we create n:macro.

To combine both in universal macro, we have to register anonymous function or define all parameters.

Use case


# obě makra (všechny parametry)
$set->addMacro("test1", "start", "end", "attributes");

# obě makra (anonymní funkce, callbacks)
$set->addMacro("test1", function ($node, $writer) { ... });
$set->addMacro("test1", [$this, 'myMacro'];
$set->addMacro("test1", ['Macros', 'myMacro']);

# pouze n:makro
$set->addMacro("test2", null, null, "attributes");

# pouze klasické makro
$set->addMacro("test3", "start", "end");


{test1 "parameter1"}Lorem lipsum..{/test1}

<div n:test1="parameter1">Lorem lipsum..</div>

<span n:test2="parameter1">Lorem lipsum..</span>

{test3 "parameter1"}Lorem lipsum..{/test3}


<?php start ?>Lorem lipsum..<?php end ?>

<div <?php atributy ?>>Lorem lipsum..</div>

<span <?php atributy?>>Lorem lipsum..</span>

<?php start ?>Lorem lipsum..<?php end ?>