Vlastní makro: Unknown macro
- ludek
- Člen | 83
Zdravím, přepisuju starý projekt z Nette 2.0.8 do 2.4. Používal jsem vlastní makro definované v BasePresenter pro všechny šablony takto:
// Nette 2.0.8
protected function startup() {
$latte = new Nette\Latte\Engine;
$macroSet = new Nette\Latte\Macros\MacroSet($latte->compiler);
$macroSet->addMacro('moje_makro', function($node, $writer) {
// ...
return $writer->write('...'); }
);
$this->template->registerFilter($latte);
parent::startup();
}
Přepsal jsem podle návodu na
// Nete 2.4 / BasePresenter / startup()
use Latte;
$latte = new Latte\Engine;
$set = new Latte\Macros\MacroSet($latte->getCompiler());
$set->addMacro(...);
Na to ale dostanu chybu Unknown macro
.
V návodu není nic o tom, že bych musel ještě vytvořený
$set
nějak předat/registrovat v šabloně? Jestli, tak jak?
Dík.
- Pavel Kravčík
- Člen | 1196
Mně to nejhezčí přijde takhle:
//config.neon
latte:
macros:
- Macros\CustomMacro
//Nějaká třída s makrem
class CustomMacro extends \Latte\Macros\MacroSet
{
/**
* Install macro
*
*/
public static function install(\Latte\Compiler $compiler)
{
$set = new static($compiler);
$set->addMacro('icon', [$set, 'icon']);
return $set;
}
public function icon(\Latte\MacroNode $node, \Latte\PhpWriter $writer)
{
return $writer->write(
'echo \Macros\CustomMacro::renderIcon(%node.word, %node.array)'
);
}
- ludek
- Člen | 83
Pavel Kravčík napsal(a): Mně to nejhezčí přijde takhle…
Díky, toto funguje. Jen je třeba do configu přidat
::install
:
latte:
macros:
- Macros\CustomMacro::install
a do třídy s makrem namespace:
namespace Macros;
Při ladění se taky musí mazat \temp\cache\latte
, protože
při změně makra se nepřegeneruje.
- Pavel Kravčík
- Člen | 1196
Jasně, psal jsem to tak nějak po „paměti“, tak za detaily se omlouvám. To s tou cache je nepříjemné, na to se zasekne každý poprvé.
- ludek
- Člen | 83
Ještě dotaz: jak do třídy s makry dostat proměnné. Např.
$basePath
. Chtěl bych pomocí makra vytvářet odkazy. Např
{mojemakro Popis souboru:soubor.jpg}
se nahradí za
<a href='{$basePath}/obrazky/soubor.jpg'>Popis souboru</a>
.
Ve staré aplikaci jsem to dělal pomocí
$basePath = Nette\Environment::getHttpRequest()->getUrl()->getBasePath();
.
Ale teď nemůžu přijít nato, jak se k tomu dostat, abych to mohl ve funkci
icon
použít.
- David Matějka
- Moderator | 6445
v makru nikdy nepristupuj k runtime promennym. makro vzdy vygeneruje php kod, ktery se pak provede. ty tedy z makra vrat retezec, ve kterem bude neco jako
return $writer->write(
'echo \Macros\CustomMacro::renderIcon($basePath . %node.word, %node.array)'
);
- Pavel Kravčík
- Člen | 1196
Asi by to šlo parametrem, nevím jestli se to dá nějak připojit na DI.
Třeba tu ikonku nahoře pak používáme takhle, takže hádám, že si v parametru pošleš cestu ve chvíli vykreslení…
{icon star, red, 2, $basePath}
EDIT: Matěj je holt bůh, tohle je nesmysl. :)
Editoval Pavel Kravčík (29. 5. 2017 11:03)
- ludek
- Člen | 83
Díky. Takže to jde udělat takto
// šablona:
{mojemakro Popis souboru:soubor.jpg}
// metoda s makrem:
public function mojeMakro(\Latte\MacroNode $node, \Latte\PhpWriter $writer) {
$file = explode(":", $node->args);
return $writer->write('echo "<a href=\'".$basePath."/obrazky/' . $file[1] . '\'>' . $file[0] . '</a>"');
}
Jenže když si přidám test na existenci souboru, stejně to nefunguje, protože šablona se načítá z cache, takže o existenci odkazovaného souboru neví. Nakonec mi funguje toto (testuje existenci, počítá velikost):
public function mojeMakro(\Latte\MacroNode $node, \Latte\PhpWriter $writer) {
$ds = DIRECTORY_SEPARATOR;
$adresar = $ds.'obrazky'.$ds;
$cesta = getcwd().$adresar;
$soubor = explode(":", $node->args);
$komplet = $cesta.$soubor[1];
// PHP kód do šablony:
return '
if (file_exists(\'' . $komplet . '\')) {
echo "<a href=\'" . $basePath . "/obrazky/' . $soubor[1] . '\'>' . $soubor[0] .
' <span class=\'text-muted\'>(" . round((filesize(\'' . $komplet . '\')/1048576),2) . " MB)</span</a>";
}else{
echo "<strong class=\"text-danger\">SOUBOR [' . $soubor[1] .'] NEEXISTUJE</strong>";
}
';
}