dedlfix: Liste mit Kategorien und Unterkategorien (2. Lösungsidee)

Beitrag lesen

Tach!

Die Inhalte der ID sind belanglos.

Was genau meinst Du bitte damit? Der "Inhalt der ID"? Verstehe ich Dich richtig, dass Du damit sagen willst, jede Kategorie braucht eine eindeutige ID und jede Unterkategorie braucht eine eindeutige ID, aber es muss nicht jede Zahl als ID in jeder Gruppe stehen? Analog dazu: Es gibt keine getrennten Kinokarten für Männer und Frauen, beide bekommen die selben, trotzdem hat jede einzelne Kinokarte als "unique ID" einen eindeutigen, nicht doppelt vorkommenden Sitzplatz. War es das, was Du mit dem "Die Inhalte der ID sind belanglos" sagen wolltest?

Genau das meinte ich.

Ich frage mich weiterhin, wieso das besser sein soll.

Weniger Tabellen bedeuten auch weniger Wartungsaufwand.

Es gibt dann also noch eine 3. Tabelle mit allen URLs
Und die ist vermutlich auch unnötig. Die Links können ebenfalls mit in der einen Tabelle als weiteres Feld stehen.
Also bei allem Respekt, das ist Nonsens. Ich fasse in Tabellen Daten zusammen, die auch in Sinn/Inhalt einen Zusammenhang haben.

In deinem Fall ging ich davon aus, dass deine Daten am Ende eine Art Menü darstellen. Da wäre es nur begrenzt sinnvoll sie auseinanderzunehmen. Aber ich überlas "Es handelt sich um eine Link-Sammlung, also eine Lesezeichenverwaltung von URLs." Dann ist der Fall klar und anders (als gedacht). Dann gehören die URLs in eine eigene Tabelle, schon weil du nun 1:n oder m:n vorliegen hast.

Ich lasse mir theoretisch ja noch einreden, dass das in meinem Fall bei Kategorien und Unterkategorien der Fall ist, weil beides thematische Beschreibungen für die URLs sind.

Wenn du Kategorien so aufteilst, dann kommst du bei mehr Ebenen gleich mal auf (mindestens) drei Tabellen. Hauptkategorien mit Kindern, Unterkategorien mit Eltern und Kindern (in beliebiger Anzahl an Ebenen - oder noch extremer für jede Ebene eine Tabelle), und Endkategorien nur mit Eltern ohne Kinder. Wenn sich nicht gravierende Unterschiede in Daten, die noch zu einer Kategorie dieser "Arten" abgelegt werden sollen, ergeben, so ist das Ergebnis eigentlich nur eine unnötig hohe Zahl an Tabellen und eine ziemliche Verzettelung. Das wäre dann totnormalisiert.

Nur verstehe ich Dein PHP nicht. Wo kommt das "$category['subcategories']" plötzlich her?

Das korrespondiert mit dem Array, das ich vorgeschlagen habe. Ich verwende generell englische Bezeichner, da hat man es (bis auf Ausnahmen) leichter mit der Pluralbildung. Im Deutschen unterscheiden sich die Formen manchmal nicht. Und oftmals sind die Wörter auch kürzer.

ID | ParentID | Name
1  | 0        | Hauptkategorie
2  | 1        | Unterkategorie
3  | 0        | zweite Haupt
4  | 0        | dritte Haupt
5  | 3        | Unterkat zur zweiten

Wenn diese Daten in einem Array landen, wie soll dann via PHP eine Liste mit den zusammengehörenden Unterkategorien als Unterliste entstehen, ohne dass auch hier für jede Zeile das komplette Array durchlaufen werden muss, wenn Kategorien und zusammengehörende Unterkategorien völlig durcheinender in der Tabelle gespeichert sind?

Wie ich schon schrieb, erst sortieren, dann reicht einmal durchlaufen - jedenfalls bei zwei Ebenen. Wenn die Hauptkategorien (mit Parent-ID 0 oder NULL) zuerst ausgegeben werden, kannst du diese im vorderen Teil des Durchlaufs anlegen und hast dann die Basis für die jeweiligen Unterkategorien. Bei mehr als zwei Ebenen klappt das so nicht, da muss man tatsächlich mehrfach durchlaufen. Das ist ein einmaliger Aufwand, bei dem man schauen muss, ob sich das im späteren Verlauf durch Vereinfachung des Iterierens lohnt.

Generell: Bei Deiner Tabelle ende ich mit einem mehrdimensionalen Array (Und ja, ich weiß, dass _Du_ das _nicht_ so nennst in PHP). Wenn ich das jetzt mit einem foreach($rows AS $row) durchlaufen lasse, habe ich pro Zeile 3 Informationen zur Verfügung: $row['id'], $row['ParentID'] und $row['Name']. Und wie soll da jetzt eine Liste entstehen, wo Kategorien und Unterkategorien logisch richtig angeordnet sind?

Definiere "logisch richtig angeordnet"! Die Kategorien sind in der Reihenfolge, wie du sie sortiert ausgegeben hast, oder wie das DBMS denkt, wenn du nicht sortieren lässt (zweites Sortierkriterium nach dem 0-oder-nicht-0). Die Unterkategorien stehen bei der jeweiligen Hauptkategorie, weil beim Durchlaufen der Hauptkategorien zu jeder davon die Unterkategorien durchlaufen werden, bevor die nächste Hauptkategorie an die Reihe kommt.

Das eine mag komplexer aussehen, hat aber den Vorteil, dass es beim Verarbeiten einfacher zugeht, weil die Beziehungen zueinander bereits da sind und nicht jedes Mal überprüft werden müssen.
Also was da einfacher sein soll als meine 2. Lösung, sehe ich nicht.

Du läufst einfach durch die jeweilige List der Unterkategorien anstatt durch alle Unterkategorien und dabei zu testen, ob sie dazugehört oder nicht. Du könntest sie auch mit einem einfachen count() auf das subcategories-Array zählen lassen. Bei deiner Variante müsste man da ebenfalls händisch durchlaufen und die nicht passenden aussortieren.

Apropos "Code/Strukturen für Menschen lesbar zu schreiben/entwerfen, ist die hohe Kunst." und weil mir das immer wieder so auf der Zunge liegt: _Genau deshalb_ steigen mir bei der gängigen Art, wie viele Programmierer in PHP bei 'if' oder 'foreach' die geschweiften Klammern setzen, die Grausbirnen auf.

Wenn du dir mal Python anschaust, wirst du sehen, dass Klammerei ziemlich überbewertet ist. Der Mensch braucht sie nicht, wenn der Code ordentlich eingerückt ist - und wer macht das nicht (und entwickelt ernsthaft Programme)? Und man kann Parser schreiben, die sie ebenfalls nicht brauchen, wie Python zeigt. Die Klammern kann man also als ein mehr oder weniger notwendiges Übel ansehen, das sich nun nicht mehr ausrotten lässt. (Noch "schlimmer" sind geschwätzigere Sprachen, die statt Klammern Wörter nehmen.)

Schon bei einem Miniaturbeispiel ist doch
auf den ersten Blick viel schneller und einfacher zu erfassen als würde man das Ganze als
schreiben.

Ansichtssache. Wenn ich Abstand für eine bessere Lesbarkeit hinzufüge, dann mach ich das bewusst. Zu viel Abstand, des Klammern-Prinzips wegen, erhöht auch nicht zwangsläufig die Lesbarkeit.

Sobald mehr als 1 Klammer gleichzeitig offen ist, geht bei der herkömmlichen Schreibweise das Gefühl, was da jetzt womit zusammengehört und welcher Block zu welcher Bedingung gehört, verloren.

Deswegen rückt man ja Blockinhalte der Lesbarkeit wegen auch ein, auch wenn es der Parser nicht braucht und man theoretisch auch die Klammern zählen könnte. Und wenn eine Funktion so groß wird, dass sie nicht mehr gut überblickbar ist, und man sie dann nicht in erfassbarere Häppchen aufteilt, macht man auch was falsch.

Eine letzte Frage noch: In diesem speziellen Fall schreibe ich das Ganz nur für mich persönlich. Da ich nur URLs kompiere und in einem Formulatr einfüge, weiß ich ja, dass hier keine html Tags landen werden. Würdest Du da _trotzdem_ mit htmlspecialchars() arbeiten und wenn ja, wieso?

Ja, weil es ohne nicht richtig ist. Oder kannst du garantieren, dass du niemals ein < im kopierten (Beschreibungs-)Text stehen hast? Es geht mir dabei nicht so sehr um Sicherheit, denn wenn du es nur für dich machst, ist mir diese egal. Aber schon ein einzelnes < kann die ganze Ausgabe ruinieren.

dedlfix.