Avatar billede reino Nybegynder
18. juni 2009 - 11:50 Der er 7 kommentarer og
1 løsning

Rekursiv menu fra en Accessdatabase

Hej

Står og skal lave en menu på baggrund af udtræk fra en access database, i databasen er der en menuid, menuparent og menutitel

Outputtet skal være som følger:

<div id="smoothmenu-ajax" class="ddsmoothmenu">
<ul>
<li><a href="/">Item 1</a></li>
<li><a href="#">Folder 0</a>
  <ul>
  <li><a href="#">Sub Item 1.1</a></li>
  <li><a href="#">Sub Item 1.2</a></li>
  <li><a href="#">Sub Item 1.3</a></li>
  <li><a href="#">Sub Item 1.4</a></li>
  <li><a href="#">Sub Item 1.2</a></li>
  <li><a href="#">Sub Item 1.3</a></li>
  <li><a href="#">Sub Item 1.4</a></li>
  </ul>
</li>
<li><a href="#">Item 3</a></li>
<li><a href="#">Folder 2</a>
  <ul>
  <li><a href="#">Sub Item 2.1</a></li>
  <li><a href="#">Folder 2.1</a>
    <ul>
    <li><a href="#">Sub Item 2.1.1</a></li>
    <li><a href="#">Sub Item 2.1.2</a></li>
    <li><a href="#">Folder 3.1.1</a>
        <ul>
            <li><a href="#">Sub Item 3.1.1.1</a></li>
            <li><a href="#">Sub Item 3.1.1.2</a></li>
            <li><a href="#">Sub Item 3.1.1.3</a></li>
            <li><a href="#">Sub Item 3.1.1.4</a></li>
            <li><a href="#">Sub Item 3.1.1.5</a></li>
        </ul>
    </li>
    <li><a href="#">Sub Item 2.1.4</a></li>
    </ul>
  </li>
  </ul>
</li>
</ul>
<br style="clear: left" />
</div>

Har prøvet at få ovenstående data ud på baggrund af nedenstående script som har været illustreret af et eagleeyes scripts andetsteds på siden:

<%
set conn = server.CreateObject("ADODB.Connection")
conn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source="& server.mappath("menu2.mdb")

menuID = Replace(Request.QueryString("id"),"'","")
submenuID = Replace(Request.QueryString("sid"),"'","")

SQL = "SELECT * FROM aa_menu ORDER BY id"
Set rs = Conn.Execute(SQL)

menu_target = "MAIN"

do while not rs.EOF
  Response.Write "<a href=""?id=" & rs("id") & """>" & rs("menunavn") & "</a>"
  Response.Write "<br>"
 
  if Int("0" & menuID) = Int(rs("id")) then 
    'Udskriver submenuer til den valgte menu
    Set subrs = Conn.Execute("SELECT * FROM aa_submenu WHERE menuID = " & rs("id"))
    do while not subrs.EOF
      Response.Write " - <a href=""?id=" & rs("id") & "&sid=" & subrs("id") & """>" & subrs("submenunavn") & "</a>"
      Response.Write "<br>"
      if Int("0" & submenuID) = Int(subrs("id")) then 
        'Udskriver links til den valgte menu og submenu
        Set linksrs = Conn.Execute("SELECT * FROM aa_link WHERE submenuID = " & rs("id"))
        do while not linksrs.EOF
          Response.Write " -- <a href=" & linksrs("linket") & " target=" & linksrs("target") & """>" & linksrs("linknavn") & "</a>"
          Response.Write "<br>"
          linksrs.Movenext
        loop   
      end if
      subrs.Movenext
    loop   

    'Udskriver links til den valgte menu som ikke har en submenu
    Set subrs = Conn.Execute("SELECT * FROM aa_link WHERE menuID = " & rs("id"))
    do while not subrs.EOF
      Response.Write " -- <a href=" & subrs("linket") & " target=" & subrs("target") & """>" & subrs("linknavn") & "</a>"
      Response.Write "<br>"
      subrs.Movenext
    loop   

  end if

  rs.Movenext
loop

Conn.Close
Set Conn = nothing
%>

Har nu brugt dage på at finde en løsning og har fundet ud af det nok skal være en rekursiv funktion der skal bruges. Er der evt. nogen der skulle have et ex. på dette ?
Avatar billede softspot Forsker
18. juni 2009 - 12:16 #1
Rekursion lyder som en løsning der vil fungere, men en hierarkisk menu er lidt kompleks at udtrække fra en relationel database og dermed også tids- og resursekrævende for serveren (der skal bruges mange opslag i databasen for at få det til at fungere). Jeg vil umiddelbart foreslå en optimering (via caching i en separat tabel).

Hvor ofte ændrer menuen sig?

Er det muligt for dig at regenerere cachen når menuen ændrer sig?

Hvis du cacher den kan du sørge for at menupunkterne ligger i den rækkefølge de skal genereres i, så du kan nøjes med at lave et "fladt udtræk" af cachetabellen og blot iterere igennem alle de udtrukne punkter. Til dette skal du bruge en eller anden indikator for orden og niveau. Jeg forestiller mig et felt som angiver dette med bogstaver, f.eks.

a
aa
ab
aba
abb
ac
b
ba
bb
c
ca
caa
cab

menupunkternes rækkefølge kan dermed ordnes med en simpel order by og niveauet kan aflæses i længden af feltet.

Du skal som nævnt have mulighed for at opdatere cachen når menuen ændrer sig og til dette slipper du ikke for at bruge en masse resurser - men det er forhåbentlig kun få gange i forhold til hvor ofte menuen skal vises :-)
Avatar billede softspot Forsker
18. juni 2009 - 12:19 #2
Et andet godt alternativ til caching er naturligvis XML evt. i kombination med XSLT, men det er givetvis for stor en mundfuld at kaste så mange "nye" teknikker ind i denne opgave :-)

Hvis ikke så sig endelig til, så må vi se om vi kan finde en teknisk løsning på det! :-)
Avatar billede softspot Forsker
18. juni 2009 - 12:40 #3
På den anden side, hvis du nu bare, for hvert menupunkt, beskrev strukturen ("forfædrestien") med den foreslående metode i stedet for kun at angive den umiddelbare forælder, kunne du spare cachingen og bare lave udtrækket som foreslået direkte på menuen.

Dette vil naturligvis kræve, at du på det tidspunkt hvor du opretter menupunktet kender

* forældernodens "forfædresti"
* ved hvilken placering menupunktet skal have i menuen

men hvis du har styr på det, når menupunktet gemmes, så burde udtrækket være ligetil... :-)
Avatar billede softspot Forsker
20. juni 2009 - 00:18 #4
Hvad så reino, kom du videre med det?
Avatar billede reino Nybegynder
24. juni 2009 - 10:19 #5
Hejsa,

nopes, har blot været lidt borte men er tilbage på pinden :)

XML kunne også være en mulighed, men vil stadigvæk have det samme problem med ul og li :)

I databasen har jeg felterne:

id, order og parent

Så disse værdier har jeg :)
Avatar billede softspot Forsker
24. juni 2009 - 10:35 #6
Du er nok nød til at uddybe lidt, for med XML kan du vedligeholde strukturen i din menu og praktisk talt lave menuen i XML, så det kan vel ikke give nogle problemer...

Mht. hvilke felter du har i databasen, så er jeg klar over at du har de felter du skal bruge for at beskrive strukturen, det jeg foreslår er blot udvidelse af datagrundlaget med henblik på en optimering af hvordan du genererer menuen (det er klart hurtigere at lavet ét gennemløb af ét udtræk end at lave adskillige udtræk i rekursion. Det var derfor jeg foreslog at du introducerede et felt du kunne sortere efter og som gav information om både struktur og sekvens (med mindre feltet order et en global orden for alle menupunkter, for så kan du vel bare sortere efter det).
Avatar billede reino Nybegynder
11. september 2009 - 12:02 #7
Heps, så er jeg tilbage igen på pinden :)

Har lavet et ekstra felt nu, der hedder zorder som definerer rækkefølgen på menupunkterne på den respektive level. Skulle dette hjælpe og i så fald hvordan ?

Faldt over denne artikel, men det ser noget rodet ud :)

http://rwstewart.wordpress.com/2009/01/31/classic-asp-database-driven-list-menu/
Avatar billede reino Nybegynder
03. marts 2010 - 06:45 #8
Lukker og slukker , prøver noget array ting istedet , men tak for hjælpen :)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester