Archiv der Kategorie: SQL

Joomla Modul mit SQL-Formfield

Da ich keinen vorgefertigten Formularfeldtyp gefunden habe, der mir die Tags (Schlagwörter) ausgibt, hab ichs mal über den Typ SQL form field type probiert, mal sehen wie weit wir damit kommen. Aber erst noch mal ein paar Gedanken zu den Anforderungen:

Ich schraubs mal ein bisschen runter

Im vorigen Artikel hatte ich ja für den Anwender die Möglichkeit geschaffen, eine bestimmte Beitragskategorie auszuwählen. Das hat ganz hübsch funktioniert, aber eigentlich ist es für meinen Zweck nicht ganz das Richtige. Ich brauche ja auch noch mein zweites Auswahlkriterium, nämlich die Tags=Schlagwörter. Kurze Erinnerung, was ausgegeben werden soll:

X Rezepte insgesamt

davon Y mit dem Tag Z

Ich habe aber in meinem Joomla-Kochbuch die Einschränkung gemacht, dass Tags nur für die Kategeorie Rezepte verwendet werden, in den anderen Kategorien (Kochbücher etc.) hab ich sie schlicht und ergreifend nicht eingesetzt. Das heisst aber, unsere Tagauswahl macht nur Sinn, wenn die Beitragskategorie 8 für Rezept ist, und dann kann ich es auch gleich fest verdrahten. Sonst dürfte ich die Tag-Auswahl nur anzeigen, wenn der Anwender die Kategorie Rezepte gewählt hat, und das geht mir dann doch ein bisschen zu weit.

Der Formularfeldtyp SQL

Ist wahrscheinlich am leichtesten zu verstehen, wenn man es am konkreten Beispiel sieht. Die Felddefinition in meiner XML-Datei sieht so aus:

<field
            name="title"
            type="sql"
            default="10"
            label="Einen Tag auswählen"
            query="SELECT id AS value, title FROM #__tags where title not like 'ROOT'"
            />

Dabei ist der Alias „AS value“ wichtig, da über diesen der Rückgabewert des Feldes definiert wird. Den Select hab ich gleich ein bisschen angepasst, wir gehen in die tabelle #_tags und schliessen hier den Systemeintrag ROOT aus, weil der in der Auswahlliste gar nicht auftauchen darf.

Zum Aufbau der Query zitiere ich mal die Joomla-Doku:

  • query (mandatory if not using the sql_* attributes) is the SQL query which will provide the data for the drop-down list. The query must return two columns; one called ‚value‘ (unless overridden by the key_field attribute) which will hold the values of the list items; the other called the same as the value of the name attribute (unless overridden by the value_field attribute) containing the text to be shown in the drop-down list.

Also, mal ganz langsam.

  • die query liefert die Daten für unser Dropdown-Feld
  • die query muss zwei Spalten zurückgeben
  • die erste Spalte der Rückgabe muss value heissen, das passiert hier mit dem Alias, und liefert die Rückgabewerte für das Formularfeld (in unserem Fall die numerische ID des Tags)
  • die zweite Spalte muss genauso heissen wie das Feld in der XML-Datei, ich bin hier bei title geblieben. Die zweite Spalte liefert die Einträge für das Dropdown-Feld.

Alles klar? Jedenfalls funktionierts, und mein Dropdownfeld sieht schon mal ganz gut aus:

dropdown_tags

dropdown_tags

Den Wert, den der Benutzer ausgewählt hat, holen wir uns in der mod_helloworld.php wie gehabt über den Namen des Feldes:

$titel = $params->get('title');

Wir erweitern unser Standardobjekt für die Parameterübergabe an die Helper-Klasse entsprechend:

$data = new stdClass();
//Objekt füllen
$data->kat = $kat;
$data->variable = $variable;
$data->titel = $titel;

Und können jetzt in der helper.php damit weiterarbeiten, da haben wir jetzt die numerische ID des gewählten Tags auf der Variablen $params->titel.

Jetzt müssen wir nur noch zählen, wieviele Rezepte dem gewählten Tag zugeordnet sind, und dafür brauchen wir die Tabelle #__content_item_tag_map, da schauen wir einfach nach, wie oft die aktuelle Tag-ID auftaucht.

//Anzahl der Tags zur TagID holen
        $db = JFactory::getDbo();
        $db->setQuery("SELECT * FROM #__contentitem_tag_map WHERE tag_id = ".$params->titel.""); 
        $db->execute();
        $my_count = $db->getNumRows();
        echo $my_count;

Schlußendlich fehlt uns noch der Name des Tags für die Ausgabe, den holen wir uns mit der ID aus der Tabelle #__tags:

//Name des Tags zur Tag-ID holen
        $db = JFactory::getDBO();
        $db->setQuery("SELECT title FROM #__tags WHERE id=".$params->titel);
        $db->execute();
        $tagName = $db->loadResult();

Das wars, fehlt nur noch die Ausgabe:

echo $my_count." davon zum Thema ".$tagName;

 Bingo, das hat hingehauen! Meine Ausgabe sieht so aus:

tag_kat_ausgabe

tag_kat_ausgabe

Passt einwandfrei. Man könnte es jetzt noch perfektionieren und einen Join auf die #__content über die Kategorie-ID einbauen, damit man nur die Tags angezeigt bekommt, die auch zu Rezepten zugeordnet sind, aber ich wills mal nicht übertreiben. Die Vorgabe war ja, dass Tags nur in der Kategorie Rezepte verwendet werden, das muss reichen.

Fazit

Ich finde, die Formularfelddefinition ist über die XML-Datei übersichtlich und komfortabel gelöst, und die vordefinierten Formularfeldtypen nehmen einem in vielen Fällen einen Haufen Arbeit ab. Das macht es wieder wett, dass die Modulerstellung am Anfang ein bisschen schwer zu durchblicken ist, aber wenn man einmal ein Basic Modul geschrieben hat, geht auch das leicht von der Hand. Modulbasteln in Joomla macht Spaß!

Noch mehr Zahlenschubserei: Besucher im schwarzen Pinguin

Ich machs kurz, ich verspreche es! 🙂

Die Besucherstatistik vom schwarzen Pinguin 2017

Vom Start der Zählung am 10.2.2017 bis gestern,  21.12.2017 waren es insgesamt 8704 Besucher an 316 Tagen im letzten Jahr, macht 27,5 Besucher pro Tag. Als Rohdiagramm sieht das so aus:

exceldiagramm besucher pro tag

besucher pro tag

Da ist im September ein Ausreisser dabei, das war 132 mal die selbe IP-Adresse, scheint ein Hack-Versuch gewesen zu sein. Den nehmen wir mal raus, der verzerrt mir die Stat doch sehr. Dasselbe nochmal ohne den Hacker:

ohne_hacker

ohne hacker

Na, das nenne ich doch einen vernünftigen Geschäftsverlauf. Ich hab das Jahr recht ruhig angefangen, dann einen sehr aktiven Sommer hingelegt und so ab September wieder ein bißchen weniger geschrieben. Da wärs jetzt natürlich interessant, wenn man die Besucherzahlen gegen die Anzahl meiner Beiträge gegenrechnen könnte, aber dazu kommen wir später. Jetzt gibts erst noch die Stammkunden, also alle, die öfter als einmal auf der Seite waren, das waren 970 Leutchen. Wie man hier sieht, waren die meisten so etwa zwischen 5 mal und 15 mal da:

stammkunden

stammkunden

Auch das ist eine sehr zufriedenstellende Gauss’sche Glocke, wie es sich gehört. Und damit laß ich es auch schon gut sein, jetzt gehen wir ans WordPress-Eingemachte, und dazu gibt es einen neuen Beitrag.

Die bessere Alternative zum -zigfachen Join: Kreuztabelle

Also, zuerst mal dieses: ich habe versucht herauszufinden, ob MySQL Kreuztabellen (Pivot Tables) kann oder nicht, und die Tendenz beim Googlen geht zu eher nicht. Jedenfalls gibt es keinen Transform-Befehl, man muß sich da irgendwie anders behelfen.

Ich habe da die tollsten Konstrukte gefunden, hier ein besonders Hübsches mit einem Case für jedes Feld… na, das ist ja wohl nicht der Weisheit letzter Schluß. Da greife ich doch lieber auf meine Leib- und Magendatenbank zurück, nämlich Microsoft Access. Ich bin ja sonst kein Microsoft-Fan, aber das gute alte Access ist einfach eine tolle Datenbank mit einem sagenhaften Bedienkomfort im Entwurfsmodus. Auch wenn die zugrundeliegende Jet-Engine schon viele Jahre auf dem Buckel hat, im intuitiven Zusammenstellen aller möglichen Arten von Abfragen ist Access echt ungeschlagen.

Was wollen wir erreichen?

Wir haben ja im letzten Artikel gesehen, daß wooCommerce zu jeder Bestellung mindestens 48 Einträge in der wp_postmeta anlegt. Ich hätte jetzt gerne einen tabellarischen Überblick über alle Bestellungen, mit allen 48 Werten aus der wp_postmeta zu jeder Bestellung.

Das heißt im Klartext: eine Tabelle mit den relevanten Daten aus der wp_posts, und allen 48 Meta Keys als Felder in einer Zeile. Auf jeden Fall brauchen wir einen Join von der wp_posts auf die wp_postmeta über die ID der Bestellung, und dann noch die Meta Keys als Feldnamen, befüllt mit den Meta Values. Klingt schaurig kompliziert, ist aber in Access relativ einfach machbar, nämlich mit einer Kreuztabelle.

Der SQL für die Kreuztabelle

…sieht so aus:

TRANSFORM First(postmeta_alle_orders.meta_value) AS ErsterWertvonmeta_value
SELECT postmeta_alle_orders.post_id, postmeta_alle_orders.post_title, postmeta_alle_orders.post_status, postmeta_alle_orders.post_type
FROM postmeta_alle_orders
GROUP BY postmeta_alle_orders.post_id, postmeta_alle_orders.post_title, postmeta_alle_orders.post_status, postmeta_alle_orders.post_type
PIVOT postmeta_alle_orders.meta_key;

Den kann man sich mit Hiilfe des Kreuztabellen-Assistenten erstellen und dann im Entwurfsmodus komfortabel editieren.

Das Ergebnis der Kreuztabelle

Ich habs mal schnell der Übersichtlichkeit halber in ein Formular gepackt (auch hierfür hat Access einen prima Assistenten), da sieht dann z.B. unser Datensatz mit der Nummer 42 so aus:

formular_kreuztabelle

formular_kreuztabelle

Na, da hat man wenigstens mal alle Felder im Blick. Wenn man jetzt noch wüßte, für was die alle gut sind… aber da lasse ich jeden selber raten, anhand der Feldnamen müßte man da relativ weit kommen.

Wie kann man es übersichtlicher machen?

Wir haben jetzt wenigstens ein bißchen den Überblick gewonnen, mit 7 Zeilen Jet-SQL statt 48 mal Join und Case. Die Krux ist halt, dass es von vorne herein ein Unding ist, einem Datensatz so viele Werte redundant zuzuordnen.

Wenn sie nur mal die vielen Felder anschauen, die etwas mit Adressen zu tun haben, die gehören ausgelagert! Da gehört ein Fremdschlüssel auf die Kundennummer rein, und zu den Kunden-Basisdaten in einer eigenen Tabelle legen wir uns noch eine schnuckelige zweite Tabelle mit Rechnungsadresse und Lieferadresse (falls abweichend) des Kunden an, das wars dann und ist sauber gelöst.,

Damit können die ganzen Adressfelder aus den Bestellungen rausfliegen, das macht so über den Daumen gepeilt schon mal etwas mehr als 20 Felder weniger. Genauso sieht es mit den Zahlungsmodalitäten und den Steuerinformationen aus, auch die gehören normalisiert und ausgelagert, das wären dann noch mal ein rundes Dutzend Felder weniger.

Aber… die wooCommerce-Entwickler wissen ja anscheinend nicht, wie man Daten normalisiert und Detailtabellen anlegt, deshalb dieser unüberschaubare Datenwust. Das ist einfach nur grottenschlecht programmiert, da beißt die Maus kein Faden ab. Es kann sich ja jeder selber überlegen, wie ein sauberes Datenmodell für die Bestellungen aussehen könnte, so als Fingerübung zum Entspannen 😉

Ich mach hier mal Schluß, und überleg mir ein neues Thema. See you demnächst, ich wünsche gute Erholung vom wooCommerce-Datenchaos!

SQL – die vergessene Kunst?

Die dolle Olle – Structured Query Language

Meine zweite große Liebe auf dem Computer, ich hab es schon erwähnt, waren relationale Datenbanken und SQL. Die geniale Structured Query Language wurde an den Universitäten sehr gepflegt, schließlich ist sie ja auch von Wissenschaftlern für Wissenschaftler erdacht worden. Der ursprüngliche Zweck von SQL war ja die digitale Auswertung von Massendaten. Soweit ich weiß waren die Verhaltensforscher die ersten, die mit Hilfe von strukturierten Datenbanken wissenschaftlich fundierte Forschungsergebnisse erzielten. Mehr über die Geschichte und die Grundlagen von SQL kann man hier bei Wiki nachlesen, das ist spannend und gilt alles auch heute noch.

Ach so, und was hat das mit WordPress zu tun? Gemach, gemach.  Ohne MySQL kein WordPress. Mehr dazu (viel mehr!) später.

SQL ist SQL geblieben

Ich jedenfalls habe SQL damals an der Uni sozusagen mit der Muttermilch aufgesogen und habe früh erkannt, welcher Power und welche Vielseitigkeit im relationalen Datenbankmodell steckt. So kam es, daß ich als studierte Biologin in der EDV gelandet bin – und dort echt Karriere gemacht habe. SQL hat sich bis heute kaum verändert. Wer die Grundlagen einmal begriffen hat, dem ist es egal ob er es nun mit Oracle, Access oder SQL Server, MySQL oder sonst einem Dialekt zu tun hat. Einen Select, einen Join oder eine Where-Klausel schreibt man heute noch genauso wie vor 40 Jahren, da ist nicht viel passiert – wozu auch. Die alten SQL-Konzepte sind so gut, da ist nie etwas Besseres nachgekommen.

Datennormalisierung – wer kennt das heute noch?

Was allerdings heute in Vergessenheit geraten scheint, ist die grundlegende Strukturierung der Daten. In SQL-Datenbanken landet heutzutage häufig unkontrolliertes Datenmus, es ist eben zu einfach, irrsinnige Mengen an Daten automatisiert abzuschöpfen. Als Programmierer sitzt man dann zu oft vor einer ungenießbaren Datensuppe, aus der man eine strukturelle Logik erst mühsam herausfieseln muß, ehe man zu vernünftigen Abfrageergebnissen kommt. Dabei könnt’s so einfach sein – wenn sich heute noch jemand die Mühe machen würde, die grundlegenden Tabellen zu Normalisieren und eine vernünftige Struktur hineinzubringen.

Gottseidank gibts Datensuppe – und (noch) keine gläsernen Bürger

Ich bin eigentlich ganz froh, daß die heutzutage erhobenen Datenmengen so schlecht strukturiert sind. Wenn da mal jemand vernünftig aufräumen würde, wären wir ganz schnell beim gläsernen Bürger. Überlegen sie nur mal, was herauskäme, wenn all ihre Bank- und Behördendaten, ihre Handy- und Internetprofile, ihre Krankenkassendaten und was weiß ich noch alles sauber durchstrukturiert und per SQL ganz easy abfragbar wären. Dann hätten wir sie, Huxley’s Schöne Neue Welt – und ich bin heilfroh, daß es nicht so ist.

Unfreiwilliger Schutz vor der totalen Überwachung

Die irrsinnigen Mengen an Datenschrott, die heutzutage über jeden von uns in irgendwelchen Computern gespeichert sind, sollen bitte so unübersichtlich und unauswertbar bleiben, wie sie sind, das ist unser bester Schutz vor der totalen Digitalisierung, die mit den heutigen technischen Mitteln theoretisch schon möglich wäre. Praktisch umsetzbar ist sie (noch) nicht, weil bei der Unzahl an unterschiedlichen Systemen und labyrinthischen gewachsenen Strukturen keiner mehr durchblickt, und das soll bitteschön so bleiben. Daten-Müllhalden als Schutz vor der totalen Überwachung?

Besser als nix, wenn sie mich fragen. Lieber ärgere ich mich noch lange Jahre z.B. mit Behörden oder Versicherungen rum, weil die anscheinend keine Daten speichern (oder sie nicht wiederfinden) und man bei jedem kleinen Antrag alles noch mal von vorn ausfüllen muß. Ist für mich als Bürger etwas unbequem, aber ehrlich: wenn die alle auf Knopfdruck meine sämtlichen Daten da hätten, würde mir mulmig. Da sei St.Murphy vor, er bewahre uns bitte das behördliche Datenchaos. Amen! 😉

Für wen ist dieser Blog gedacht?

Ist ernstgemeint: für alte Programmierer. Das ist jetzt nicht unbedingt für Tattergreise gedacht, sondern für technisch interessierte Leute, die schon ein paar Jahre Erfahrung in der IT auf dem Buckel haben. Dazu zähle ich auch ausdrücklich die alten Hobby-Programmierer, denn von denen gibt es viele sehr gute da draussen, die womöglich ihre erste Datenbank noch anno Dunnerkeil mit dBase geschrieben haben und die sich mit Excel, Word und Access schon unter DOS auskannten.

Also für Dinosaurier?  Ausdrücklich JA! Ich liebe Dinos, vermutlich weil ich selber mittlerweile einer bin 😉

Und mit diesen Dinosauriern möchte ich mich gerne über WordPress unterhalten, die erfolgreichste Blog-Software aller Zeiten. Ich selber nutze Wordpess seit einigen Jahren als Frontend für die Erstellung kleiner und mittlerer Webseiten, und bin eigentlich ein begeisterter Fan,  es ist so schön einfach zu bedienen, es ermöglicht auf einfachste Weise wunderbare Layouts und ist unendlich erweiterbar.

Warum „eigentlich“ ein Fan?

Weil ich nicht alles an WordPress gut finde.  Es gibt auch Sachen, die mich echt nerven, oder wo ich nicht verstehe warum man Dinge unnötig kompliziert macht. Ich möchte hier aber keinesfalls verbiesterte Kritik üben, mir geht es um eine eher lockere, ich würde fast sagen spielerische Herangehensweise, denn WordPress kann auch richtig Spaß machen.

Was ich voraussetze

Einige allgemeine Grundlagen der Programmierung (Sie sollten schon wissen wie man ein if..then..else und sowas konstruiert), solide SQL-Grundkenntnisse und ein allgemeines Verständnis des relationalen Datenbankmodells, dazu noch für den optischen Zuckerguß Erfahrung mit HTML und CSS, und ein bißchen PHP und MySQL kann auch nichts schaden. Und natürlich zumindest erste Erfahrungen mit WordPress, wenigstens ihre Urlaubsfotos sollen sie schonmal damit veröffentlich haben 😉

Was  ich nicht machen werde

Ich werde hier keine Sammlung von fix und fertigen Code Snippets zum Rauskopieren aufstellen, dafür fehlt mir einfach die Geduld. Einige beispielhafte Codeschnipsel hier und da müssen genügen, sie können ja selber tippen, und alte Programmierer lassen sich von verschachtelten Klammerungen und der allgemeinen Gänsefüßchenwut nicht abschrecken. Mir geht es darum, daß sie meine Codebeispiele nach vollziehen können, weil sie sie verstanden haben. Hier wird es also keinen  Copy&Paste-Laden geben, sondern eher eine lockere Plauderei über Konzepte mit eingestreuten Programmierbeispielen, die sie selber ausbauen und aufhübschen können. Sie werden sehen, wir werden jede Menge Spaß damit haben!