Analogie pluginu ve smarty
- xmn
- Člen | 6
Zdravim vlky, pokousime se proniknout do nette a zalozit na nem nas novy redakcni system. Stavajici je zalozen, mimo jine na smarty ve kterem hojne pouzivame pluginy jakozto samostatne komponenty, ktere nezavisi na „hlavnim“ presenteru (napr anketa, vytahy z rubrik, zobrazovane napric celym webem v pravem sloupecku a pod.). Domnival jsem se, ze podobna funkcionalita jsou makra v CurlyBracketsFilter-u nicmene se mi nedari toto zprovoznit. Postupuju nasledovne
- jako pokusnou komponentu jsem si vybral TagCloud, ktery je ke stazeni tady v diskusi. Je naprogramovan v duchu nette a to vyhovuje.
- v bootstrap jsem pridal radek
NCurlyBracketsFilter::$macros['mod'] = '<?php $presenter->createMod("%%")->render();?>';
- vytvoril jsem si BasePresenter a v nem metodu createMod, ktera se postara o vytvoreni a vraceni komponenty
function createMod($param){
list($cname,$cparams) = explode(' ',$param,2);
switch($cname){
default:
$arr = explode(',',$cparams);
$pole = array();
foreach($arr as $a){
list($i,$f) = explode(':',$a);
$pole[$i] = $f;
}
$c = new $cname();
if(!is_null($cparams))$c->setData($pole);
return $c;
break;
}
}
- v sablone, kde chci zobrazit data komponenty zadam kod
{mod tagCloud Auto:1,Letadlo:3,Slon:5}
metoda createMod se postara o rozparsovani parametru a spravnou aktivaci
komponenty
5)komponenta TagCloud pouziva taktez CurlyBracketsFilter a objekt temlate
ziskava v metode render pres $this->createTemplate(); registruje potrebny
filter, zavola render nad sablonou … a dojde k vyjimce, ze ktere vyplyva, ze
v aktualnim kontextu neexistuje $presenter … ktery je nutny pro
sestaveni linku
$presenter->link('Article:', array(array('tag' => $tag->url)))
je ta cast, kde dojde k havarii.
Z toho vyplyva, ze jsem zrejme zvolil spatnou cestu. Existuje tedy v nette nejaka analogie smarty pluginu?
Dik za info,
M.
- jasir
- Člen | 746
xmn napsal(a):
<?php function createMod($param){ list($cname,$cparams) = explode(' ',$param,2); switch($cname){ default: $arr = explode(',',$cparams); $pole = array(); foreach($arr as $a){ list($i,$f) = explode(':',$a); $pole[$i] = $f; } $c = new $cname(); if(!is_null($cparams))$c->setData($pole); return $c; break; } } ?>
Podle mě je chyba tady: $c = new $cname()
, komponenta musí
být připojená k presenteru
pokud chce používat link()
. Mělo by tam být buď
<?php
$c = new $cname($name,$this);
?>
anebo přidat komponentu do stromu takto:
<?php
$c = new $cname();
$this->addComponent($name,$c);
?>
Chce to tedy tu komponentu ještě pojmenovat, to jest naplnit to
$name
(třeba čítač komponent ve statické proměnné),
třeba tak:
<?php
function createMod(...)
static $created = array();
if(isset($created[$cname])) {
$created[$cname] = $created[$cname]+1;
} else {
$created[$cname] = 1;
}
$name = $cname . $created[$cname];
...
?>
Jednu věc by jsi ale měl zvážit – tímto způsobem se komponenta připojí (a vytváří) až v render fázi, čili nemůže být příjemcem signálů.
Editoval jasir (3. 6. 2009 13:51)
- Patrik Votoček
- Člen | 2221
Ještě bych to řešení malinko doplnil/upravil a v presenteru v metodě
createComponent($name)
:
public function createComponentTagCload($name)
{
return new TagCload();
}
A šablona by to přeložila na toto:
$presenter['tagCload']->render($params);
Je jesné že pak musís upravit i samotnou komponentu.
Nevím jestli je to pochopitelné. Kdyby něco tak piš.
- xmn
- Člen | 6
Parada – rada pomohla, stacilo komponentu zaregistrovat :-* Jinak k te namitce, ze komponenta vznikne v okamziku renderovani a nebude mit moznost prijimat signaly – vubec to nevadi (prozatim), spise jsem nenasel zpusob jak to udelat. Jde mi o to abych mel moznost vkladat do stranky moduly pouze pres sablonu – muze to udelat „sablonar/designer“ , neni k tomu treba asistence programatora a zmena kodu. A dopredu aktivovat kod, ktery nebude vyuzit se mi take nezda jako rozumne. Je na toto nejaky jiny zpusob?
- nAS
- Člen | 277
To co popisuješ ty jsou aktivní šablony. Tedy, že se nejprve parsují šablony a podle nich se volá příslušný kód. V Nette jsou naopak šablony pasivní, tzn. že se nejprve provede kód a ten se doplní do šablon.
Pokud bys opravdu potřeboval tuto funkčnost, tak můžeš zaregistrovat všechny připravené komponenty třeba v BasePresenteru a jejich funkčnost provádět v metodě, která se bude volat přímo ze šablony. Ale moc čisté mi to nepřipadá…
- David Grudl
- Nette Core | 8228
Připravím na toto téma obsáhlejší článek, ale asi až po víkendu.
Každopádně k řešení podobné situace bude sloužit makro
{control ...}
a rozšiřování
NCurlyBracketsFilter::$macros
NCurlyBracketsMacros::$defaultMacros
by se mělo zjednodušit.
- David Grudl
- Nette Core | 8228
Nějak mi to časově nevychází, alespoň tedy příklad rozšiřování $macros