Avatar billede exp Juniormester
20. august 2004 - 00:00 Der er 18 kommentarer og
1 løsning

Jeg giver op; hjælp til at generere punktliste, med underpunkter

Jeg har nu i et par dage prøvet at få lavet en eller anden form for funktion, der ka generere en unordered list (<ul>) ud fra nogle rækker i en mysql-tabel

Tabellen ser sådan ud:
CREATE TABLE `hbp_pages` (
  `id` int(1) NOT NULL auto_increment,
  `menu` int(11) NOT NULL default '0',
  `menu_text` varchar(30) NOT NULL default '',
  PRIMARY KEY  (`id`)
);

ID er primær nøgle, og er unik for hver række
MENU er lig med parentID, altså den række der er forælder til den aktive række
MENU_TEXT indeholder den tekst der skal stå i listen


Et bud på et output kunne være (id i parantes):
- header 1 (1)
    - subheader 1 (4)
    - subheader 2 (5)
- header 2 (2)
    - subheader 3 (6)
          - sub-subheader 1 (10)
          - sub-subheader 2 (11)
              - sub-sub-subheader 1 (12)
    - subheader 4 (7)
- header 3 (3)
    - subheader 5 (8)
    - subheader 6 (9)

Idéen er, at der kan komme uendeligt mange underpunkter, og det skal der tages højde for i scriptet...

For at gøre det endnu værre, så skal det være sådan, at jeg via en funktion skal kunne starte hvor som helt i strukturen, så fx function(6) viser:

- subheader 3 (6)
          - sub-subheader 1 (10)
          - sub-subheader 2 (11)
              - sub-sub-subheader 1 (12)

Nogen der kan kringle den?
Avatar billede mjense173 Nybegynder
20. august 2004 - 00:12 #1
Har du prøvet med rekursion?
Avatar billede exp Juniormester
20. august 2004 - 00:21 #2
Ja, det har jeg, men kan ikke få det til at virke :-/

Kan slet ikke finde ud af de der rekursive funktioner... har sågar prøvet at følge nogle tutorials, men der ender altid med noget der enten ikke virker ordentligt, eller virker, men absolut, overhovedet ikke til det jeg skal bruge... derfor spørger jeg nu her :-)
Avatar billede dennismp Nybegynder
20. august 2004 - 00:27 #3
<?php
getMenu();
getMenu(3);

function getMenu($rootId=0,$topLevel=true) {
    static $items = null;

    if( $items == null  )  {
        // Load everything
        $sql = "SELECT id, menu as parent_id, menu_text FROM hbp_pages ORDER BY menu_text";

        $res = mysql_query($sql) or die(mysql_error());

        while($row = mysql_fetch_assoc($res))
            $items[$row['id']] = $row;
    }

    if( $rootId != 0 && $topLevel) {
        print "<ul>";
        print '<li>'.$items[$rootId]['menu_text'].'</li>';
    }

    $noOutput = true;

    foreach(array_keys($items) as $i ) {
        if( $items[$i]['parent_id'] == $rootId ) {
            if( $noOutput )  {
                $noOutput = false;
                print '<ul>';
            }
            print '<li>'.$items[$i]['menu_text'];
            getMenu($items[$i]['id'],false);
            print '</li>';
        }
    }

    if(! $noOutput )
        print "</ul>";

    if( $rootId != 0 && $topLevel ) {
        print "</ul>";
    }
}
?>
Avatar billede dennismp Nybegynder
20. august 2004 - 00:30 #4
Så vidt jeg kan se, er der to muligheder;

1) Man loader alle data af een omgang
2) Man loader data efter behov.. Flere omgange..

Jeg valgte nummer 1 - da jeg mente at det ekstra arbejde mysql udsættes for er så lille, at det kan svare sig. Jeg mener, så mange rækker i menu-tabellen får du vel heller ikke - og da rækkerne alligevel er små, så burde det ikke være et problem. Uden at vide det, så tror jeg næsten at mange queries ville tage længere tid, med det ekstra overhead der er pr. query. Men det er spekulation - ikke  noget jeg har målt på.

Men da du ikke havde krav om dette, så tog jeg en rask beslutning :)
Avatar billede exp Juniormester
20. august 2004 - 09:16 #5
Det er ikke urealistisk, at der på et tidspunkt skal genereres en liste på over 1000 punkter, men lige nu er dette rigeligt.

I givet fald vil jeg overveje en optimering...


Tusind mange tak for hjælpen :-D
Avatar billede exp Juniormester
20. august 2004 - 11:03 #6
Lige et kort tillægsspørgsmål:

Hvis jeg vil have at den første (og kun den første) <ul> får et ID, således at den kommet til at se sådan ud:
<ul id="noget">

hvordan gør jeg så det?


Har prøvet med:
function getMenu($rootId=0,$topLevel=true) {
    $topul = true;

    static $items = null;

    if( $items == null  )  {
        // Load everything
        $sql = "SELECT id, menu as parent_id, menu_text FROM hbp_pages ORDER BY menu_text";

        $res = mysql_query($sql) or die(mysql_error());

        while($row = mysql_fetch_assoc($res))
            $items[$row['id']] = $row;
    }

    if( $rootId != 0 && $topLevel) {
    if ($topul=true) {
        print "<ul id=\"noget\">";
        $topul = false;
    } else {
        print "<ul>";
        $topul = false;
    }
        print '<li>'.$items[$rootId]['menu_text'].'</li>';
    }

    $noOutput = true;

    foreach(array_keys($items) as $i ) {
        if( $items[$i]['parent_id'] == $rootId ) {
            if( $noOutput )  {
                $noOutput = false;
                if ($topul=true) {
            print "<ul id=\"noget\">";
            $topul = false;
        } else {
            print "<ul>";
            $topul = false;
        }
            }
            print '<li>'.$items[$i]['menu_text'];
            getMenu($items[$i]['id'],false);
            print '</li>';
        }
    }

    if(! $noOutput )
        print "</ul>";

    if( $rootId != 0 && $topLevel ) {
        print "</ul>";
    }
}


hvor jeg med en simpel if-sætning burde kunne løse det:
    if ($topul=true) {
        print "<ul id=\"noget\">";
        $topul = false;
    } else {
        print "<ul>";
        $topul = false;
    }

men det glipper :-(
Den sætter alle <ul> til <ul id="noget">...
Avatar billede dennismp Nybegynder
20. august 2004 - 11:07 #7
if ($topul=true) {

du mener da vel
if ($topul==true) {
Avatar billede dennismp Nybegynder
20. august 2004 - 11:10 #8
Og jeg tror du skal if()'en i foreach løkken til:
if ($topul && $toplevel) {


Da den første jo nødvendigvis må findes i $toplevel, da denne er kun sand i øverste niveau. Ellers vil den nok finde den første i hvert niveau.
Avatar billede exp Juniormester
20. august 2004 - 13:47 #9
hmm... den udskriver ikke valid kode :-(

http://validator.w3.org/check?uri=http%3A%2F%2Fcoolcms.1go.dk%2Frekursiv.php&charset=iso-8859-1+%28Western+Europe%29&doctype=HTML+4.01+Strict

Den putter <ul> ind imellem <li></li> og det er ikke korrekt...
Avatar billede dennismp Nybegynder
20. august 2004 - 14:18 #10
ret:
            print '<li>'.$items[$i]['menu_text'];
            getMenu($items[$i]['id'],false);
            print '</li>';

til
            print '<li>'.$items[$i]['menu_text'] . '</li>';
            getMenu($items[$i]['id'],false);
Avatar billede exp Juniormester
20. august 2004 - 14:34 #11
:-D

Så mangler jeg kun at få løst problemet med <ul id="noget"> - der tilføjer den stadig id="noget" til alle <ul>'er... :-(
Avatar billede dennismp Nybegynder
20. august 2004 - 14:49 #12
Gider du at poste koden igen - så jeg arbejder på samme kode som du har :)
Avatar billede exp Juniormester
20. august 2004 - 15:04 #13
Det vil jeg da :-)

<?php
    include('config.php');

function getMenu($rootId=0,$topLevel=true) {
    $topul = true;

    static $items = null;

    if( $items == null  )  {
        // Load everything
        $sql = "SELECT id, menu as parent_id, menu_text FROM hbp_pages ORDER BY menu_text";

        $res = mysql_query($sql) or die(mysql_error());

        while($row = mysql_fetch_assoc($res))
            $items[$row['id']] = $row;
    }

    if( $rootId != 0 && $topLevel) {
    if ($topul==true) {
        print "<ul id=\"nav\">";
        $topul = false;
    } else {
        print "<ul>";
        $topul = false;
    }
        print '<li><a href="#">'.$items[$rootId]['menu_text'].'</a></li>';
    }

    $noOutput = true;

    foreach(array_keys($items) as $i ) {
        if( $items[$i]['parent_id'] == $rootId ) {
            if( $noOutput )  {
                $noOutput = false;
                if ($topul==true) {
            print "<ul id=\"nav\">";
            $topul = false;
        } else {
            print "<ul>";
            $topul = false;
        }
        }
            print '<li><a href="#">'.$items[$i]['menu_text'] . '</a></li>';
            getMenu($items[$i]['id'],false);
        }
    }

    if(! $noOutput )
        print "</ul>";

    if( $rootId != 0 && $topLevel ) {
        print "</ul>";
    }
}


getMenu();
//echo "<hr />";
//getMenu(7);
?>
Avatar billede dennismp Nybegynder
20. august 2004 - 15:14 #14
erstat:
$topul = true;
med;
$topul = $topLevel;

Jeg tror det er det eneste der skal til. Her er min kopi:
<?php

mysql_connect('localhost','dmp','dmp');
mysql_select_db('dennis_test');

function getMenu($rootId=0,$topLevel=true) {
    static $items = null;
    $topul = $topLevel;

    if( $items == null  )  {
        // Load everything
        $sql = "SELECT id, menu as parent_id, menu_text FROM hbp_pages ORDER BY menu_text";

        $res = mysql_query($sql) or die(mysql_error());

        while($row = mysql_fetch_assoc($res))
            $items[$row['id']] = $row;
    }

    if( $rootId != 0 && $topLevel) {
        if ($topul) {
            print '<ul id="nav">';
            $topul = false;
        } else {
            print '<ul>';
            $topul = false;
        }
        print '<li><a href="#">'.$items[$rootId]['menu_text'].'</a></li>';
    }

    $noOutput = true;

    foreach(array_keys($items) as $i ) {
        if( $items[$i]['parent_id'] == $rootId ) {
            if( $noOutput )  {
                $noOutput = false;
                if ($topul==true) {
                    print "<ul id=\"nav\">";
                    $topul = false;
                } else {
                    print "<ul>";
                }
            }
            print '<li><a href="#">'.$items[$i]['menu_text'] . '</a></li>';
            getMenu($items[$i]['id'],false);
        }
    }

    if(! $noOutput )
        print "</ul>";

    if( $rootId != 0 && $topLevel )
        print "</ul>";
}


getMenu();
//echo "<hr />";
//getMenu(7);
?>
Avatar billede exp Juniormester
20. august 2004 - 16:42 #15
outputtet er lidt forkert:

<ul id="nav">
    <li><a href="#">1</a></li>
    <li><a href="#">2</a></li>
    <li><a href="#">3</a></li>
    <li><a href="#">4</a></li>
    <li><a href="#">5</a></li>
// Fejl    <li>
        <ul>
            <li><a href="#">8</a></li>
// Fejl            <li>
                <ul>
                    <li><a href="#">10</a></li>
                </ul>
// Fejl            </li>
            <li><a href="#">9</a></li>
        </ul>
// Fejl    </li>
    <li><a href="#">6</a></li>
    <li><a href="#">7</a></li>
</ul>
Avatar billede exp Juniormester
20. august 2004 - 16:43 #16
det er det, hvor der startes en ny <ul>, der kommer der en <li></li> for meget
Avatar billede dennismp Nybegynder
20. august 2004 - 16:56 #17
Jeg kan ikke genskabe problemet. Kan jeg få et dump af din databse?

Du har denne linje right? Og ikke den gamle? (hvor </li> stod efter getMenu(...)

    print '<li><a href="#">'.$items[$i]['menu_text'] . '</a></li>';
Avatar billede exp Juniormester
20. august 2004 - 17:32 #18
db'en:

#
# Table structure for table `hbp_pages`
#

CREATE TABLE `hbp_pages` (
  `id` int(1) NOT NULL auto_increment,
  `menu` int(11) NOT NULL default '0',
  `menu_text` varchar(30) NOT NULL default '',
  PRIMARY KEY  (`id`)
) TYPE=MyISAM AUTO_INCREMENT=11 ;

#
# Dumping data for table `hbp_pages`
#

INSERT INTO `hbp_pages` VALUES (1, 0, '1');
INSERT INTO `hbp_pages` VALUES (2, 0, '2');
INSERT INTO `hbp_pages` VALUES (3, 0, '3');
INSERT INTO `hbp_pages` VALUES (4, 0, '4');
INSERT INTO `hbp_pages` VALUES (5, 0, '5');
INSERT INTO `hbp_pages` VALUES (6, 0, '6');
INSERT INTO `hbp_pages` VALUES (7, 0, '7');
INSERT INTO `hbp_pages` VALUES (8, 5, '8');
INSERT INTO `hbp_pages` VALUES (9, 5, '9');
INSERT INTO `hbp_pages` VALUES (10, 8, '10');




Og har lavet direkte copy/paste af det du postede 20/08-2004 15:14:20 - har kun rettet database-info :-)
Avatar billede dennismp Nybegynder
20. august 2004 - 18:22 #19
Mit output..
<ul id="nav">
  <li><a href="#">1</a></li>
  <li><a href="#">2</a></li>
  <li><a href="#">3</a></li>
  <li><a href="#">4</a></li>
  <li><a href="#">5</a></li>
  <ul>
    <li><a href="#">8</a></li>
    <ul>
      <li><a href="#">10</a></li>
    </ul>
    <li><a href="#">9</a></li>
  </ul>
  <li><a href="#">6</a></li>
  <li><a href="#">7</a></li>
</ul>

Det er da rigtig nok? Eller er jeg blind?
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
Vi tilbyder markedets bedste kurser inden for webudvikling

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