Class Latte\Macros\MacroSet not found

Notice: This thread is very old.
RadaR
Member | 46
+
0
-

I have problem with David's example for standalone Latte API.

Before, I used whole Nette\Latte somehow like this:

require_once ('Nette/loader.php');

use Nette\Templating\FileTemplate;

$template = new FileTemplate();
$template->setCacheStorage(new Nette\Caching\Storages\PhpFileStorage(ROOT_PATH. 'cache/nette/'));
$template->registerHelperLoader('Nette\Templating\Helpers::loader');
$template->onPrepareFilters[] = function($template) {
	$latte = new Nette\Latte\Engine;
	$template->registerFilter($latte);

	$set = new Nette\Latte\Macros\MacroSet($latte->compiler);

	$set->addMacro(
		'SklkartaNazev',
		'$args = %node.array;echo ($args[0] == \'\' ? $args[1] : $args[0]);'
	);
};

Now, I would like to start using standalone Latte API in similar way. My problems / questions are:

  1. First, I got error message Fatal error: Class ‘Latte\Engine’ not found in…

OK, let's add some classes to my script:

<?php
require_once('Latte/Object.php');
require_once('Latte/Engine.php');
require_once('Latte/Compiler.php');
require_once('Latte/Template.php');
require_once('Latte/ILoader.php');
require_once('Latte/Parser.php');
require_once('Latte/Token.php');
require_once('Latte/Loaders/FileLoader.php');
require_once('Latte/Macros/CoreMacros.php');
require_once('Latte/Macros/MacroSet.php');
require_once('Latte/Macros/BlockMacros.php');
// (This is terrible. I think there is better way to do this...?)

$template = new Latte\Engine;
$template->setTempDirectory(__DIR__. '/cache/nette/');

$template->onCompile[] = function($template) {
   	$template->addMacro(
		'SklkartaNazev',
		'$args = %node.array;echo ($args[0] == \'\' ? $args[1] : $args[0]);'
	);
};


$template->test = 'abc';
$template->render('test.htm', array());
?>

But, this is the end. I still got error message Fatal error: Class ‘Latte\Macros\MacroSet’ not found – even so class MacroSet.php is included. It does not work :(

  1. How I add my own custom macros? It's this way correct?
$template->onCompile[] = function($template) {
   	$template->addMacro(
		'SklkartaNazev',
		'$args = %node.array;echo ($args[0] == \'\' ? $args[1] : $args[0]);'
	);
};

Unfortunately, I do not understand this http://goo.gl/d5A1u2

3. It's possible to use?

$template->setFile('test.htm');

4. What is variable $parameters? See:

$template->render('test.htm', $parameters);

Last edited by RadaR (2014-04-09 10:17)

Milo
Nette Core | 1283
+
0
-

Ad loading… Use Composer ;) Manual loader will be added. To solve Fatal, load MacroSet.php before CoreMacros.php. Full loadig can looks like:

EDIT: File latte.php exists in Latte repo now.

require __DIR__ . '/Latte/exceptions.php';
require __DIR__ . '/Latte/ILoader.php';
require __DIR__ . '/Latte/IMacro.php';
require __DIR__ . '/Latte/Runtime/IHtmlString.php';
require __DIR__ . '/Latte/Helpers.php';
require __DIR__ . '/Latte/Object.php';
require __DIR__ . '/Latte/Compiler.php';
require __DIR__ . '/Latte/Engine.php';
require __DIR__ . '/Latte/HtmlNode.php';
require __DIR__ . '/Latte/MacroNode.php';
require __DIR__ . '/Latte/Parser.php';
require __DIR__ . '/Latte/PhpWriter.php';
require __DIR__ . '/Latte/Template.php';
require __DIR__ . '/Latte/Token.php';
require __DIR__ . '/Latte/TokenIterator.php';
require __DIR__ . '/Latte/Tokenizer.php';
require __DIR__ . '/Latte/MacroTokens.php';
require __DIR__ . '/Latte/Loaders/FileLoader.php';
require __DIR__ . '/Latte/Loaders/StringLoader.php';
require __DIR__ . '/Latte/Macros/MacroSet.php';
require __DIR__ . '/Latte/Macros/BlockMacros.php';
require __DIR__ . '/Latte/Macros/CoreMacros.php';
require __DIR__ . '/Latte/Runtime/CachingIterator.php';
require __DIR__ . '/Latte/Runtime/Filters.php';
require __DIR__ . '/Latte/Runtime/Html.php';

Last edited by Milo (2014-04-22 11:12)

Milo
Nette Core | 1283
+
+1
-

Add macro… You get Engine in callback. The easist way is to use MacroSet

$engine = new Latte\Engine;
$engine->onCompile[] = function(Latte\Engine $engine) {
	$macroSet = new Latte\Macros\MacroSet($engine->getCompiler());
	$macroSet->addMacro('myMacro', "echo 'FOO';", '');
};
Milo
Nette Core | 1283
+
0
-

Add shortNoEscape It enables/disables ! syntax. So {!$var} will be allowed. But preferred way is to use {$var |noEscape}. It's better readable.

Milo
Nette Core | 1283
+
+1
-

Add render Parameters are “variables” in template.

# Instead of
$template->a = 'aaa';
$template->b = 'bbb';
$template->render();

# use
$params = array('a' => 'aaa', 'b' => 'bbb');
$engine->render('template.latte', $params);

Yeh, it is a new way. If you liked the old behaviour, make your own template like:

class MyTemplate
{
	private $parameters = array();

	public function __set($name, $value)
	{
		$this->parameters[$name] = $value;
	}

	public function & __get($name)
	{
		if (!array_key_exists($name, $this->parameters)) {
			trigger_error("Missing parameter '$name' in template.", E_USER_WARNING);
			return;
		}

		return $this->parameters[$name];
	}

	public function getParameters()
	{
		return $this->parameters;
	}

}

# and
$template = new MyTemplate;
$template->a = 'aaa';

$engine->render('my-page.latte', $template->getParameters());

Maybe there is a simplest way. I'm familiarizing with new API too.

RadaR
Member | 46
+
0
-

Oh, thank you very much for your time!

ad 1) I don't know what Composer is, it's a new for me. But your full-loading-code helped me :)

ad 2) My code now is:

require __DIR__ . '/Latte/exceptions.php';
require __DIR__ . '/Latte/ILoader.php';
require __DIR__ . '/Latte/IMacro.php';
require __DIR__ . '/Latte/Runtime/IHtmlString.php';
require __DIR__ . '/Latte/Helpers.php';
require __DIR__ . '/Latte/Object.php';
require __DIR__ . '/Latte/Compiler.php';
require __DIR__ . '/Latte/Engine.php';
require __DIR__ . '/Latte/HtmlNode.php';
require __DIR__ . '/Latte/MacroNode.php';
require __DIR__ . '/Latte/Parser.php';
require __DIR__ . '/Latte/PhpWriter.php';
require __DIR__ . '/Latte/Template.php';
require __DIR__ . '/Latte/Token.php';
require __DIR__ . '/Latte/TokenIterator.php';
require __DIR__ . '/Latte/Tokenizer.php';
require __DIR__ . '/Latte/MacroTokens.php';
require __DIR__ . '/Latte/Loaders/FileLoader.php';
require __DIR__ . '/Latte/Loaders/StringLoader.php';
require __DIR__ . '/Latte/Macros/MacroSet.php';
require __DIR__ . '/Latte/Macros/BlockMacros.php';
require __DIR__ . '/Latte/Macros/CoreMacros.php';
require __DIR__ . '/Latte/Runtime/Filters.php';

$template = new Latte\Engine;
$template->setTempDirectory(__DIR__. '/cache/nette/');
$template->onCompile[] = function(Latte\Engine $template) {
	$macroSet = new Latte\Macros\MacroSet($template->getCompiler());
   	$macroSet->addMacro('myMacro', "echo 'FOO';", '');
};

//$template->test = 'Hello';
$template->render('test.htm', array('test' => 'Hello'));

But there is some problem remains…

New way to passing variables to template. Hmm… honestly, it's sucks :( Old method was better, straightest for me. I have written whole app by old way, I don't want to replace it. Unnecessary work.

I would like to use $template->setFile(path-to-template); But it seems to be not working.

My own macros still not working. When I use {myMacro} in template, I have got the message:
Fatal error: Uncaught exception ‘Latte\CompileException’ with message 'Missing {/myMacro} in test…htm

I thought that Latte API will provide same functionality as in Nette, but this is not the same… :(

Last edited by RadaR (2014-04-09 13:28)

Milo
Nette Core | 1283
+
0
-

RadaR wrote:
New way to passing variables to template. Hmm… honestly, it's sucks :(

It doesn't :) It is just more “low-level”.

Old method was better, straightest for me. I have written whole app by old way, I don't want to replace it. Unnecessary work.

That's because there was a mix between Latte and Template. Now are the Template a Latte separated concepts. Post here how you handled templates with latte in the old way and we can cretate an backward-compatible solution.

My own macros still not working. When I use {myMacro} in template, I have got the message:
Fatal error: Uncaught exception ‘Latte\CompileException’ with message 'Missing {/myMacro} in test…htm

Strange. Show me how do you register the macro and snippet of code from template.

I thought that Latte API will provide same functionality as in Nette, but this is not the same… :(

Latte becomes an alone project. It is great for next development. And I'm curious, why are you upgrading to new Latte API?

RadaR
Member | 46
+
0
-

It doesn't :) It is just more “low-level”.

That's right :)

That's because there was a mix between Latte and Template. Now are the Template a Latte separated concepts. Post here how you handled templates with latte in the old way and we can cretate an backward-compatible solution.

You already propose possible solution by the class MyTemplate. I will consider your suggestion and then I make a decision, what I will do.

Strange. Show me how do you register the macro and snippet of code from template.

My code:

require __DIR__ . '/Latte/exceptions.php';
require __DIR__ . '/Latte/ILoader.php';
require __DIR__ . '/Latte/IMacro.php';
require __DIR__ . '/Latte/Runtime/IHtmlString.php';
require __DIR__ . '/Latte/Helpers.php';
require __DIR__ . '/Latte/Object.php';
require __DIR__ . '/Latte/Compiler.php';
require __DIR__ . '/Latte/Engine.php';
require __DIR__ . '/Latte/HtmlNode.php';
require __DIR__ . '/Latte/MacroNode.php';
require __DIR__ . '/Latte/Parser.php';
require __DIR__ . '/Latte/PhpWriter.php';
require __DIR__ . '/Latte/Template.php';
require __DIR__ . '/Latte/Token.php';
require __DIR__ . '/Latte/TokenIterator.php';
require __DIR__ . '/Latte/Tokenizer.php';
require __DIR__ . '/Latte/MacroTokens.php';
require __DIR__ . '/Latte/Loaders/FileLoader.php';
require __DIR__ . '/Latte/Loaders/StringLoader.php';
require __DIR__ . '/Latte/Macros/MacroSet.php';
require __DIR__ . '/Latte/Macros/BlockMacros.php';
require __DIR__ . '/Latte/Macros/CoreMacros.php';
require __DIR__ . '/Latte/Runtime/Filters.php';

$template = new Latte\Engine;
$template->setTempDirectory(__DIR__. '/cache/nette/');
$template->onCompile[] = function(Latte\Engine $template) {
    $macroSet = new Latte\Macros\MacroSet($template->getCompiler());
    $macroSet->addMacro('myMacro', "echo 'FOO';", '');
};

$template->render('test.htm', array('test' => 'Hello'));

And my template file (it's pretty simple):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
<head>
	<title>New document</title>
	<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
</head>
<body>

{$test}
{myMacro}

</body>
</html>

This generate error Fatal error: Uncaught exception ‘Latte\CompileException’ with message 'Missing {/myMacro} in…

EDIT: Huh… I found it! Error say Missing {/myMacro}. I'm blind :) When I alter my template to this:

{myMacro}{/myMacro}

it works. But how I create unpaired macro? I need something like this:

{myMacro $param1, $param2}

Latte becomes an alone project. It is great for next development. And I'm curious, why are you upgrading to new Latte API?

I used Nette only for his Latte templating functions. Latte is perfect and amazing :) I needed any handy templating system and I have choose Latte. I spent about 2–3 months (from november 2013) to remade my project for using Latte. Meanwhile David Grudl make a decision not participate to Nette anymore and split its work into small packages.

Only what I need is Latte. That's why I'm trying “new” Latte API. I thought that Latte API will be the same as Nette\Latte, but without too manyy unneccessary files from whole Nette framework :)

Last edited by RadaR (2014-04-09 22:29)

Milo
Nette Core | 1283
+
0
-

RadaR wrote:

{myMacro}{/myMacro}

it works. But how I create unpaired macro? I need something like this:

{myMacro $param1, $param2}
$macroSet->addMacro('myMacro', "echo 'FOO';"); # just ommit 3rd param

I used Nette only for his Latte templating functions. Latte is perfect and amazing :) I needed any handy templating system and I have choose Latte. I spent about 2–3 months (from november 2013) to remade my project for using Latte. Meanwhile David Grudl make a decision not participate to Nette anymore and split your work into small packages.

Only what I need is Latte. That's why I'm trying “new” Latte API. I thought that Latte API will be the same as Nette\Latte, but without too manyy unneccessary files from whole Nette framework :)

I see. When you will solve back compatibility you can check out current Framework source. Framework uses Latte with new API but it leaves some deprecated classes just for BC purpose.

RadaR
Member | 46
+
0
-

Thank you very much, for your time and your help!