Tach!
Jede Kategorie, jede Unterkategorie und jeder Link hat in der Tabelle auch eine Spalte 'Aufrufe' (INT-Felder). Die Ressource 'goto_link.php' erhöht nun via PDO den aktuellen Wert von 'Aufrufe' in allen 3 Tabellen. Ich weiß somit genau, wie oft ich einen bstimmten Link aufgerufen habe und wie oft Links aus jeder Kategorie sowie jeder Unterkategorie aufgerufen worden sind.
Das ist auch kein Problem mit nur einer Kategorientabelle. Du kannst mit einem Statement beide Werte erhöhen. (Für den Link braucht es ein eigenes). UPDATE requests = requests + 1 FROM categories WHERE id IN (category, subcategory); (im IN natürlich die beiden entsprechenden IDs einfügen, und requests ist das, was bei dir Aufrufe heißt).
Wenn ich die Kategorien so wie von Dir vorgeschlagen mit dem
if($category['subcategories'])ausgebe, dann erhalte ich bei jeder Kategorie, die keine Unterkategorien besitzt, ein "Notice: Undefined index: subcategories in G:\XAMPP\htdocs\test\index.php on line...".
Das kannst du auf zwei Arten lösen. Die eine hast du schon herausgefunden, die andere wäre, beim Anlegen der Hauptkategorie gleich ein leeres Subcategories-Array hinzuzufügen. Das bleibt eventuell später leer, ist aber generell vorhanden und wirft dan auch keine Notice.
Erst, wenn ich das ändere in
if(isset($category['subcategories'])), kommen keine Notices mehr.
Wieso ist das so?
Es ist eben etwas nicht da und du versuchst lesend darauf zuzugreifen. Nicht selten ist das ein Fehler, wie zum Beispiel beim Variablennamen vertippt. Es ist aber immer eine gute Idee, alles was da sein muss irgendwo vor dem Gebrauch explizit zu definieren. (Das mache ich aber möglichst in der Nähe der Verwendungsstelle und nicht irgendwo generell am Script- oder Funktionsanfang. Wenn man das so unnötig verteilt hilft das nicht unbedingt der Übersichtlichkeit.)
Und das nehme ich gleich zum Anlass, zu fragen, was genau der Unterschied ist, ob ich jetzt
if($foo),if(empty($foo))oderif(isset($foo))schreibe?
if prüft immer einen Ausdruck auf seinen booleschen Wert. Soweit ist das sicherlich klar. Bei if ($foo) ist es ein Variableninhalt. PHP weiß, dass if einen booleschen Wert haben will, also wird der Ausdruck ausgewertet und gegebenenfalls nach Boolean gecastet. Die Variable muss dazu gelesen werden. Bei PHP muss man die Variablen nicht explizit deklarieren, sondern sie werden beim ersten Schreibzugriff angelegt. Beim Lesen passiert das aber nicht. Da geht die PHP-Code-Ausführung lediglich die interne Liste der vorhandenen Variablen durch und wird nicht fündig. Ergebnis ist dann null und eine Notice. Das null wird nach boolean gecastet und ergibt false - das if ist zufrieden. empty() und isset() sind nun zwei Konstrukte (keine echten Funktionen), die dafür da sind, zu prüfen ob eine Variable oder ein Array-Element oder eine Objekteigenschaft vorhanden ist (und empty prüft auch noch auf „leer“). Sie geben deshalb keine Notice aus.
Würdest Du da _trotzdem_ mit
htmlspecialchars()arbeiten und wenn ja, wieso?
Ja, weil es ohne nicht richtig ist.
Das verstehe ich nicht so recht.
Es ist nur dann nicht notwendig, wenn der Wert garantiert keine (in diesem Fall) HTML-spezifischen Zeichen enthält. Bei Inhalten aus einer anderen Quelle kann man das nicht wirklich garantieren. Im Prinzip geht das nur bei einem direkt im Code stehenden Wert.
Oder kannst du garantieren, dass du niemals ein < im kopierten (Beschreibungs-)Text stehen hast?
Ja, das kann ich.
Naja, das sagst du jetzt so, in deinem jugendlichen Leichtsinn ... Mach es lieber gleich richtig, als dich ständig an dein Garantieversprechen erinnern zu müssen, selbst wenn es überflüssig erscheint. Es ist nur ein Wort und zwei Klammern. (Na gut, gegebenenfalls noch ein paar Zeichen mehr, wenn es vorher ein "String mit $variable drin war", weil der jetzt aufgeteilt werden muss.)
Jetzt müsste ich ja theoretisch nicht auch noch die Hauptkategorie speichern weil ja durch die erste Tabelle hervorgeht, zu welcher Kategorie die Unterkategorie 29 gehört. Aber wie mache ich es dann, die Links _inclusive_ dem ausgeschriebenen Namen von Unterkategorie _und_ Kategorie auf den Bildschirm zu bekommen? [...] Prinzipiell natürlich mit einem JOIN, damit ich zur Nummer aus Tabelle 2 auch einen Namen aus Tabelle 1 habe. ABer wie kommt dann noch der Name der Hauptkategorie dazu? Kannst Du mir da auf die Sprünge helfen bitte? (Heißt es eigentlich 'der', 'die' oder 'das' Query??)
Join ist richtig, genauer ein Self-Join, wenn es nur noch eine Kategorien-Tabelle ist. Die (sagt mein Sprachgefühl (wegen „Abfrage“)) Query sieht da ungefähr so aus:
SELECT c.id category_id, c.name category_name, s.id subcategory_id, s.name subcategory_name
FROM categories s
JOIN categories c ON c.id = s.parent_id
WHERE s.id = ?
Da sind zunächst gewählt die beiden Kategorienamen nebst deren IDs, die du sicher auch benötigen wirst. Dann hab ich die s ins FROM genommen, weil das die Tabelle ist, die du zuerst befragen musst (wenn es zwei verschiedene wären) und von da aus dann über die parent_id die „andere“ Tabelle erreichen kannst. Du kannst die in dem Fall auch andersrum joinen mit demselben Ergebnis. Und das WHERE sollte klar sein.
dedlfix.