Du bist nicht eingeloggt! Möglicherweise kannst du deswegen nicht alles sehen.
  (Noch kein mods.de-Account? / Passwort vergessen?)
Zur Übersichtsseite
Hallo anonymer User.
Bitte logge dich ein
oder registriere dich!
 Moderiert von: Che Guevara


 Thema: rekursives Menu ( PHP )
erste ungelesene Seite | letzter Beitrag 
Dataminer

Arctic
PHP
Moin,

ich bräuchte mal eure Hilfe.


Ich habe eine Tabelle mit folgenden Registern:
id
parent
name

Daraus möchte ich mir jetzt ein Menu generieren.
Das ganze muss rekursiv sein damit ich quasi unendliche Ebenen habe.
Cool wäre auch wenn man das ganze wie im Explorer aufklappen könnte, nur stehe ich zur Zeit aufm Schlauch!

Beispiel:
 
Code:
id  parent name
1   0      Hauptkategorie 1  
2   0      Hauptkategorie 2
3   1      Unterpunkt1 zu 1
4   1      Unterpunkt2 zu 1
5   3      Unterpunkt1 zu 3
6   2      Unterpunkt1 zu 2


Dann wär das ganze:
 
Code:
Hauptkategorie 1
|-Unterpunkt1 zu 1
  |-Unterpunkt1 zu 3
|-Unterpunkt2 zu 1
Hauptkategorie 2
|-Unterpunkt1 zu 2

So, nun hoffe ich ihr könnt mir helfen, und das BB mir den Thread nicht unlesbar macht.

Danke,
Data.
[Dieser Beitrag wurde 2 mal editiert; zum letzten Mal von Dataminer am 27.09.2004 8:54]
27.09.2004 8:52:36  Zum letzten Beitrag
[ zitieren ] [ pm ] [ diesen post melden ]
SirSiggi

SirSiggi
Hab soetwas schon realisiert, aber ohne eigentlichen Ansatz kann ich dir nicht helfen.

Oder willst du alles vorgekaut bekommen?
27.09.2004 9:28:26  Zum letzten Beitrag
[ zitieren ] [ pm ] [ diesen post melden ]
[DEC]Imperator

imperator
Ich weiss nicht, ob ich ganz genau verstanden habe, was du willst, aber sowas vielleicht:

 
PHP:
<?
function leseMenuPunkt($parentID = 0,$platzhalter = '& nbsp')
{
   $sql = "SELECT * FROM blub WHERE parent = $parentID";
   $qry = mysql_query($sql);
   while($row = mysql_fetch_array($qry))
   {
      echo $platzhalter.$row['name']. "<br>";
      leseMenuPunkt($row['id'],$platzhalter.$platzhalter);
   }
}

leseMenuPunkt();
?>


Ansonsten ist die Sache mit dem Platzhalter durchaus noch verbesserungsfähig *hust*

ALso nur so als Ansatz Augenzwinkern
27.09.2004 12:04:21  Zum letzten Beitrag
[ zitieren ] [ pm ] [ diesen post melden ]
comm@nder

Russe BF
Pear::HTML_Menu sollte Dir weiterhelfen
27.09.2004 13:34:48  Zum letzten Beitrag
[ zitieren ] [ pm ] [ diesen post melden ]
unitrialer

Arctic
Ok, probier ichs mal stückweise:

also erstmal die Klasse:
 
PHP:
<?php
/**
 *  Menu generator
 * 
 *  @copyright Copyright 2004, Thomas Gossmann
 *  @license [URL]http://www.gnu.org/copyleft/gpl.html[/URL] GNU Public License
 *  @author Thomas Gossmann
 */
define('MENU_PARENT'0);
define('MENU_LINK_ID'1);
define('MENU_CAPTION'2);
define('MENU_LOCATION'3);
define('MENU_EVENTHANDLER'4);
define('MENU_TEMPLATE'5);
define('MENU_HIDE'6);

class 
menu
{
    protected 
$current NULL;
    protected 
$activated NULL;
    protected 
$menu = array();
    protected 
$templates = array();
    protected 
$reversed = array();
    protected 
$assembly_line = array();
    protected 
$sorted = array();
    protected 
$return = array();

    function 
menu($items$templates$current$active)
    {
        
$this->menu $items;
        
$this->templates $templates;
        
$this->current $current;
        
$this->active $active;
        if( 
$current === NULL )
        {
            
$this->activated key($this->menu);
            
reset($this->menu);
        }
        else
        {
            
$this->reverse();
            
$this->trace_back($current);
        }
    }

    function 
trace_back$level )
    {
        if( !
array_key_exists($level$this->reverse) )
            return 
NULL;

        foreach( 
$this->reverse[$level] as $menu )
        {
            
$this->assembly_line[] = $level;
            if( 
$menu[MENU_PARENT] != NULL )
            {
                
$this->trace_back($menu[MENU_PARENT]);
            }
            else
            {
                
$this->activated $level;
            }
        }
    }

    function 
reverse()
    {
        foreach( 
$this->menu as $unixname => $menu )
        {
            
$this->reverse[$unixname][$unixname] = &$this->menu[$unixname];
        }
    }

    function 
prepare()
    {
        foreach( 
$this->menu as $unixname => $data )
        {        
            
$this->menu[$unixname]['unixname'] = $unixname;
            
$this->sorted[$data[MENU_PARENT]][] = &$this->menu[$unixname];
        }
    }

    function 
replace_location( &$data )
    {
        
$char strpos($data[MENU_LOCATION], '?') ? '&amp;' '?';
        return 
$data[MENU_LOCATION] . $char 'menu_id=' $data[MENU_LINK_ID];
    }

    function 
replace( &$data )
    {
        
$replace = array(
            
'{assembly_line}' => in_array($data['unixname'], $this->assembly_line) ? 'assembly_line' NULL,
            
'{unixname}' => $data['unixname'],
            
'{location}' => $this->replace_location($data),
            
'{caption}' => $data[MENU_CAPTION],
            
'{parent}' => $data[MENU_PARENT],
            
'{active}' => $this->current == $data['unixname'] ? $this->active NULL,
            
'{level}' => ($data['level'] + 1),
        );

        return 
str_replace(array_keys($replace), $replace$this->templates[$data[MENU_TEMPLATE]]);
    }

    function 
build$level )
    {
        static 
$indentlevel 0;
        if( !
array_key_exists($level$this->sorted) )
            return 
NULL;

        foreach( 
$this->sorted[$level] as $data )
        {
            if( 
$data[MENU_EVENTHANDLER] == ON_LOAD
                
|| ($data[MENU_EVENTHANDLER] == ON_KLICK 
                
&& ( in_array($data[MENU_PARENT], $this->assembly_line)
                || 
in_array($data['unixname'], $this->assembly_line)) ) )
            {
                
$data['level'] = $indentlevel;
                
                if( !
$data[MENU_HIDE] )
                    
$this->return[$data[MENU_PARENT]][$data['unixname']] = $this->replace($data);
            }
            
            
$indentlevel++;
            
$this->build($data['unixname']);
            
$indentlevel--;
        }
    }

    function 
parse()
    {
        
$this->prepare();
        
$this->build();
        return 
$this->return;
    }
}
?>


für php4 die protected durch var ersetzen, warum auch immer die protected sein mögen, private würde ja reichen o_O


So, zur Fütterung des Menüs:

 
PHP:
<?php
// erstmal herausfinden, auf welchem Menupunkt wir uns gerade befinden:

$current = isset($_GET['menu_id']) ? $_GET['menu_id'] : NULL;
if( 
is_null($current) )
{
    
$current = isset($_COOKIE['menu_id']) ? $_COOKIE['menu_id'] : NULL;
}
setcookie('menu_id'$current);


/* Array für Menü-Elemente:
Aufbau:
array {
'unixname' => array(parent, caption, location, eventhandler, template),
'unixname' => ...


unixname: ein eindeutig identifizierbarer Name
parent: Entweder NULL oder unixname eines gewünschten Elternteils
caption: das was man im Endeffekt sieht, der klickbare text
eventhandler: ON_LOAD oder ON_KLICK (einfach bisschen rumprobieren)
template: unixname eines templates, das geparst werden soll
*/
$a_menu = array(
    
'main' => array(NULL'Startseite''test.php'ON_LOAD'item'),
    
'tools' => array(NULL'Tools''test.php'ON_LOAD'item'),
    
'search' => array(NULL'Suchen''test.php'ON_LOAD'item'),
    
'misc' => array(NULL'Misc''test.php'ON_LOAD'item'),
    
'exchange' => array(NULL'Exchange''test.php'ON_LOAD'item'),
    
'admin' => array(NULL'Administration''test.php'ON_LOAD'item'),
    
'sub1' => array('main''Sub 1''test.php'ON_KLICK'subitem'),
    
'sub2' => array('main''Sub 2''test.php'ON_KLICK'subitem'),
    
'sub3' => array('cat2''Sub 3''test.php'ON_KLICK'subitem'),
    
'sub4' => array('cat2''Sub 4''test.php'ON_KLICK'subitem'),
    
'sub5' => array('cat1''Sub 5''test.php'ON_LOAD'subitem'),
    
'top' => array('misc''<img src="images/toplist.gif"> Toplist''test.php'ON_KLICK'subitem'),
    
'list' => array('misc''<img src="images/list.gif"> Verzeichnis''test.php'ON_KLICK'subitem'),
    
'playlist' => array('misc''<img src="images/playlist.gif"> Playlist''test.php'ON_KLICK'subitem'),
    
'export' => array('exchange''<img src="images/export.gif"> Export''test.php'ON_KLICK'subitem'),
    
'import' => array('exchange''<img src="images/import.gif"> Import''test.php'ON_KLICK'subitem'),
    
'edit' => array('admin''<img src="images/edit.gif"> Verwalten''test.php'ON_KLICK'subitem'),
    
'settings' => array('admin''<img src="images/settings.gif"> Einstellungen''test.php'ON_KLICK'subitem'),
);

/* Array für Menütemplates
Aufbau:
array {
'unixname' => 'template',
}

unixname: templates eindeutig identifizierbarer name
template: html-template informationen mit folgenden gültigen werten:

{unixname} - unixname also
{location} - href="{location}"
{caption} - <a href="...">{caption}</a>
{parent} - weiß der geier vielleicht, ich nicht mehr, wozu das ist =)
{active} - <a class="{active}"></a> wird später erklärt
{assembly_line} - <a class="{assembly_line}"></a> wird später erklärt
{level} - einrücklevel
*/
$a_templates = array(
'item' => '<li id="{unixname}"><a href="{location}">{caption}</a></li>',
'subitem' => '<li id="{unixname}"><a href="{location}">{caption}</a></li>',
);

/* Fehlt noch der Menüaufruf: 
Parameterliste:
new menu( array items, array template, mixed current, string [activelink]);

items: array der items
template: array der templates
current: unixname des aktuellen links
activelink: erklärung unten
*/


$menu = new menu($a_item$a_template$current'menulink_active');
$parsed $menu->parse();

echo 
'<pre>';
var_dump($parsed);

// sorry bin mir gerade ned sicher, was da rauskommt.
?>


So, für die Erklärung später:

Es bleiben also activelink (im Konstruktor) und {active} im template. Diese beiden stehen nämlich in Verbindung.
Ist nämlich ein Menülink gerade aktiviert, so kann man ihm einem bestimmten Stylesheet verpassen, wie er heißt, wird eben im Konstruktor festgelegt.
So, dann gibts noch {assembly_line}, ebenfalls ein string, der als stylesheet-Klasse genutzt werden soll. Dann kannst du allen Elternitems eines gerade aktiven Menüitems/links eine bestimmte Klasse vergeben.
Und zu guter letzt noch der {level}. Ist sehr nützlich für die Einrückung eines Items, im Anhang wird ein Beispiel von Template und CSS vielleicht deutlich, wie das funktioniert:


Also, hier mal ein Beispiel-template:
<li class="menulink indentlink{level} {active} {assembly_line}"><a href="{location}">{caption}</a></li>

und hier die CSS-Formatierung dazu:
 
PHP:
.menulink a {
    font-family: Verdana, Arial, Helvetica;
    font-size: 12px;
    background-repeat: no-repeat;
}

.menulink a:link, .menulink a:visited {
    color: #547694;
    background-image: url('images/menu_standard.gif');
}

.menulink a:hover {
    color: #547694;
    background-image: url('images/menu_hover.gif');
}

.menulink_active a:link, .menulink_active a:visited, .menulink_active a:hover {
    font-weight: bold;
}

.assembly_line a:link, .assembly_line a:visited{
    background-image: url('images/menu_active.gif');
}

.indentlink2 a {
    padding-left: 17px;
    background-position: 0px; 
}

.indentlink3 a {
    padding-left: 34px;
    background-position: 17px; 
}

.indentlink4 a {
    padding-left: 51px;
    background-position: 34px; 
}

.indentlink5 a {
    padding-left: 68px;
    background-position: 51px; 
}


So, einfach am besten bisschen rumspielen, ich glaube die Bedienung dürfte nicht mehr gar so schwer sein...

Ride On,
gossi
27.09.2004 14:20:43  Zum letzten Beitrag
[ zitieren ] [ pm ] [ diesen post melden ]
 Thema: rekursives Menu ( PHP )


mods.de - Forum » Webdesign & Coding » 

Hop to:  

| tech | impressum