Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 20
  1. #1
    Utente di HTML.it
    Registrato dal
    Mar 2004
    Messaggi
    281

    menu multilivello ricorsivo

    Ho implementato in forma statica il menu che si vede qui
    c'e' il menu e la tabella che definisce il legame tra nodi genitori e figli.

    Ho utilizzato solo una tabella. Se il nodo ha un genitore nella riga del nodo metto l'id del genitore.
    Secondo voi e' strutturato in maniera corretta ?

    Ora partendo dalla tabella dovrei generare dinamicamente il codice che vedete sempre nella pagina (cioe' la sequenza di tag UL e LI corretta).

    Il primo livello riesco a generarlo e anche il secondo pero' il terzo no ma dovrebbe essere simile al secondo e poi non posso ragionare a livelli dovrei fare una cosa diciamo RICORSIVA!

    Io mi sono fermato(piantato) qui, mi date qualche suggerimento ?

    Codice PHP:
    <?
    $db_host 
    "localhost";
    $db_user "root";
    $db_password "";
    $db_name "t3";
    $db mysql_connect($db_host$db_user$db_password);
    if (
    $db == FALSE)
    die (
    "Errore nella connessione.");

    mysql_select_db($db_name$db)
    or die (
    "Errore nella selezione del database.");

    ?>

    <ul id="menu">
    <?
    $str_query_main        
    " SELECT * FROM `main_menu` WHERE id_parent is NULL";
    $result_main           mysql_query($str_query_main$db);

     while (
    $row_main mysql_fetch_array($result_main))  {?>

      <li class="folder">[url="#"]<?print $row_main['etichetta_ita'];?>[/url]
        
        <?
        $str_query_sub        
    " SELECT * FROM `main_menu` WHERE id_parent = " .$row_main['id'];
        
    $result_sub           mysql_query($str_query_sub$db);
        
    $submenu_number mysql_num_rows($result_sub); 
        
    ?>
        
        <? if ($submenu_number>0) print "<ul>"?>
        [*][url="#"]in corso[/url][*][url="#"]in archivio[/url]
        
        <? if ($submenu_number>0) print "[/list]"?>
      
     <? }  ?>

  2. #2
    Utente di HTML.it L'avatar di Teuzzo
    Registrato dal
    Mar 2002
    Messaggi
    969
    Ti consiglio di usare le 'nested sets'. E' spiegato in questo articolo:
    http://database.html.it/articoli/leg...su-database/1/

  3. #3
    Utente di HTML.it L'avatar di M4rko
    Registrato dal
    Dec 2000
    Messaggi
    619
    Se vuoi mantenere quello schema sul database devi ragionare appunto in modo ricorsivo (adjacency list model)
    E` il sistema piu semplice dal punto di vista dell'implementazione, ma ha appunto il difetto della ricorsione... ad esempio un menu su 5 livelli richiede 5 query
    Il punto debole č quindi nelle prestazioni, perō č anche vero che se il tuo albero ha pochi livelli di profonditā, potresti anche non risentirne

    L'alternativa č usare appunto la tecnica dei netsted set: implementazione piu laboriosa ma, indipendentemente dal numero di livelli, fai tutto con una query

    Entrambe le tecniche sono spiegate nell'articolo linkato sopra, con tanto di esempi

    Tutti hanno bisogno di credere in qualcosa.
    Io credo che mi farō un'altra birra.


  4. #4
    Originariamente inviato da M4rko
    Se vuoi mantenere quello schema sul database devi ragionare appunto in modo ricorsivo (adjacency list model)
    E` il sistema piu semplice dal punto di vista dell'implementazione, ma ha appunto il difetto della ricorsione... ad esempio un menu su 5 livelli richiede 5 query
    Il punto debole č quindi nelle prestazioni, perō č anche vero che se il tuo albero ha pochi livelli di profonditā, potresti anche non risentirne
    o altrimenti fai una sola query all'inizio, prima della ricorsione, e memorizzi i dati in un array. questa singola query estrae tutti i dati del menų. poi passi l'array alla funzione ricorsiva e lo usi per estrapolare i vari livelli del menų, quindi senza fare ulteriori query.

  5. #5
    Utente di HTML.it
    Registrato dal
    Mar 2004
    Messaggi
    281
    Aiuto ! Sono incasinato ma e' un problema carino. La soluzione meno onerosa dal punto di vista computazionale mi sembra la migliore anche se la piu' complicata da implementare.

    Questo codice funziona ma non riesco a scrivere i tag UL e LI.

    Codice PHP:
    <?php
    function display_tree($root,$db) {
       
    // retrieve the left and right value of the $root node
       
    $result mysql_query('SELECT lft, rgt FROM rsscategories '.                          'WHERE name="'.$root.'";',$db);
       
    $row mysql_fetch_array($result);

       
    // start with an empty $right stack
       
    $right = array();

       
    // now, retrieve all descendants of the $root node
         
       
    $result mysql_query('SELECT * FROM rsscategories  WHERE lft BETWEEN '.$row['lft'].' AND '$row['rgt'].' ORDER BY lft ASC;',$db);

       
    // display each row
       
    while ($row mysql_fetch_array($result)) {
           
    // only check stack if there is one
           
    if (count($right)>0) {
               
    // check if we should remove a node from the stack
               
    while ($right[count($right)-1]<$row['rgt']) {
                   
    array_pop($right);
               }
           }

           
    // display indented node title
           
    echo str_repeat('',count($right)).$row['name']."
    "
    ;

           
    // add this node to the stack
           
    $right[] = $row['rgt'];
       }
    }
    ?>

    <?
    $db_host 
    "localhost";
    $db_user "root";
    $db_password "";
    $db_name "t3";
    $db mysql_connect($db_host$db_user$db_password);
    if (
    $db == FALSE)
    die (
    "Errore nella connessione.");

    mysql_select_db($db_name$db)
    or die (
    "Errore nella selezione del database.");

    display_tree('Massimiliano',$db);
    ?>
    La tabella e' questa:
    id name lft rgt
    1 Massimiliano 1 14
    2 Francesco 2 13
    3 Mario 3 4
    4 Luigi 5 6
    5 Fabio 7 12
    6 Piero 8 9
    7 Gianni 10 11

  6. #6
    Utente di HTML.it
    Registrato dal
    Mar 2004
    Messaggi
    281
    Il risultato e' questo:
    Massimiliano
    -Gianni
    -Francesco
    --Mario
    --Luigi
    --Fabio
    ---Piero

  7. #7
    Utente di HTML.it
    Registrato dal
    Mar 2004
    Messaggi
    281
    Tra i vari esempi ho trovato questa pagina che penso sia un suggerimento per semplificarmi la vita dei tag LI e UL.
    http://dev.mysql.com/tech-resources/...ical-data.html

    Codice PHP:
    CREATE TABLE nested_category (
     
    category_id INT AUTO_INCREMENT PRIMARY KEY,
     
    name VARCHAR(20NOT NULL,
     
    lft INT NOT NULL,
     
    rgt INT NOT NULL
    );


    INSERT INTO nested_category
    VALUES
    (1,'ELECTRONICS',1,20),(2,'TELEVISIONS',2,9),(3,'TUBE',3,4),
    (
    4,'LCD',5,6),(5,'PLASMA',7,8),(6,'PORTABLE ELECTRONICS',10,19),
    (
    7,'MP3 PLAYERS',11,14),(8,'FLASH',12,13),
    (
    9,'CD PLAYERS',15,16),(10,'2 WAY RADIOS',17,18); 
    E la query che mostra la profondita' dei nodi:
    Codice PHP:
    SELECT node.name, (COUNT(parent.name) - 1) AS depth
    FROM nested_category 
    AS node,
    nested_category AS parent
    WHERE node
    .lft BETWEEN parent.lft AND parent.rgt
    GROUP BY node
    .name
    ORDER BY node
    .lft;

    +----------------------+-------+
    name                 depth |
    +----------------------+-------+
    ELECTRONICS          |     |
    TELEVISIONS          |     |
    TUBE                 |     |
    LCD                  |     |
    PLASMA               |     |
    PORTABLE ELECTRONICS |     |
    MP3 PLAYERS          |     |
    FLASH                |     |
    CD PLAYERS           |     |
    2 WAY RADIOS         |     |
    +----------------------+-------+ 
    Il testo indica questa query come quella per partire a generare i tag UL e LI ma io non ci arrivo.

  8. #8
    Utente di HTML.it
    Registrato dal
    Mar 2004
    Messaggi
    281
    Risolto:
    Codice PHP:
    <style type="text/css">

        body {
            behavior:url("csshover.htc");
        }
        
        * {
            font-family:Verdana, Arial, Helvetica, sans-serif;
            font-size:10px;
        }

        /* the menu */

        ul,li,a {
            display:block;
            margin:0;
            padding:0;
            border:0;
        }

        ul {
        width:130px;
        border:1px solid #eee;
        background:white;
        list-style:none;
        }

        li {
            position:relative;
            padding:1px;
            padding-left:1px;
        
            z-index:9;
        }
            li.folder    { }        
            li.folder ul {
                position:absolute;
                left:120px; /* IE */
                top:5px;
            }        
                li.folder>ul { left:120px; } /* others */

        a {
            padding:1px;
            border:1px solid white;
            text-decoration:none;
            
            font-weight:bold;
            width:125px; /* IE */
        }
            li>a { width:125px; } /* others */

        li a.submenu {
            
        }

        /* regular hovers */

        a:hover {
            border-color:#FF0000;
        }
            li.folder a:hover {
            }
        
        /* hovers with specificity */
        
        li.folder:hover { z-index:10; }        
            
        ul ul, li:hover ul ul {
            display:none;
        }

        li:hover ul, li:hover li:hover ul {
            display:block;
        }        

        </style>




    <?

    $db_host 
    "localhost";
    $db_user "root";
    $db_password "";
    $db_name "t3";
    $db mysql_connect($db_host$db_user$db_password);
    if (
    $db == FALSE)
    die (
    "Errore nella connessione.");

    mysql_select_db($db_name$db)
    or die (
    "Errore nella selezione del database.");

         
    $sql 'SELECT node.*, (COUNT(parent.name) - 1) AS depth FROM nested_category AS node, nested_category AS parent WHERE node.lft BETWEEN parent.lft AND parent.rgt AND parent.category_id !=1 GROUP BY node.name ORDER BY node.lft  ';
            
           
            
            
       
    $result mysql_query($sql,$db);     
       
    $last_depth = -1;
    $output'<ul id="menu">';  // rezultatul final

    while(   $rs mysql_fetch_array($result)             ) {
      
    $current_depth $rs['depth']; // adancimea nodului curent
      // conditie cheie:
      
    if ($last_depth $current_depth) {
        
    $output .= str_repeat('[/list]', ($last_depth $current_depth));
      }
      
    $output .= '<li class="folder"><a href="#">' $rs['name'];

      
    // conditie echivalenta cu intrebarea hasChildren()?,
      // urmata de getChilds() si parcurgerea recursiva 
      // a noului arbore
      
    if ($rs['rgt'] - != $rs['lft']) {
        
    $output .= '</a><ul>';
      } else {
        
    $output .= '</a>';
      }
      
    $last_depth $current_depth;
    }
    echo 
    $output '[/list]';
            
     
    ?>

  9. #9
    Forse la funzione non chiude tutti i tag ul/li (ho fatto un controllo aprossimativo) .


    Cmq che voi sappiate apparte la classe di PEAR non c'č altro? Quello che mi interessa sarebbe, nel caso in cui ad esempio cambiassi il nome ad una voce, riordinare alfabeticamente (mi sto facendo una funzione, perō č un po' uno sbattimento ).
    dA .. foto di viaggio
    L'esperienza č il tipo di insegnante pių difficile.
    Prima ti fa l'esame, e poi ti spiega la lezione.

  10. #10
    Utente di HTML.it
    Registrato dal
    Mar 2004
    Messaggi
    281
    Funziona perfettamente la sto provando.
    Devi solo stare attendo a etichettare i nodi.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.