Analogie pluginu ve smarty

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
xmn
Člen | 6
+
0
-

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

  1. jako pokusnou komponentu jsem si vybral TagCloud, ktery je ke stazeni tady v diskusi. Je naprogramovan v duchu nette a to vyhovuje.
  2. v bootstrap jsem pridal radek
	NCurlyBracketsFilter::$macros['mod'] = '<?php $presenter->createMod("%%")->render();?>';
  1. 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;
		}
	}
  1. 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
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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á…

Patrik Votoček
Člen | 2221
+
0
-

A nebo mít obalovou komponentu která by volala „sub“ komponentu.

David Grudl
Nette Core | 8228
+
0
-

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.

xmn
Člen | 6
+
0
-

David Grudl napsal(a):

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 by se mělo zjednodušit.

… jak jsme probrali ve Zline ;-)

David Grudl
Nette Core | 8228
+
0
-

Nějak mi to časově nevychází, alespoň tedy příklad rozšiřování $macros