#1 9. 2. 2010 12:01
- Peetee
- Člen
- Registrovaný: 1. 2. 2010
- Příspěvky: 10
Šablony: Traverzování kolem stromu
Ahoj,
pokouším se v šabloně vypsat strom, který vznikl metodou Traverzování kolem stromu. Takže je seřazený a má proměnou hloubka, která určuje zanoření položky – více v části s „Výpis stromu do seznamu s odrážkami“ – chtěl bych to vypsat přesně do stromu s odrážkami
Chci zeptat, jestli je to dobrý nápad – jestli je dobrý nápad sestavovat takto strom v šabloně.
Pokoušel jsem se upravit příklad z Dědičnost bloků – konkrétně:
{block #menu}
<ul>
{foreach $menu as $item}
<li>{if is_array($item)} {include #menu, 'menu' => $item} {else}{$item}{/if}</li>
{/foreach}
</ul>
{/block}
Ale tam mi přijde zbytečné transformovat to pole menu, aby jednotlivé položky byly zase pole menu a ty by byly taky pole atd… když už to mám takle pěkně seřazený…
Moc děkuju za každej nápad.
Offline
#2 9. 2. 2010 12:43
- Ondřej Mirtes
- Moderator

- Místo: Praha
- Registrovaný: 8. 1. 2009
- Příspěvky: 1357
- Web
Re: Šablony: Traverzování kolem stromu
Před nějakou dobou jsem v Nette taky traverzování kolem stromu dělal, taky na základě článku Jakuba Vrány. A pokud se nemýlím, tak tato metoda stromového výpisu je výjimečná právě tím, že se nevypisuje rekurzivně.
Myslím, že v této metodě by se vnořování v <ul> dalo zajistit detekcí změny hloubky oproti předchozí položce a na základě toho vypsat nějaké ukončování <ul> (vnořeného) a <li>… Bude to chtít trochu přemýšlení a experimentování, aby výsledek byl vždy validní, ale půjde to.
Offline
#3 9. 2. 2010 13:35
- toka
- Člen

- Místo: Kostelec nad Orlicí
- Registrovaný: 5. 8. 2009
- Příspěvky: 173
Re: Šablony: Traverzování kolem stromu
Experimentoval jsem takto dlouho, když jsem chtěl vypsat do šablony
sitemap, a musím říct, že jsem byl tak netrpělivý a
rozladěný výsledkem a nechtělo se mi nad tím myslet, půl páté ráno, že
jsem se na to vykašlal :-) Ale zamínkou bylo vypsat nejen seznam, správně
zanořený, což mi funguje, ale i mít možnost udělat odkazy – tedy
každý prvek je pole. Šel jsem na to tak, že jsem přidal do pole klíč
hasChild a podle něho chtěl ověřovat následnou potřebu
volání rekurze, či nikoliv, ale ještě jsem to nedokončil. Proto bych se
rád seznámil s Vaším řešením, pokud to není tajemství :-) Díky.
Offline
#4 9. 2. 2010 16:31
Re: Šablony: Traverzování kolem stromu
Robim teraz na niecom, kde sa „Nested set“ pouziva a mam to celkom pekne vyriesene. Ako Model pouzivam Doctrine a ten Nested set podporuje nativne nad tabulkou. Ked si „fetchnem“ cely jeden strom, tak mi Model vrati cca toto:
Array
(
[id] => 23
[root_id] => 22
[lft] => 2
[rgt] => 9
[level] => 1
)
Array
(
[id] => 27
[root_id] => 22
[lft] => 3
[rgt] => 4
[level] => 2
)
Array
(
[id] => 28
[root_id] => 22
[lft] => 5
[rgt] => 6
[level] => 2
)
Array
(
[id] => 29
[root_id] => 22
[lft] => 7
[rgt] => 8
[level] => 2
)
Array
(
[id] => 24
[root_id] => 22
[lft] => 10
[rgt] => 15
[level] => 1
)
Array
(
[id] => 30
[root_id] => 22
[lft] => 11
[rgt] => 12
[level] => 2
)
Array
(
[id] => 31
[root_id] => 22
[lft] => 13
[rgt] => 14
[level] => 2
)
Array
(
[id] => 25
[root_id] => 22
[lft] => 16
[rgt] => 17
[level] => 1
)
Array
(
[id] => 26
[root_id] => 22
[lft] => 18
[rgt] => 19
[level] => 1
)
Doctrine umoznuje viac stromov v jednej tabulke, root nodu vynechavam, lebo by mi svietila ako rodic nultej urovne a ak by som kcel vytvorit jej ‚sibling‘, musel by som robit novy strom.
Nody su uz usporiadane a ako vidno nie su ulozene rekurzivne (vid. vyssie Ondrej). Na ich vykreslenie pouzivam takuto sablonu:
<ul>
{? $temp = 1; }
{foreach $tree as $node}
{if $node->level > $temp}
<ul>
{? $temp = $node->level;}
{elseif ($node->level == $temp) && (!$iterator->isFirst())}
</li>
{elseif $node->level < $temp}
</li></ul></li>
{? $temp = $node->level;}
{/if}
<li><a href="{plink Foo:bar 'id'=>$node->id}">{$node->name}</a>
{/foreach}
</li>
</ul>
Generuje to validny HTML kod cca:
<ul>
<li>
<a href="">Node name</a>
<ul>
<li><a href="">Subnode name</a></li>
...
</ul>
</li>
...
cize vnorene UL je „zakomponovane“ este v nadradenom LI, tak ako som to
potreboval (a ako je to spravne podla W3C). Sablona si do
$temp uklada aktualny level a v jednotlivych
iteraciach sa if podmienka pozera, ci level klesa, stupa alebo je
bez zmeny a podla toho renderuje. Pouzivam tam este premennu
$iter aby sa mi hned po v prvej iteracii nevyrenderovalo
uzatvaracie </li>, toto treba trocha zrefaktorovat a vyuzit
ten iterator, co je ako pomocna premenna v loopoch v sablonach.
Inak ked som hladal tuto vec po nete, nasiel som, ze ludia zo Symfony a Propel renderuju Nested set uplne rovnako (odkladaju si level do docasnej premennej), takze je toto riesenie IMO spravne. enjoy.
Edit: este pripomeniem, ze tato sablona umoznuje renderovat strom neobmedzenej hlbky, nie len do druhej urovne ako je v ukazke vyssie (je to len priklad). Okrem tohom nody v mojom priklade su objekty, nie len polia, preto na nich mozem volat rozne pomocne metody potrebne k renderu. Priklad je ale IMHO dostatocne zrozumitelny.
Editoval srigi (9. 7. 2010 6:45)
developing on Arch linux, Apache 2.2.15, PHP-5.3.2 (mod_php5), Mysql 5.1.47 :: www.twitter.com/srigi
Offline
#5 9. 2. 2010 23:41
- Vyki
- Nette guru

- Místo: Liberec & Plzeň
- Registrovaný: 12. 7. 2009
- Příspěvky: 246
Re: Šablony: Traverzování kolem stromu
Já osobně používám základní myšlenku tohoto: http://forum.dibiphp.com/…34-fetchtree. Je to rekurzivní
tvoření stromu (pole) dle záznamů z DB na základě vztahu $id
a $parent_id. Jsou tam velmi pěkně použity reference polí.
Celý ten strom si ukládám do cache aby to vždy při tvoření menu nemuselo
sahat do DB. Pro vypisování toho menu potom také používám ten příklad
z dědičnosti bloků.
Offline
#6 10. 2. 2010 1:01
- Ani
- Člen

- Místo: Praha
- Registrovaný: 2. 2. 2009
- Příspěvky: 65
Re: Šablony: Traverzování kolem stromu
Trochu to tu zneužiju. Můžu se jen zeptat, proč všichni vypisujete tyhle menu do <ul> <li>, snad jedině, že to jsou značky na seznam? Já to vždycky řešim jen jako normální odkazy, který si upravím pomocí css a .depth1, .depth2… Dělám něco špatně?
Jinak já si celý menu z db tahám jako ->fetchAssoc(‚parent_id,id‘) a to pak projedu poměrně jednoduchou i docela rychlou rekurzivní funkcí. A vykreslení už je jednoduchý, přes foreach.
Editoval Ani (10. 2. 2010 1:15)
Offline
#7 10. 2. 2010 1:42
Re: Šablony: Traverzování kolem stromu
Ani napsal(a):
Trochu to tu zneužiju. Můžu se jen zeptat, proč všichni vypisujete tyhle menu do <ul> <li>, snad jedině, že to jsou značky na seznam?
Ide o to, že strom vyrenderovany do UL-LI zoznamu sa ti vykresli ako strom aj pri vypnutom stylovani. Tvoje riešenie IMO zlyha (z vizualnej stránky veci) pri vypnutom CSS. A navyše je renderovanie do UL-LI nezávisle na hĺbke stromu. Ty ak vo svojej metode nepripravys štýly pre hĺbku 5 a viac, tak už paturovnove menu sa nebude vykreslovat správne. A okrem toho je to semantickejsie ako nejaké ahref-y v dive.
developing on Arch linux, Apache 2.2.15, PHP-5.3.2 (mod_php5), Mysql 5.1.47 :: www.twitter.com/srigi
Offline
#8 8. 7. 2010 21:51
- iguana007
- Nette guru

- Místo: Praha
- Registrovaný: 3. 11. 2009
- Příspěvky: 265
Re: Šablony: Traverzování kolem stromu
Ahoj srigi, prosimte, mel bych na tebe dotaz, pokousel jsem se implementovat tvuj priklad (http://bit.ly/bAVvlc) tykajici se nested set. Jde mi o to, ze mam v databazi nested strom odkazu, z ktereho bych rad vykreslil UL>LI dropdown menu. Myslim, ze jsem vse pochopil spravne, ale narazil jsem na error, ktery na me pri renderu menu vyskoci: Call to undefined method DibiRow::getActive() Predpokladam, ze to po me bude chtit i ty dalsi metody z sablony, mohl by si mi prosim popsat, co tyto metody maji presne delat? Diky moc za kazdou radu.
Omne Principium Grave
Offline
#9 9. 7. 2010 6:37
Re: Šablony: Traverzování kolem stromu
iguana007 napsal(a):
Ahoj srigi, prosimte, mel bych na tebe dotaz, pokousel jsem se implementovat tvuj priklad (http://bit.ly/bAVvlc) tykajici se nested set. Jde mi o to, ze mam v databazi nested strom odkazu, z ktereho bych rad vykreslil UL>LI dropdown menu. Myslim, ze jsem vse pochopil spravne, ale narazil jsem na error, ktery na me pri renderu menu vyskoci: Call to undefined method DibiRow::getActive() Predpokladam, ze to po me bude chtit i ty dalsi metody z sablony, mohl by si mi prosim popsat, co tyto metody maji presne delat? Diky moc za kazdou radu.
Hello, ide o to, ze som ten svoj priklad neocistil – pri vykreslovani LIcka si vsimni, ze je zistovanie „aktivnosti“. Len to vyhod z kodu a pojde ti to.
ide o to, ze ja som do View sablony predaval tzv. Doctrine_List co je hentamto pole – v skutocnosti su to objeky Doctrine_Record, ktore je mozne previest na pole. No a ja som ich rozsiril o metodu getActive()
Sypem si popol na hlavu
edit: upravil som povodny prispevok. Kod je tam upraveny (ocisteny), je tam pouzity aj ten $iterator, takze si to updatnite.
Editoval srigi (9. 7. 2010 6:47)
developing on Arch linux, Apache 2.2.15, PHP-5.3.2 (mod_php5), Mysql 5.1.47 :: www.twitter.com/srigi
Offline
#10 9. 7. 2010 10:40
- iguana007
- Nette guru

- Místo: Praha
- Registrovaný: 3. 11. 2009
- Příspěvky: 265
Re: Šablony: Traverzování kolem stromu
Super! :o) uz to bezi … diky moc … ;o)
Omne Principium Grave
Offline


