myGully.com Boerse.SH - BOERSE.AM - BOERSE.IO - BOERSE.IM Boerse.BZ .TO Nachfolger
Zurück   myGully.com > Computer & Technik > Programmierung
Seite neu laden

[PHP] Drop Down Menu aus Datenbank auslesen

Willkommen

myGully

Links

Forum

 
Antwort
Themen-Optionen Ansicht
Ungelesen 24.06.12, 11:59   #1
Stunk70
Anfänger
 
Registriert seit: Oct 2011
Beiträge: 10
Bedankt: 0
Stunk70 ist noch neu hier! | 0 Respekt Punkte
Standard [PHP] Drop Down Menu aus Datenbank auslesen

Hi

Ich hab mich endlich wieder nach einiger Zeit dazu aufmuntern können für nen Freund eine Homepage zu machen. Der Typ will aber besonders viel, was ja nicht das Problem ist.

Der erste Knackpunkt ist das Menu. Es soll insgesamt 2 Ebenen haben. Weiters soll das Menu in einer Tabelle in der Datenbank gespeichert werden, damit er die Menupunkte dann bequem ändern kann etc. CMS-Style eben

Sprich:

Menu 1
- Menu 1.1

Menu 2
- Menu 2.1
- Menu 2.2


Jedenfalls habe ich bereits eine Datenbank angelegt und die zugehörige Tabelle bereits mit Werten gefüllt. Wie ich dann den Algorithmus angesetzt habe hats schon gescheitert. ich kann die erste Ebene wunderbar auslesen, aber sobald es darum geht, die Children zu suchen und richtig einzutragen funktioniert die ausgabe der Children nichtmehr.

Code:
$sql = "SELECT * FROM menu";
	
	$db_erg = mysql_query( $sql );
			
	if ( ! $db_erg )
	{
		echo "Es konnten keine Einträge gefunden werden.";
	}
	
		
	while ($zeile = mysql_fetch_array( $db_erg, MYSQL_ASSOC))
	{
		if ($zeile['parent_id'] == "")
		{
			$ausgabe[1] = $ausgabe[1]."<li><a href='?site_id=".$zeile['site_id']."'>".$zeile['menu_name']." | </a></li>";
			
			$sql_befehl = "SELECT * FROM menu";
			$abfrage = mysql_query($sql_befehl);
			
			while($row = mysql_fetch_array($abfrage, MYSQLASSOC))
			{
				if($row['parrent_id'] == $zeile['site_id'])
				{
					$ausgabe[3] = $ausgabe[3]."<li><a href='?site_id=".$row['site_id']."'>".$row['menu_name']." | </a></li>";
				}
			}
			$ausgabe[1] = $ausgabe[1]."<ul>".$ausgabe[3]."</ul>";
		}
	}
	
	$ausgabe0 =  "<ul>";
	$ausgabe2 =  "</ul>";
	
	echo $ausgabe0.$ausgabe[1].$ausgabe2;

Wenn sich jemand erbarmen könnte da nen Blick drauf werfen könnte und mir sagen könnte wieso die Ausgabe nicht geht dann wäre ich sehr dankbar dafür.


Aja die Struktur der Menu-Tabelle hät ich ganz vergessen:

1. Spalte: id (Laufvariable)
2. Spalte: site_id (Seitenindex - mit Hilfe dieser Nummer erzeuge ich dann den passenden Content über eine andere Funktion)
3. Spalte: parent_id (Enthällt die site_id wo der aktuelle Eintrag untergeordnent ist. Wenn dieser Eintrag leer ist, dann gibts es kein Parent, also Hauptmenüpunkt)
4. Spalte: menu_name (der dann angezeigte Name)


Herzlichen Dank
Stunk70
Stunk70 ist offline   Mit Zitat antworten
Ungelesen 24.06.12, 21:56   #2
urga
Mitglied
 
Benutzerbild von urga
 
Registriert seit: Aug 2009
Ort: void* (*wtf[])(void **);
Beiträge: 453
Bedankt: 137
urga ist noch neu hier! | 0 Respekt Punkte
Standard

stichpunkte: datenstrukturen und rekursive algorithmen.

ich versuche gar nicht genau zu verstehen warum dein programm nicht läuft - dazu ist der code zu konfus ($ausgabe0, $ausgabe[1], $ausgabe2, $ausgabe[3] ... ? mal ein string, mal ein array). weiterhin 2x das gleiche sql-query "SELECT * FROM menu" ? da steckt massiv der wurm drin.

also: das sql 1x ausführen, und aus dem ergebnis den menübaum aufbauen. dann den baum traversieren und gewünschten output erzeugen.

weil ich grade keine DB zur hand habe, das menu als statisches array $data.
wichtig ist: die hauptkategorien müssen 0 als parent_id haben (statt "") => "update menu set parent_id=0 where parent_id="" or parent_id is null)"
und damit korrekt einsortiert werden kann muss bei deinem sql noch ein order by parent_id erfolgen! weiterhin möchte dein kumpel bestimmt noch eine sortierung (sort int default 0) als zusätliche spalte bei menu hinterlegen können.
dann sollte folgender code weiterhelfen:
PHP-Code:

$data
[] = array ('id' => 1'parent_id' => 0'name' => 'a''sort' => 1);
$data[] = array ('id' => 2'parent_id' => 0'name' => 'b''sort' => 2);
$data[] = array ('id' => 3'parent_id' => 1'name' => 'aa''sort' => 2);
$data[] = array ('id' => 4'parent_id' => 1'name' => 'ab''sort' => 1);
$data[] = array ('id' => 5'parent_id' => 2'name' => 'ba''sort' => 0);
$data[] = array ('id' => 6'parent_id' => 3'name' => 'aaa''sort' => 0);
$data[] = array ('id' => 7'parent_id' => 6'name' => 'aaaa''sort' => 0);


class 
CAT {
    public 
$id;
    public 
$parent;
    public 
$name;
    public 
$sort;
    public 
$children = array();
    public function 
__construct($id$name$sort) {
        
$this->id $id;
        
$this->name $name;
        
$this->sort $sort;
    }
    public function 
insert (CAT $c$parent_id) {
        if (
$parent_id == $this->id) {
            
$c->parent $this;
            
$this->children[] = $c;
            return 
true;
        }
        foreach (
$this->children as $chld) {
            if (
$chld->insert ($c$parent_id)) {
                return 
true;
            }
        }
        return 
false;
    }

    private 
$children_sorted false;
    private function 
sort() {
        if (! 
$this->children_sorted) {
            
// falls output mehrfach aufgerufen wird nur einmal sortieren...
            
$this->children_sorted true;
            
usort ($this->children, function ($a$b) { return $a->sort $b->sort;});
        }
    }
    public function 
output ($indent = -1) {
        if (
$this->id != 0) {
            echo 
str_repeat (' ' $indent);
            echo 
$this->name "\n";
        }
        
$this->sort();
        foreach (
$this->children as $chld) {
            
$chld->output ($indent+1);
        }
    }
    public function 
output2 ($indent 0) {
        echo 
str_repeat (' ' $indent);
        
$this->sort();
        foreach (
$this->children as $chld) {
            echo 
$chld->name ' ';
        }
        echo 
"\n";
        foreach (
$this->children as $chld) {
            
$chld->output2 ($indent+1);
        }

    }
}

$root = new CAT (0'root'0);

foreach (
$data as $c) {
    
$res $root->insert (new CAT ($c['id'], $c['name'], $c['sort']), $c['parent_id']);
    if (! 
$res) {
        
print_r ($c);
        die (
'kann c nicht einsortieren!');
    }
}
$root->output();
echo 
"\nout2:\n";
$root->output2(); 
Code:
# php x.php
a
 ab
 aa
  aaa
   aaaa
b
 ba

out2:
a b
 ab aa

  aaa
   aaaa

 ba

#
__________________
entropie erfordert keine wartung
urga ist offline   Mit Zitat antworten
Ungelesen 24.06.12, 23:32   #3
Stunk70
Anfänger
 
Registriert seit: Oct 2011
Beiträge: 10
Bedankt: 0
Stunk70 ist noch neu hier! | 0 Respekt Punkte
Standard

Ach du dicke Flöte....

hmmm...gut dann werd ich das morgen gleich mal testen. Vorerst mal herzlichen Dank für die ausgesprochen UMFANGREICHE Hilfe. Hab mir eher erwartet, dass mir jemand nur sagt wo was umzuschreiben ist, dass mir aber jemand gleich ne ganze Klasse präsentiert ufff....erstaunlich wieviel brauchbare Menschen es noch auf dieser Welt gibt....ich hatte die Hoffnung fast verloren.

Danke
Stunk70 ist offline   Mit Zitat antworten
Ungelesen 24.06.12, 23:56   #4
urga
Mitglied
 
Benutzerbild von urga
 
Registriert seit: Aug 2009
Ort: void* (*wtf[])(void **);
Beiträge: 453
Bedankt: 137
urga ist noch neu hier! | 0 Respekt Punkte
Standard

naja, mit deinem ansatz wirds - wenn es dann irgendwann mal läuft - ein tierisches gefrickel mit unnötig vielen zeilen code. da dachte ich, ich zeig mal lieber wie man es m.e. richtig macht.

für richtig große kategoriebäume (>> 1000 einträge) ist der code zum einsortieren nicht effizient. andererseits denke ich, daß wenn du den code verstehst, einen aha-effekt hast und damit was lernst.

weiterhin empfehle ich dir dringend die einarbeitung in [ Link nur für registrierte Mitglieder sichtbar. Bitte einloggen oder neu registrieren ] falls du mit php webseiten aufziehst. das trennt design bzw. output von programmierung. es gibt fast nichts schlimmeres, als webseiten die php+sql+html+css+javas***** nicht sauber trennen, zu warten.

ausserdem habe ich so viehische zahnschmerzen, daß ich froh über jegliche ablenkung bin...
den code hab' ich nochmal überarbeitet, $parent_id als member von CAT ist unnötig. was man evntl. braucht ist $parent. noch 8h bis zum termin.... aua aua aua
__________________
entropie erfordert keine wartung
urga ist offline   Mit Zitat antworten
Ungelesen 25.06.12, 10:13   #5
Stunk70
Anfänger
 
Registriert seit: Oct 2011
Beiträge: 10
Bedankt: 0
Stunk70 ist noch neu hier! | 0 Respekt Punkte
Standard

Also irgendwie hab ich die jetzt probiert einzubinden. Der Kategorieaufruf wäre doch der Teil hier oder?

PHP-Code:

$root 
= new CAT (0'root'0);

foreach (
$data as $c) {
    
$res $root->insert (new CAT ($c['id'], $c['name'], $c['sort']), $c['parent_id']);
    if (! 
$res) {
        
print_r ($c);
        die (
'kann c nicht einsortieren!');
    }
}
$root->output();
echo 
"\nout2:\n";
$root->output2(); 
Ich hab die Tabelle auch erweitert und die Hauptebene mit parent_id auf 0 gesetzt. Dennoch zeigt er mir gleich garnichtsmehr an. Wahrscheinlich hab ich da irgendwie was falsch verstanden xD.

Woran happerts da...oder bin ich simple doch noch etwas zu blöde für das ganze....

Aha Effekt hatte ich noch keinen, zumal ich den Source bei den ersten paar Malen durchlesen kein bisschen verstanden habe.
Stunk70 ist offline   Mit Zitat antworten
Ungelesen 25.06.12, 18:14   #6
urga
Mitglied
 
Benutzerbild von urga
 
Registriert seit: Aug 2009
Ort: void* (*wtf[])(void **);
Beiträge: 453
Bedankt: 137
urga ist noch neu hier! | 0 Respekt Punkte
Standard

naja, statt foreach ($data ...) machst du ein:

PHP-Code:
$sql "SELECT * FROM menu order by parent_id";
if (! (
$db_erg mysql_query$sql )) {
  echo 
"Es konnten keine Einträge gefunden werden.";
  die;    
}

$root = new CAT (0'root'0); 
while (
$c mysql_fetch_array$db_ergMYSQL_ASSOC)) {
  
$res $root->insert (new CAT ($c['id'], $c['menu_name'], $c['sort']), $c['parent_id']);
    if (! 
$res) {
        
print_r ($c);
        die (
'kann c nicht einsortieren!');
    } 
}
$root->output();

// und dann musst du eben noch output anpassen()
// z.b:
 
public function output ($indent = -1) {
        if (
$this->id != 0) {
            echo 
str_repeat ('&nbsp;' $indent);
            echo 
$this->name "<br>\n";
        }
        
$this->sort();
        foreach (
$this->children as $chld) {
            
$chld->output ($indent+1);
        }
    } 
btw: welche php-version verwendest du?
wenn < 5.3 dann setze erstmal private $children_sorted = true;
damit nicht sortiert wird.
__________________
entropie erfordert keine wartung
urga ist offline   Mit Zitat antworten
Ungelesen 25.06.12, 18:30   #7
Stunk70
Anfänger
 
Registriert seit: Oct 2011
Beiträge: 10
Bedankt: 0
Stunk70 ist noch neu hier! | 0 Respekt Punkte
Standard

Also ich hab da jetzt nen Testalgoritmus, der nicht ganz dem entspricht vorerst mal.

ich will zuerst mal das ganze so angehen, dass ichs verstehe also hab ich mir folgendes Überlegt:

PHP-Code:

$html 
"<ul>";    
    
    while (
$zeile mysql_fetch_array($db_ergMYSQL_ASSOC))
    {
        if(
$zeile['parent'] == 0)
        {
            
$sql2 "SELECT * FROM menu WHERE parent LIKE '".$zeile['link']."' ORDER BY id";
            
$dbabfrage mysql_query($sql2);
            
            
$html .= "<li><a href='?site_id=".$zeile['link']."'>".$zeile['label']."</a></li>";
            
            
$kinder "<ul>";
            while (
$reihe mysql_fetch_array($dbabfrage))
            {
                if(
$zeile['link'] == $reihe['parent'])
                {
                    
$kinder .= "<li><a href='?site_id=".$reihe['link']."'>".$reihe['label']."</a></li>";
                }
            }
            
$html .= $kinder."</ul>";
            
        }        
    }
    
    
    
$html .= "</ul>";
    echo 
$html

Das Ganze macht jetzt auch eine richtige Ausgabe. Schlichtweg am display:block happerts jetzt.


Wieso ich mich vorerst für diese Umständliche Methode entschieden habe, nunja...das Menu auf der Projekttseite wird nicht all zu lang. insgesamt 13 Einträge hat das ganze Maximal.

Da kann ich mir diese Art vorerst mal so implementieren.

So und anchdem ich dann noch einige Fragen habe, hoff ich mal, dass dir die Fragerei nicht aufn Leim geht:

Wozu ist das $indent = -1 ?

MfG Sttunk70

PS: Herzlichen Dank!
Stunk70 ist offline   Mit Zitat antworten
Ungelesen 25.06.12, 18:57   #8
urga
Mitglied
 
Benutzerbild von urga
 
Registriert seit: Aug 2009
Ort: void* (*wtf[])(void **);
Beiträge: 453
Bedankt: 137
urga ist noch neu hier! | 0 Respekt Punkte
Standard

indent (einrückung) = -1

$root->ouput() -> $indent == -1, es wird nix ausgegeben wg. (if $this->id != 0) ...
für alle kinder von $root ist $indent == 0,
der deren kinder == 1
und deren == 2, ect.

du machst ja deine einrückungen über geschachtelte ul,

dann sähe output so aus (mit default $indent = 0)
PHP-Code:
    public function output ($indent 0) {
        
$spaces str_repeat (' ' $indent);
        if (
$this->id != 0) {
            echo 
$spaces// nur zur lesbarkeit des html-outputs
            
echo '<li>' $this->name "</li><br>\n";
        }
        
$this->sort();
        if (
$this->children) {
            echo 
"$spaces<ul>\n";

            foreach (
$this->children as $chld) {
                
$chld->output ($indent+1);
            }
            echo 
"$spaces</ul>\n";
        }

    } 
mit meinen fake-kategorien erzeugt das:
Code:
# php x.php
<ul>
 <li>a</li><br>
 <ul>
  <li>ab</li><br>
  <li>aa</li><br>
  <ul>
   <li>aaa</li><br>
   <ul>
    <li>aaaa</li><br>
   </ul>
  </ul>
 </ul>
 <li>b</li><br>
 <ul>
  <li>ba</li><br>
 </ul>
</ul>
auch empfehle ich dir ein besseres buch zur thematik, z.b. [ Link nur für registrierte Mitglieder sichtbar. Bitte einloggen oder neu registrieren ]
__________________
entropie erfordert keine wartung
urga ist offline   Mit Zitat antworten
Ungelesen 26.06.12, 08:22   #9
Stunk70
Anfänger
 
Registriert seit: Oct 2011
Beiträge: 10
Bedankt: 0
Stunk70 ist noch neu hier! | 0 Respekt Punkte
Standard

OK. Danke dir.


Also ich hab meinen Fehler schon gefunden. Funktioniert jetzt alles einwandfrei. Zwar mit meinem Algorithmus, aber den werd ich in der kommenden Zeit eh stanzen und mich mal an die Kategorie sortierung von dir waagen.


Das erste was ich mal machen werde ist mir das Smarty Dingens da anschauen. Das hab ich bis jetzt noch nie gesehen. xD

Ich hab zwar schon Templates geschrieben/entworfen, aber nie wirklich verstanden warum bestimmte Dinge so oder so gemacht wurden. Schaumamal, dass ich das so mal auf die Reihe bekomme.

Herzlichen Dank für deine Hilfe, hat mir einiges gebracht, ich hoff mal es war für dich auch die Mühe wert.

MfG Stunk70
Stunk70 ist offline   Mit Zitat antworten
Ungelesen 05.07.12, 18:57   #10
psychonetic
Newbie
 
Registriert seit: Feb 2010
Ort: Germany
Beiträge: 20
Bedankt: 7
psychonetic ist noch neu hier! | 0 Respekt Punkte
Standard

Wenn du sehr umfangreiche Bäume erstellen willst kannst du dir auch mal Nested Sets anschauen, was sich bei großen CMS-System mit vielen Katagerorien sicherlich besser macht, auch wenn es nicht ganz einfach ist. Die Performance ist beim auslesen aber um einiges besser, nur das Speichern ist nicht gerade einfach. Aber naja das auslesen, kann man mit Cache Systemen verbessern.
psychonetic ist offline   Mit Zitat antworten
Antwort


Forumregeln
Du kannst keine neue Themen eröffnen
Du kannst keine Antworten verfassen
Du kannst keine Anhänge posten
Du kannst nicht deine Beiträge editieren

BB code is An
Smileys sind An.
[IMG] Code ist An.
HTML-Code ist Aus.

Gehe zu


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:40 Uhr.


Sitemap

().