#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.


$this->terminate();

http://twitter.com/TomasKavalek

Offline

 

#4 9. 2. 2010 16:31

srigi
Člen
Místo: BA
Registrovaný: 6. 1. 2009
Příspěvky: 144
Web

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

srigi
Člen
Místo: BA
Registrovaný: 6. 1. 2009
Příspěvky: 144
Web

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

srigi
Člen
Místo: BA
Registrovaný: 6. 1. 2009
Příspěvky: 144
Web

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

 

Zápatí