Latte For Developers

How to Render a Template

Just run this code:

$latte = new Latte\Engine;

$latte->setTempDirectory('/path/to/tempdir');

$params = [
	'items' => ['one', 'two', 'three'],
];

// render to output
$latte->render('template.latte', $params);
// or render to string
$html = $latte->renderToString('template.latte', $params);

Latte automatically regenerates the cache every time you change the template, which can be turned off in the production environment to save a little performance:

$latte->setAutoRefresh(false);

You can also use an object instead of the $params array, which has some advantages. You get autosuggestion in IDE and way for registration of filters and functions:

class MyTemplate
{
	public $items = ['one', 'two', 'three'];
}

$params = new MyTemplate;
$latte->render('template.latte', $params);

Template from String

You can load template from strings using Latte\Loaders\StringLoader:

$latte->setLoader(new Latte\Loaders\StringLoader([
	'main.file' => '{include other.file}',
	'other.file' => '{if true} {$var} {/if}',
]));

$latte->render('main.file', $params);

Custom Filters

Custom filters can be registered this way:

$latte = new Latte\Engine;
$latte->addFilter('shortify', function (string $s): string {
	return mb_substr($s, 0, 10); // shortens the text to 10 characters
});

In this case it would be better for the filter to get an additional parameter:

$latte->addFilter('shortify', function (string $s, int $len = 10): string {
	return mb_substr($s, 0, $len);
});

We use it in a template like this:

<p>{$text|shortify}</p>
<p>{$text|shortify:100}</p>

The second way to define a filter is a template class. It is important to specify the annotation @filter:

class MyTemplate
{
	/** @filter */
	public function shortify(string $s, int $len = 10): string
	{
		return mb_substr($s, 0, $len);
	}
}

$params = new MyTemplate;
...
$latte->render('template.latte', $params);

Universal filter

Manual registration of multiple filter can be replaced with a single universal registration:

$latte->addFilter(null, 'Filters::common');

Filters:common gets name of filter as first parameter.

class Filters
{
	public static function common($filter, $value)
	{
		if (method_exists(__CLASS__, $filter)) {
			$args = func_get_args();
			array_shift($args);
			return call_user_func_array([__CLASS__, $filter], $args);
		}
	}

	public static function shortify($s, $len = 10)
	{
		return mb_substr($s, 0, $len);
	}
}

Functions

In Latte you can use all PHP functions and at the same time define your own:

$latte = new Latte\Engine;
$latte->addFunction('random', function (...$args) {
	return array_rand($args);
});

The usage is then the same as when calling the PHP function:

{random(apple, orange, lemon)} // prints for example: apple

The second way to define a function is a template class. It is important to specify the annotation @function:

class MyTemplate
{
	/** @function */
	public function random(...$args)
	{
		return array_rand($args);
	}
}

$params = new MyTemplate;
...
$latte->render('template.latte', $params);

User-defined Tags

Latte provides API for making your own tags. It isn't difficult at all. Tags are added in sets (a set can consist of a single tag).

$latte = new Latte\Engine;

// lets create a set
$set = new Latte\Macros\MacroSet($latte->getCompiler());

// add new pair tag {try} ... {/try}
$set->addMacro(
	'try', // tag name
	'try {',  // PHP code replacing the opening brace
	'} catch (\Exception $e) {}' // code replacing the closing brace
);

If we omit the last parameter of addMacro() method, we denote the tag is not paired.

PHP code in the second and third parameter can contain tags:

  • %node.word – inserts the first tag argument
  • %node.array – inserts the tag arguments formatted as a PHP array
  • %node.args – inserts the tag arguments formatted as PHP code
  • %escape(...) – replaced by the current escape function
  • %modify(...) – replaced by a sequence of modifiers

For example:

$set->addMacro('if', 'if (%node.args):', 'endif');

If the tag logic is more complex we can use callbacks or lambda functions instead of strings. In the first parameter, they will get MacroNode object which represents the current node, the second parameter is PhpWriter object which helps with generating the output code.

$set->addMacro('if', function ($node, $writer) {
	return $writer->write('if (%node.args):');
}, 'endif');
Improve this page