Kreuzabfragen mit mehreren Hirarchien

dwex

Erfahrenes Mitglied
Hallo Leute,

leider ist mir kein besserer Titel eingefallen.

Also ich müsste aus einer DB Artikeldaten abfragen und diese den hirachischen Produktgruppen zuordnen und dann das ganze in ein TXT-File schreiben.

Ich erklärs mal:

1. Tabelle = Produkte
2. Tabelle = Produkte zu Kategorie
3. Tabelle = Kategorien

(es handelt sich um OSCommerce - nur nebenbei)


1. Tabelle:
products_id,title,discription,price

2. Tabelle
products_id,categories_id

3. Tabelle
categories_id,parent_id


Jetzt habe ich z.B. in der Tabelle 1 folgenden Eintrag:
1,Das ist der Titel,Das ist die Beschreibung,599

in Tabelle 2
1,25

und in Tabelle 3
25,22
22,10
10,0

Das will heisen, dass der Artikel mit der ID 1 zur Kategorie 10 --> Untergruppe 22 --> Unteruntergruppe 25 gehört (es kann aber auch sein, dass ein Artikel zu keiner Untergruppe gehört oder das es von der Hirarchie aus gesehen mehr Untergruppen gibt als 2 (wie hier im Beispiel)

Jetzt müsste ich folgendes Ergebnis erzielen, also die ausgegebene TXT-Datei:
Code:
1;Das ist der Titel;Das ist die Beschreibung;599;10 > 22 > 25

Leider hänge ich hier wie ich das mit den Kategorien am dümmsten anstellen soll.
Wie würdet Ihr das machen?
Vielen Dank für eure Beiträge im voraus!
 
Tabelle 1 und 2 sind dir sicherlich klar zum auslesen. Tabelle 3 dürfte wohl das Problem sein.
Ich würde es mit einer rekursiven Funktion versuchen. Diese ruft sich selbst wieder auf bis parent_id = 0 ist, was wohl quasi die "oberste" Kategorie ist, wenn ich das richtig verstehe.

Nur mal grob den Code:
PHP:
function categories ($categories_id, $string) {
  $sql = "select * from tabelle3 where categories_id = '$categories_id'";
  if($row['parent_id'] == 0) return $string . $row['categories_id'];  // Ende
  else {
    $string .= $row['categories_id'];
    categories($row['parent_id'], $string); // Funktion wird wieder mit parent_id aufgerufen um den nächsten Eintrag des "Kategorie-Baumes" zu erhalten
  }
}

$ausgabe = $Tabelle1 // Eintrag aus Tabelle1
$categories_id = ... // categories_id aus Tabelle 2 lesen
$string = '';
$ausgabe .= categories($categories_id, $string);

Vom Prinzip her sollte das so funktionieren, die Ausgabe ist glaube ich noch verdreht. Aber vielleicht hilft es dir ja weiter.

Hier ist auch noch bisschen was zur Rekursion zu lesen: http://www.webmasterpro.de/coding/article/php-rekursive-programmierung.html
 
Servus CKlausi,

vielen Dank für deinen Vorschlag - ist eine geniale Idee.
Leider habe ich noch ein Problem bei dessen Umsetzung wo ich nicht drauf komme wo das Problem liegt.

Ich habe also folgendes gemacht:
PHP:
echo categories(25,'');



// BOF: Funktion zur rekursiven Abfrage der Kategorien
function categories ($categories_id, $string) {

    $abfrage = mysql_query("SELECT * FROM `categories` WHERE `categories_id` = '$categories_id' LIMIT 1");
    
    if(!@mysql_num_rows($abfrage)) {
    	return "nichts gefunden";
    }
    
    $row = mysql_fetch_array($abfrage);
    
    if($row['parent_id'] == 0) {
    	return $string.$row['categories_id'];
    } else {
    	$string .= $row['categories_id'];
    	categories($row['parent_id'], $string);
    }
    
}
// EOF: Funktion zur rekursiven Abfrage der Kategorien

Wenn ich jetzt die categories_id = 10 übergebe (also die parent_id = 0 ist) liefert mir die Funktion auch "10" zurück.
Wenn ich jedoch für die categories_id = 25 übergebe müsste sich die Funktion ja über "else" erneut aufrufen und die parent_id als neue ID übergeben - das Ergebniss müsst dann so wie ich es jetzt geschrieben habe "102225" sein.
Ich bekomme jedoch keine Ausgabe (der Bildschirm bleibt leer).

Wenn ich den Else-Teil so umschreibe:
PHP:
else {
    	return $row['parent_id'];
    }
dann bekomme ich aber die parent_id geliefert. Deshalb schliese ich mal einen "Tipfehler" bei den Variablen aus. Mir stellt es sich so dar, dass die Funktion im Else-Teil garnicht mehr aufgerufen wird. Das Script läuft auch nicht in eine Endlosschleife oder so.

Hast du (oder jemand anderes) eine Idee woran es liegen könnte?
Vielen Dank im voraus!
 
Zuletzt bearbeitet:
Du hast die eigentliche rekursion (halb) Unterschlagen.
PHP:
} else {
        $string .= $row['categories_id'];
        categories($row['parent_id'], $string);
    }
Ich bekomme jedoch keine Ausgabe (der Bildschirm bleibt leer).
[...]

Hast du (oder jemand anderes) eine Idee woran es liegen könnte?
Die Antwort hast dir schon selbst gegeben:
Wenn ich den Else-Teil so umschreibe
PHP:
else {
        return $row['parent_id'];
    }
dann bekomme ich aber die parent_id geliefert
Bei dem Zweiten bekommst du etwas "geliefert". Warum?

Bemerks du von selbst welches wichtige "Wörtchen" beim ersten Codeabschnitt fehlt, das aber im zweiten enthalten ist? ;)

P.S. : 'CKlausi' hat den Fehler ebenfalls. Hast den übernommen.
 
Zuletzt bearbeitet:
Sorry - aber ganz verstehe ich deine Antwort nicht.

Es ist doch Ziel der Rekursion die Funktion solange erneut aufzurufen bis parent_id=0 ist. Wenn ich in den Else-Teil jetzt ein return mit einbringe dann sollte die Rekursion ja beim ersten Durchlauf abgebrochen werden.
So wird im Else-Teil die Funktion erneut aufgerufen und beginnt von vorne bis parent_id=0 ist und dann wird erst was ausgegeben.

Ich habe das jetzt so gemacht:
PHP:
} else {
    	$string .= $row['categories_id'];
    	return categories($row['parent_id'], $string);
    }
Jetzt funktioniert es auch - aber WARUM?
 
Zuletzt bearbeitet:
Um ehrlich zu sein, ich dachte das return wäre dort nicht nötig.
Hm ich steh wohl auf dem Schlauch, warum es dort benötigt wird :-(
 
Sorry - aber ganz verstehe ich deine Antwort nicht.

Es ist doch Ziel der Rekursion die Funktion solange erneut aufzurufen bis parent_id=0 ist. Wenn ich in den Else-Teil jetzt ein return mit einbringe dann sollte die Rekursion ja beim ersten Durchlauf abgebrochen werden.
So wird im Else-Teil die Funktion erneut aufgerufen und beginnt von vorne bis parent_id=0 ist und dann wird erst was ausgegeben.

Ja. Das ist die hälfte der Rekursion die du schon hast. Das wichtigste fehlte.

PHP:
} else {
    	$string .= $row['categories_id'];
    	return categories($row['parent_id'], $string);
    }
Jetzt funktioniert es auch - aber WARUM?

Und wieder steht die Antwort in deinem Quelltext. Sieh mal diese Funktion:
PHP:
function ErstesZeichen($text)
{
  substr($text, 0, 1);
}

$handler = ErstesZeichen("Foo");

Was passiert in der Funktion und welchen Wert wird $handler am Ende haben?
Überlege und dann sieh dir den Spoiler an (wie Text markieren, auch wenn man keinen sieht):
$handler ist komplett leer.

Warum wohl? Was macht die Funktion nicht?
Überlege und dann sieh dir den Spoiler an:
Die Funktion gibt den Wert nicht wieder. Sie ruft nur substr auf und das macht einfach was es soll. Das Ergebnis wird ins PHP-Nirvana geschickt, weil es nicht in eine Variable gespeichert wurde:
$ret = substr(...);
oder als return zurückgegeben so wie es jede Funktion machen sollte.

Das "Problem" ist also das der PC genau das macht was man ihm sagt ;) Sagt man ihm nichts dann macht er auch nichts.

Was heißt "return" auf Deutsch?
Überlege und dann sieh dir den Spoiler an:
return (engl.) = "Antwort", "Rückführung", "Rückgabe"
keine return, keine Antwort
 
PHP:
function ErstesZeichen($text)
{
  substr($text, 0, 1);
}

$handler = Alles("Foo");

Das würde einen Fehler verursachen, da die Funktion Alles nicht bekannt ist ;), aber das nur OT.
 
D.h. man braucht den Parameter $string gar nicht für die Funktion?
Ich dachte mir das nämlich so, dass die Funktion erst am Ende den zusammengebauten String wieder zurückgibt.
 
D.h. man braucht den Parameter $string gar nicht für die Funktion?
Ich dachte mir das nämlich so, dass die Funktion erst am Ende den zusammengebauten String wieder zurückgibt.

Genau so hatte ich es mir auch gedacht!

Aber das wir den Return brauchen - das wissen wir jetzt logisch ist es jedoch immer noch nicht da ja in der Funktion erneut die Funktion aufgerufen wird mit Variablen die ja bekannt sind und am Ende ist parent_id eben 0 und dann werden die vorher zusammengebauten Strings eben ausgegeben.

Ich für meinen Teil nehms jetzt mal so als gegeben hin - wobei der "dumme" Computer es auch anders machen müsste - eben weil er "dumm" ist.

Ich möchte mich noch bedanken bei CKlausi für den Lösungsvorschlag - ich wäre nicht drauf gekommen.
Und bedanken möchte ich mich auch bei ZodiacXP ohne dich wäre ich wahrscheinlich auch nicht auf den Fehler gekommen.

Vielen Dank!
 
Zurück