Rekurze v šabloně se zacyklí

- Pan Dobrman
 - Člen | 45
 
Dobrý den, snažil jsem se převést tento kód do šablony:
	private function buildTree($parent2 = null)
	{
		foreach($this->menu as $name => $parent)
		{
			if($parent == $parent2)
			{
				echo $name;
				$this->buildTree($name);
			}
		}
	}
{block #menu}
	{var $parent2 = null}
	{foreach $menu as $name => $parent}
		{if $parent == $parent2}
			{$name}
			{include #this, parent2 => $name}
		{/if}
	{/foreach}
{/block}
V php vše funguje v pořádku, jen v latte se zacyklí a vyhodí výjimku „Maximum function nesting level of ‚100‘ reached, aborting!“. Kde jsem udělal chybu?
Editoval Pan Dobrman (17. 7. 2012 22:08)

- Pan Dobrman
 - Člen | 45
 
Bylo by možné v latte vytvořit, aby všechny poslední položky v každé větvi menu byly tučným písmem? Například takto:
- Menu 1
		
- Submenu 1
				
- Subsubmenu 1
 
 - Submenu 2
 
 - Submenu 1
				
 - Menu 2
 
Pokusil jsme se použít makro last, ale to mi vždy označí tučným písmem jen poslední položku z úplně poslední větve (v příkladu položku „Submenu 2“).
{var $parent2 = null}
{block #menu}
        {foreach $menu as $name => $parent}
                {if $parent == $parent2}
                        {last}<strong>{/last}{$name}{last}</strong>{/last}
                        {include #this, parent2 => $name}
                {/if}
        {/foreach}
{/block}
Byl bych moc vděčný za radu. Děkuji
Editoval Pan Dobrman (18. 7. 2012 15:55)

- vvoody
 - Člen | 910
 
Ty mas v $menu vsetky polozky a vzdy prechadzas uplne vsetky takze last moze byt len jedno. Mozno by si mohol vyuzit css selector :last-child alebo to menu poskladat este niekde popredu v modely a potom ho uz len takto vypisat s tym ze uz nebudes hladat vo vsetkych jeho polozkach, alebo do tretice :D ak to menu mas v DB tak to ide aj priamo s tym ze staci vlozit do sablony len selection na menu polozky s parentom NULL.

- Pan Dobrman
 - Člen | 45
 
Děkuji za odpověď. Já měl za to, že pokud procházím pomocí rekurze, takže budu moci uplatnit makro last na více položek. Selector „:last-child“ by pro mě byl ideální, ale zjistil jsem, že bych potřeboval přidat ještě odkaz na vytvoření nové položky (což musím řešit v šabloně, protože přes css to nejspíše neudělám). V modelu jsem to nechtěl skládat, protože mi přijde čistější to udělat až v šabloně. Je něco takového možné v latte? Už se o to snažím skoro dvě hodiny, ale né a né na to přijít :).

- Pan Dobrman
 - Člen | 45
 
Data mám předpřipravené tak, že při požadavku se mi vrátí pole ve tvaru ‚název‘ ⇒ ‚rodič‘. Pokud jsem vás správně pochopil, tak bych měl ke zpracování do šablony odeslat vždy jen jednu hlavní větev? např.:
1. cyklus
- Menu 1
		
- SubMenu 1
				
- SubSubMenu 1 #nebude označeno jako last
 
 - SubMenu 2 #last
 
 - SubMenu 1
				
 
2. cyklus
- Menu 2 #last
 

- Pan Dobrman
 - Člen | 45
 
Mockrát děkuji za vás nápad. Výsledek vypadá takto (kód je ošklivý, psal jsem ho narychlo):
Komponenta:
	public function render()
	{
		$return = array();
		$this->generateTree($this->menu, null, $return);
		$this->template->menu = $return;
		$this->template->render();
	}
	private function generateTree($menu, $_parent = null, &$return)
	{
		foreach($menu as $name => $parent)
		{
			if($_parent == $parent)
			{
				$return[$name] = null;
				unset($menu[$name]);
				$this->recurse($menu, $name, $return[$name]);
			}
		}
	}
Latte:
{var $_menu = $menu}
{block #menu}
	<ul> /* Zatím nefunguje */
	{foreach $_menu as $name => $parents}
				<li>
					{$name}
					{if $parents != null}
						{include #this, _menu => $parents}
					{else}
						Přidat novou položku
					{/if}
				</li>
	{/foreach}
	</ul>
{/block}
					Editoval Pan Dobrman (18. 7. 2012 19:16)

- Pan Dobrman
 - Člen | 45
 
Výstup není úplně podle mé představy, protože mám problémy s tagem <ul>. Chápete to správně, ale pokud vyměním makro else za last, tak se text „Přidat novou položku“ vypíše 2× (s else funguje vše jak má). Menu tahám z databáze jako pole ve tvaru: ‚název‘ ⇒ ‚rodič‘, poté ho přes funkci generateTree změním na:
array(2) {
   "Menu 1" => array(2) {
      "SubMenu 1" => array(1) {
         "SubSubMenu 1" => NULL # 'název' => 'rodič'
      }
      "SubMenu 2" => NULL
   }
   "Menu 2" => NULL
}
				
- vvoody
 - Člen | 910
 
Aky problem s tagom ul?
Ak pouzivate Nette/Database tak by bolo mozno lepsie riesenie z tohto vlakna.

- Pan Dobrman
 - Člen | 45
 
Bohužel, používám Doctrine 2. Problém s tagem je, že jsem ho nejspíše špatně umístil :), takže se to pokusím přepsat a doufám, že poté už bude vše v pořádku.

- kbtm
 - Člen | 22
 
Přeji dobrý den,
nechci zakládat nové vlákno, proto se ptám na možnost řešení stejné
chyby (Maximum function nesting level of ‚100‘ reached, aborting!) …
Aplikaci (seznamuji se s některými komponentami, problém je u komponenty
Menu od autora Murdej) zkouším pod několika prohlížeči – ale chyba se
objeví jen pod Firefoxem – v IE, Opeře a Chrome je vše OK.
Testuji na lokálu (WinXP + WampServer).
Pokud zkusím pustit testovací aplikaci „venku“ (http://menu.nette.murdej.cz/), je vše OK i pod
Firefoxem.
V prohlížeči jsou vyprázdněny všechny cache (tedy alespoň si myslím
…), pokud do aplikace úmyslně zavleču nějakou chybu (třeba změním
název třídy), je tato chyba správně ohlášena – tj. chybové hlášení
se změní.
Chyba se neprojevovala hned zpočátku – až po několika změnách aplikace.
Nyní ale zůstává stejná i při návratu k „originálu“ (modul
Menu.php, na řádce 179 :
178: public function Add($node) {
179: if (is_array($node)) {
180: $newNode = new MenuNode;
S pozdravem kbtm