Archiv der Kategorie: WordPress

WordPress 5.0 und Gutenberg – der erste Eindruck

Was soll ich sagen? Gerade WordPress 5.0 installiert, und gleich beim ersten Versuch mit dem neuen Editor Gutenberg einen Bug produziert. Ich hab einfach mal rumgeklickt und einen „Drop Cap“ angewählt, also ein Initial, und dazu eine Hintergrundfarbe. Das sah dann erstmal so aus:

dropcap_bug

dropcap_bug

Ist jetzt irgendwie nicht so ideal, oder?

Das neue Theme Twenty Nineteen ist ausserdem so ziemlich das häßlichste Theme, das mir je untergekommen ist. Das Design ist absolut grottig, die Schriften sind für meinen Geschmack lieblos zusammengeklatscht, und statt eines schönen Titelbilds ist nur ein minikleines rundes Logo vorgesehen. Die Startseite sieht dann z.B. so aus:

schriften

schriften

Weiter unten ist es auch nicht schöner, der Widget-Bereich ist vom Layout her so schön wie eine billige Einwurfzeitung:

widgetarea

widgetarea

Dann wollte ich ein Bild einfügen – hab erstmal nur die Option „Beitragsbild“ gefunden, das stellt sich dann so dar, blaugetönt und über die ganze Seite ausgebreitet:

beitragsbild

beitragsbild

Finde ich jetzt auch nicht wirklich prickelnd…

Aber ein Theme kann man wechseln, ich hör da mal auf zu meckern und nehm das Twenty Sixteen, damit bin ich eigentlich immer gut gefahren. Wollen doch mal sehen, wie sich der neue Editor benimmt.

Ich möchte gerne eine Liste mit Bullets, erster Ansatz: ich schreib mal meine Listenpunkte untereinander hin, mach jeweils ein Return am Ende. Und jetzt? Noch nichts weiter in Sicht. Ich markiere mal meine drei Listenpunkte, dann ändert sich das Bild. Anscheinend wird für jeden Listenpunkt ein Block angelegt.

drei_blocks

drei_blocks

Ah, guxtu! Wenn man auf das Paragraph-Zeichen drauffährt, kommt auch ein Tooltip, der sagt „Change Block Type“, und hier kriege ich schließlich die Auswahl Liste oder Zitat:

transform_to_list

transform_to_list

Ah, geschafft! Anscheinend brauche ich für jeden Listenpunkt einen eigenen Block, so läuft der Hase.

liste

liste

Dann werde ich wohl für ein Bild auch einen eigenen Block brauchen, schätze ich mal. Ich mach da mal unterhalb der Liste weiter. Wenn man da ganz genau hinguckt, aber wirklich ganz genau, sieht man drei ausgegraute Icons, das mittlere davon könnte evtl. für ein Bild sein:

graue_icons

graue_icons

Sehen sie die Icons in der rechten unteren Ecke? Also, ohne Brille hätte ich da keine Chance. Na gut, klicken wir mal auf das Bild-Icon. Hurra, da kommt der Media-Uploader!

media_uploader

media_uploader

Wenn ich das Bild eingefügt habe, erscheinen rechts im Editorfenster die Bildeigenschaften, das ist OK:

bildeigenschaften

bildeigenschaften

Wenn ich jetzt rechts neben dem Bild Text weiterlaufen lassen will, geht das wieder nur mit einem neuen Block. Hier vermisse ich die Oprion „Als Text einfügen“, die hab ich einfach nicht gefunden. Wenn ich jetzt z.B. aus Word einen Text mit einer Überschrift reinkopiere, baut er mir gleich wieder zwei Blocks, einen für die Überschrift und einen für den Textkörper. Langsam wirds hier unübersichtlich. Ausserdem fehlen im Text etliche Leerzeichen, das ist nicht schön:

leerzeichen_fehlen

leerzeichen_fehlen

Jetzt möchte ich gern noch ein Video einfügen, also frisch auf, ein neuer Block. Klick auf das Icon „Add file“, dann gehts wieder in die Mediathek oder zum Upload und wird defaultmässig zum Download angeboten, das ist ganz OK.

file_download

file_download

Man kann aber auch mit „Change Block Type“ das ganze in ein eingebettetes Video konvertieren, wer das möchte ist auch gut bedient.

Ich lasse es hier mal gut sein, für einen ersten Eindruck reicht das. Das man für jeden Pfiffkaas einen eigenen Block braucht, finde ich dann doch etwas gewöhnungsbedürftig. Man hat dann quasi den Bildschirm voll mit lauter kleinen spezialisierten Editorfenstern, die einem immer nur die Optionen anbieten, die für den jeweiligen Blocktype gültig sind. Na ja. Das kann man mögen oder nicht, ich finde es ziemlich gewöhnungsbedürftig. Was mich definitiv stört: ich bin mehrfach in eine „Keyboard Trap“ gefallen, wo die Tab- und Pfeiltasten nicht mehr so durch den Artikel navigieren, wie man es erwarten würde. Das ist natürlich total grottenschlecht für Benutzer, die Gutenberg nicht mit der Maus, sondern über die Tastatur bedienen möchten. Aber das geht schon stark ans Thema Barrierefreiheit, und sprengt den Rahmen dieses ersten subjektiven Eindrucks.  Mein Fazit: geht so. Ich sehe keinen großen Vorteil im Block-Konzept, aber man kanns wahrscheinlich doch recht schnell lernen. Man kann mit Gutenberg arbeiten, aber wo der grosse bahnbrechende Innovationsvorsprung liegt, hat sich mir nic.ht erschlossen.

Wie lange braucht man, um eine neue Programmiersprache zu lernen?

Das selbsternannte Javascript-Genie

Ich hatte mal einen Teamkollegen in einem sehr explosiven Projekt, der hielt sehr grosse Stücke auf sich. Er codierte ellenlange Module, war ein furchtbarer Geheimniskrämer und ließ sich nicht in die Karten schauen. Er war auch kein Teamplayer, und seine Codeschnipsel arbeiteten nie so mit den Codeschnipsel der anderen Teamkollegen zusammen, dass man sie verwenden konnte. Ich musste eines Tages an einem Algorithmus mit ihm zusammenarbeiten, und das war eine mittlere Katastrophe. Er verkündete: „Ich habe mir Javascript selbst beigebracht, deswegen bin ich so erfolgreich und kann von meinem Know-How in diesem Job gut leben! Ich teile mein Wissen nicht mit dir, schau wie du zurechtkommst!“ und schnappte zu wie eine beleidigte Auster.

Ich schrieb mir dann die notwendigen Routinen selber, statt mich mit seinem Spaghetti-Code herumzuschlagen, und brachte mir dafür ebenfalls Javascript selber bei – in ein paar Tagen, das hat keine Woche gedauert. Warum ich das erzähle? Weil es mich immer wieder erstaunt, dass es Leute gibt die tatsächlich nur eine einzige Programmiersprache beherrschen und sich doch als Developer auf dem Markt behaupten können. Und weil es mich auch immer wieder noch mehr erstaunt, welches Brimborium verantaltet wird, wenn es darum geht, eine neue Programmiersprache zu erlernen.

Gutenberg und React.js

Nehmen wir nur mal als Besipiel den Zinnober, der um den neuen WordPress Editor Gutenberg gemacht wird. Der ist komplett neu programmiert worden, in React.js. Ich habe (noch) keine Ahnung von React.js, vielleicht handelt es sich ja wirklich um eine sehr schwierig zu erlernende und komplizierte Sprache… aber ich schweife ab.

Was ich eigentlich erzählen wollte: als WordPress Accessibility Team Lead Rian Rietveld kürzlich ihren Rücktritt wegen der Querelen um Gutenbergs schlechtes Abschneiden in den Accessiility Audits erklärte, nannte sie als eine der Hauptschwierigkeiten, dass es im Accessibility Team niemanden gab, der sich mit React.js auskannte, und es in der knappen Zeit auch nicht möglich war, einen externen React-Programmierer anzuheuern.

Was kann denn da so schwierig sein?

Ja Donnerlittchen, dachte ich mir, dieses React muss aber ein harter Brocken sein. Ich meine, wenn ich ein Projekt in einer neuen Programmiersprache vor die Nase gesetzt bekomme, hocke ich mich ein paar Tage auf den Hosenboden und arbeite mich da ein, und gut ists.

Ich lerne jetzt seit bald 30 Jahren regelmäßig neue Programmiersprachen, und die Hauptschwierigkeit dabei ist, dass die Syntax von Sprache zu Sprache ein bisschen unterschiedlich ist und man hier ein einfaches oder ein doppeltes Hochkomma, da ein Komma oder ein Semikolon, und dort eine eckige oder geschweifte Klammer braucht.

Aber die Sprachelemente sind fast überall gleich oder zumindest sehr ähnlich. Datentypen sind Datentypen, ein Array ist ein Array, ein Objekt ist ein Objekt, und all die FORs, WHILEs, SWITCHes und wie sie alle heissen, folgen in allen Programmiersprachen der selben Logik. Wenn man die Grundlagen einmal draufhat, ist es auch nicht weiter schwer, sich die Semantik einer neuen Programmiersprache einzuverleiben, die Konstrukte gleichen sich ja doch.

Wieso zum Dunnerkeil hat sich also nicht jemand aus dem Accessibility Team hingesetzt und sich dieses verflixte React.js schnell mal reingezogen? Ich kann es mir nur so erklären: das sind wohl alles keine Programmierer, sondern „nur“ Barrierefreiheits-Experten, die mit Codierung nichts am Hut haben. Denn für einen alter Programmierer ist es eine der leichteren Übungen noch eine Programmiersprache zu lernen, egal wie modern und hyper die auch immer sein mag.

Wenn mich der Teufel reitet, ziehe ich mir mal auf FreeCodeCamp die React-Challenges rein, und ich wette dass ich damit in wenigen Tagen durch bin und dann sehr wohl weiß, was React macht und tut und wie man es anwendet. Echte Programmierer sind nämlich keine One-Trick-Ponys, sondern immer auch ein bisschen Universalgenies. Aber das ist unser Betriebsgeheimnis …

Quick&Dirty Editor für HTML-Posts mit Vorschaufunktion

Wer viel mit CMS umgeht, kennt das zur Genüge: in der Datenbank landet im Feld für den Inhalt eines beliebigen Posts oder einer Seite Text mit jeder Menge HTML-Tags, schließlich arbeitet man ja mit dem TinyMCE oder einem seiner Verwandten.Das sieht zum Beispiel in WordPress so aus:

<h2>Einleitung</h2>
In München-Haidhausen gibt es einen wunderbaren Laden, den "Liquid", da kann man erlesene Alkoholika auch in kleinen Mengen (ab 0,1 l) kaufen. Daher gibt es bei mir die Scaloppine mal mit Marsala, mal mit Sherry, oder ich bereite sie mit Portwein zu, ganz nach Lust und Laune. Wichtig ist, daß der Wein eher von der lieblichen Sorte sein soll, nur dann bekommt die Sauce den schönen vollmundigen Geschmack.
<h2>Zutaten</h2>
Für 4 Personen:

4 Kalbsschnitzel oder 8 dünn geschnittene Minutensteaks, alle Fettränder und Häutchen sorgfältig abgeschnitten, Mehl zum wenden. Je 1 El Butter und gutes Olivenöl, Salz, Pfeffer.
Zum Ablöschen: 1 kleines Glas lieblicher Südwein.
Noch 1 El. eiskalte Butter.
<h2>Zubereitung</h2>
Siehe <a href="http://evileu.de/inselfisch-kochbuch/2017/01/12/schnitzel-mit-zitrone-scaloppine-al-limone/">Scaloppine Grundrezept</a>, zum Ablöschen ein kleines Glas Südwein (s.oben) nehmen. Man kann die Scaloppine auch noch mit etwas feingehackter Petersilie bestreuen, aber das muß nicht unbedingt sein.

Das ist der post_content eines Rezeptes für Scaloppine. Im Inselfisch-Kochbuch sieht das so aus:

scaloppine

scaloppine

Recht und schön, aber im richtigen Leben kommt es immer wieder mal vor, dass man Content aus einem CMS abzieht und in einem anderen CMS weiterverwenden möchte. Das geht in den seltensten Fällen ohne umfangreiche Nacharbeiten, und nicht alles kann man programmgesteuert erledigen.

Man kann mit PHP natürlich alle HTML-Tags entfernen (siehe strip_tags Doku) und dabei sogar Ausnahmen definieren, welche Tags drinbleiben dürfen, und man kann sich auch mit preg_replace mehr oder weniger geniale Ersetzungen einfallen lassen. Aber das hat auch so seine Nachteile.

In dem Scaloppine-HTML ist zum Beipiel ein Link drin, der auf das Inselfisch-Kochbuch auf evileu.de verweist, das kann natürlich nicht so bleiben. Schmeißt man alle Links programmatisch komplett raus, ergibt der Text keinen Sinn mehr, da fehlt dann für das ganze Rezept die Zubereitung. Hier müßte man, wenn man es ganz richtig machen will, dem Link nachgehen und den entsprechenden Zubereitungstext rauskopieren. Das ist natürlich aufwendig, aber im Zweifelsfall die einzig richtige Lösung.

Tscha, was macht man jetzt, wenn man vor ein paar Hundert Posts sitzt, die manuell überarbeitet werden müssen? Man überlegt sich eine Arbeitserleichterung.

Voraussetzungen

Ich hab mir mal aus der WordPress posts-Tabelle nur die minimalsten Rohdaten abgezogen, nämlich die ID, den Titel und den Content, gefiltert nach post_type = post und post_status=publish, das sind die Kerndaten aller veröffentlichten Kochrezepte. Wenn ich sonst noch was brauchen sollte, den Autor oder das Datum oder sogar die Kategorien oder sonstwas, das kann ich mir später über die ID wieder dazulinken. Das selbe könnte ich auch mit Joomla-Beiträgen oder Drupal-Nodes machen, Hauptsache die ID kommt mit und der Titel und Content passen. Und das Ganze ist eigentlich nur sinnvoll, wenn die Posts nicht allzu lang sind, aber meine Kochrezepte gehen selten über eine Bildschirmseite hinaus.

Wir basteln uns einen Quick&Dirty Editor

Damit man jetzt nicht immer direkt in der Datenbank rumpfuschen muss, wenn man in einem HTML-Post etwas ändern will, habe ich mir eine zwar nur als Arbeitspferd geeignete, aber durchaus zeitsparende Lösung überlegt. Ich habe bei meinen ganzen Snippets zur Pagination gekupfert und mir ein PHP-Script gebaut, in dem pro Seite ein Datensatz dargestellt wird. Es gibt eine rudimentäre Navigation (voriger/nächster Datensatz), das reicht mir für die Arbeit, schließlich gucke ich im Zweifelsfall einen Datensatz nach dem anderen durch. Dann habe ich mit Hilfe einer Tabelle zwei Bildschirmbereiche konstruiert, im ersten wird der HTML-Code dargestellt und kann editiert werden, im zweiten gibt es eine Vorschau des Ergebnisses. Noch ein Knöpfchen zum Speichern der Änderungen, und es kann losgehen.

qe_scaloppine

qe_scaloppine

Für den Fall dass ich zu einem bestimmten Datensatz springen möchte habe ich ganz unten auch noch eine nummerische Navigation eingebaut, das ist bei über 300 Datensätzen ganz nützlich.

seitenpagination

Seitenpagination

Wie man mit dem Editor arbeitet

Wenn man in einem Post etwas entdeckt hat, das man ändern möchte, kann man dies direkt im HTML-Fenster tun. Hier habe ich zum Beispiel ein Bild drin, das wird WordPress-typisch in einen caption-Shortcode eingeklemmt, der sorgt in WordPress für die korrekte Darstellung der Bildbeschriftung.

caption

caption

Ein anderes CMS kennt aber den Shortcode nicht, also muss er raus. Das sieht man auch an der Darstellung im Vorschau-Fenster, der Browser kann natürlich ohne WordPress mit dem Shortcode nix anfangen und stellt ihn als Text dar:

caption_vorschau

caption_vorschau

Um das zu korrigieren, schmeisse ich im HTML-Fenster die caption-Tags raus und platziere noch ein paar <br> an den geeigneten Stellen, mache gleichzeitig noch einige kleine Textkorrekturen:

ohne_caption

ohne_caption

Klick auf den Button „Änderungen speichern“, dann kommt erst mal eine kurze Meldung, ob der Update erfolgreich war:

meldung

meldung

Und dann kriegt man das Ergebnis im Vorschaufenster angezeigt:

vorschau

vorschau

Na bitte, das geht doch ratzfatz!

Ohne Netz und doppelten Boden

Da ich beim Klicken auf den „Änderungen speichern“-Button direkt einen Update auf die Datenbank fahre, sind die Änderungen natürlich nicht mehr rückgängig zu machen, aber das kann ich verschmerzen. Schlimmstenfalls muss ich mir einen Datensatz aus der Originaltabelle wieder herholen, wenn ich ihn total verhunzt habe, aber das ist mir eigentlich noch nicht passiert. Im richtigen Leben wird sowas eh der Praktikant machen, und der kann HTML und weiß was er tut, wenn er Tags rausschmeisst oder korrigiert.

Der Q&D-Editor ist ja auch nur als Arbeitshilfe für Entwickler gedacht, und nicht für den Endanwender. Er soll auch nicht den gezielten Einsatz von programmatischen preg_replace-Aktionen ersetzen, die haben ja durchaus auch einen Sinn. Mir gehts immer so, dass ich beim Arbeiten mit dem Editor meistens ganz schnell merke, welche Elemente programmgesteuert rausgeschmissen werden können, weil ich immer die selben Tags editiere – und dann ist natürlich ein bisschen zusätzliches PHP angesagt. In der Praxis wird man immer eine Kombination aus manuellem Editieren und programmgesteuerten Ersetzungen fahren, damit bin ich eigentlich bis jetzt recht gut klargekommen.

Und jetzt gibts den Sourcecode des Q&D-Editors, in einem neuen Beitrag.

 

Sag niemals nie: Widget für die X neuesten Beiträge eigener Post Types

Ich hab ja gesagt, mir ist das zu kompliziert, aber jetzt hab ich mir doch ein Widget geschrieben, das die X neuesten Beiträge eines wählbaren Post Types anzeigt. Man kann dem Widget einen Titel geben, man kann eingeben wieviele Beiträge angezeigt werden sollen, man kann auch noch anwählen ob das Datum mit angezeigt werden soll oder nicht. Aussehen tut das Ganze so:

post_type_widget

post_type_widget

Und die Ausgabe in der Sidebar sieht zum Beispiel so aus:

widget_posts

widget_posts

Hier hab ich als Post Type „post“ angegeben (das sind meine Rezepte), das Limit auf 5 gesetzt und Datum ausgeben angekreuzt.

Das Widget wird ganz normal im Plugins-Verzeichnis angelegt, der Header mit der Klassendeklaration sieht so aus:

/*
Plugin Name: Post Type Widget
Plugin URI: http://evileu.de/wordpress
Description: Zeigt die neuesten X Beiträge des gewählten Post Types an
Author: Evi Leu
Version: 1.0
Author URI: http://evileu.de
*/


class PostTypeWidget extends WP_Widget
{
  function PostTypeWidget()
  {
    $widget_ops = array('classname' => 'PostTypeWidget', 'description' => 'Zeigt die neuesten X Beiträge des gewählten Post Types an' );
    $this->WP_Widget('PostTypeWidget', 'Post Type', $widget_ops);
  }

Interessant wird es in der Formulardefinition, da habe ich mir ein Dropdownfeld mit meinen vorhandenen Post Types gebastelt, ich picke das mal heraus und markiere die anzupassenden Stellen rot:

<p>
    <label for="<?php echo $this->get_field_id( 'posttype' ); ?>"><?php _e( 'Select Post Type', 'textdomain' ); ?>:</label>
    <p>Post Type auswählen
   <select id="<?php echo $this->get_field_id('posttype'); ?>" name="<?php echo $this->get_field_name('posttype'); ?>" class="widefat" style="width:100%;">
    <option <?php selected( $instance['posttype'], 'post'); ?> value="post">Post</option>
    <option <?php selected( $instance['posttype'], 'kochbuch'); ?> value="kochbuch">Kochbuch</option>   
    <option <?php selected( $instance['posttype'], 'projects'); ?> value="projects">Projects</option> 
    </select>
   </p>

Man hätte auch die vorhandenen Post Types aus der Datenbank fischen können, aber das war mit zu viel Heckmeck, da müsste man ja noch die WordPress-eigenen Types und evtl. auch die von irgendwelchen Plugins angelegten herausfiltern, ich fand es so herum entschieden einfacher. Wer mehr Post Types hat, ergänzt einfach den Select entsprechend.

Nachtrag: alle Post Types aus der wp_posts anzeigen

Jetzt hab ichs doch noch ausprobiert, wer sich alle vorhandenen Post Types aus der wp_posts im Dropdownfeld anzeigen lassen will, kann für den Select folgende Konstruktion verwenden:

 <p>Post Type auswählen
   <select id="<?php echo $this->get_field_id('posttype'); ?>" name="<?php echo $this->get_field_name('posttype'); ?>" class="widefat" style="width:100%;">
    <?php
    global $wpdb;
    $alleposts = $wpdb->get_results( "SELECT DISTINCT post_type 
                                      from ".$wpdb->prefix."posts");
    
    foreach($alleposts as $einpost){      
      echo "<option ".selected( $instance['posttype'], $einpost->post_type)." value=".$einpost->post_type.">".$einpost->post_type."</option>";
    }
    ?>
    
    </select>
   </p>

Da kriegt man halt auch jeden Schrott angezeigt, aber es funktioniert:

alle_post_types

alle_post_types

Bleibt jedem selber überlassen, ob er diese Option verwenden will oder den statischen Select von oben. Mir ist die statische Dropdownliste lieber, weil sie den Benutzer nicht in Versuchung bringt hier eine sinnfreie Option wie z.B revisions anzuwählen. Natürlich könnte man den SQL entsprechend aufblasen und noch einige „WHERE post_type NOT LIKE ‚xyz'“ dranflicken, aber das ist mir entschieden zu umständlich.

Die Checkbox für das Datum

Für die Checkbox zum Datum anzeigen habe ich folgende Konstruktion verwendet:

<p>
    <input class="checkbox" type="checkbox" <?php checked( $instance[ 'your_checkbox_var' ], 'on' ); ?> id="<?php echo $this->get_field_id( 'your_checkbox_var' ); ?>" name="<?php echo $this->get_field_name( 'your_checkbox_var' ); ?>" /> 
    <label for="<?php echo $this->get_field_id( 'your_checkbox_var' ); ?>">Datum anzeigen</label>
</p>

Die ganze Funktion form($instance) sieht so aus:

function form($instance)
  {
    $instance = wp_parse_args( (array) $instance, array( 'title' => '' ) );
    $title = $instance['title'];
    
    $instance = wp_parse_args( (array) $instance, array( 'posttype' => '' ) );
    $posttype = $instance['posttype'];
    
    $instance = wp_parse_args( (array) $instance, array( 'anzahl' => '' ) );
    $anzahl = $instance['anzahl'];
    
    $instance = wp_parse_args( (array) $instance, array( 'your_checkbox_var' => '' ) );
    $your_checkbox_var = $instance['your_checkbox_var'];
    
    
    
?>
  <p><label for="<?php echo $this->get_field_id('title'); ?>">Titel: <input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo attribute_escape($title); ?>" /></label></p>
  
   <p>
    <label for="<?php echo $this->get_field_id( 'posttype' ); ?>"><?php _e( 'Select Post Type', 'textdomain' ); ?>:</label>
    <p>Post Type auswählen
   <select id="<?php echo $this->get_field_id('posttype'); ?>" name="<?php echo $this->get_field_name('posttype'); ?>" class="widefat" style="width:100%;">
    <option <?php selected( $instance['posttype'], 'post'); ?> value="post">Post</option>
    <option <?php selected( $instance['posttype'], 'kochbuch'); ?> value="kochbuch">Kochbuch</option>   
    <option <?php selected( $instance['posttype'], 'projects'); ?> value="projects">Projects</option> 
    </select>
   </p>
  <p><label for="<?php echo $this->get_field_id('anzahl'); ?>">Anzahl: <input id="<?php echo $this->get_field_id('anzahl'); ?>" 
name="<?php echo $this->get_field_name('anzahl'); ?>" type="number" value="<?php echo attribute_escape($anzahl); ?>" /></label></p>
<p>
    <input class="checkbox" type="checkbox" <?php checked( $instance[ 'your_checkbox_var' ], 'on' ); ?> id="<?php echo $this->get_field_id( 'your_checkbox_var' ); ?>" name="<?php echo $this->get_field_name( 'your_checkbox_var' ); ?>" /> 
    <label for="<?php echo $this->get_field_id( 'your_checkbox_var' ); ?>">Datum anzeigen</label>
</p>
  
  
  
<?php
  }

Dann noch die Funktion update() anpassen:

function update($new_instance, $old_instance)
  {
    $instance = $old_instance;
    $instance['title'] = $new_instance['title'];
    $instance['posttype'] = $new_instance['posttype'];
    $instance['anzahl'] = $new_instance['anzahl'];
    $instance[ 'your_checkbox_var' ] = $new_instance[ 'your_checkbox_var' ];
    return $instance;
  }

Und schliesslich in der Funktion widget() die Variablen abholen:

function widget($args, $instance)
  {
    extract($args, EXTR_SKIP);
 
    echo $before_widget;
    $your_checkbox_var = $instance[ 'your_checkbox_var' ] ? 'true' : 'false';
    $title = empty($instance['title']) ? ' ' : apply_filters('widget_title', $instance['title']);
    $posttype    = empty( $instance['posttype'] ) ? '' : esc_attr( $instance['posttype'] );
    $anzahl    = empty( $instance['anzahl'] ) ? '' : esc_attr( $instance['anzahl'] );

Der eigentliche OpCode des Widgets ist nicht weiter kompliziert, die Hauptsache ist die SQL-Query, in die ich die Variablen für den Post Type und für die Anzahl einsetze:

global $wpdb;
    $alleposts = $wpdb->get_results( "SELECT * from ".$wpdb->prefix."posts 
where post_type like '".$posttype."' 
and post_status like 'publish' 
ORDER BY post_date DESC
 LIMIT ".$anzahl."");
    

Das ganze wird noch nach dem post_status=publish gefiltert und absteigend nach Datum sortiert und kann jetzt in einem foreach ausgegeben werden. Dabei baue ich noch die Abfrage ein, ob das Datum mit ausgegeben werden soll:

foreach($alleposts as $einpost){
        
        $dt = new DateTime($einpost->post_date);
        echo $einpost->post_title." ";
        if ($your_checkbox_var == 'true'){ echo $dt->format('d.m.Y');}
        echo "<br>";
    }

Hier könnte man wie schon öfter gehabt mit dem get_permalink() über die ID gleich noch den Link zum entsprechenden Beitrag mit einbauen, das spare ich mir jetzt. Wem das jetzt zu schnell ging, den ganzen Code des Widgets gibt es hier gezippt: post-type-widget

Viel Spaß beim Nachbauen!

 

 

Custom Post Types: kurzes Resümee

Wie wir gesehen haben, sind Custom Post Types und Custom Taxonomies für jemanden, der ein bisschen Ahnung vom Programmieren hat, nicht besonders schwierig zu realisieren. Rein funktional gesehen sind sie eine tolle Erweiterungsmöglichkeit, die WordPress auf dem Weg zum „richtigen“ CMS mit Siebenmeilenstiefeln weiterbringen. Was hab ich also noch zu meckern?

Eben: es geht nicht ohne Eingriffe in die functions.php (oder ein selbst programmiertes Plugin), und man kommt auch nicht darum herum die Theme-Templates zu manipulieren. Da würde ich mir eine andere Lösung wünschen! Es wäre eine tolle Erweiterung des Core, wenn man Custom Post Types und Taxonomien über das Dashboard anlegen könnte, und dass da Bedarf da ist, zeigt die stattliche Auswahl an Plugins für diesen Zweck. Ich hab hier mal mit Absicht auf deren Einsatz verzichtet, eben weil es nicht sonderlich kompliziert ist sich seine Custom Post Types selber zu stricken, und  weil ich manchmal gern den Dingen auf den Grund gehe.

Aber für zukünftige WordPress-Versionen wäre es schon eine Bereicherung, wenn einem die Erstellung eigener Post Types auch so einfach gemacht werden würde wie bei der Konkurrenz (Joomla, Drupal…). Beim googlen zum Thema bin ich einige Male auf Diskussionen gestossen, in denen genau dies thematisiert wird. Also, mal schauen was noch kommt, und was sich die WordPress-Entwickler da noch einfallen lassen. Es bleibt jedenfalls spannend!

Custom Post Types in einem Widget

Ich hab nach langem und nicht besonders produktiven Googlen beschlossen, KEIN eigenes Widget für die Ausgabe der neuesten X Kochbücher zu schreiben, das ist mir viel zu umständlich. Es gibt auch Plugins speziell für diesen Zweck, aber das muss auch nicht sein, denn eigentlich ist die Anforderung mit einem einzigen MySQL-Statement zu erschlagen, das machen wir selber. Ich packe das wieder mal in einen Shortcode, der kann in die functions.php oder in ein Plugin, ganz nach Belieben. Das Ganze sieht schlicht und ergreifend so aus:

function kochbuch_ausgabe(){
   
  global $wpdb;
  $alleposts = $wpdb->get_results( "SELECT * from iii_wpposts 
WHERE post_type LIKE 'kochbuch' 
AND post_status LIKE 'publish' 
ORDER BY post_date DESC LIMIT 10");
    
    $ausgabe="";
    foreach($alleposts as $einpost){
        
        $ausgabe = $ausgabe.$einpost->post_title."</br>";
    }
    return $ausgabe;
 }
 add_shortcode('k_ausgabe', 'kochbuch_ausgabe');

Im Select ist alles drin was wir brauchen, das Limit kann man sich nach Wunsch selber anpassen.

Wenn wir das jetzt in einem Widget in der Sidebar haben wollen, klemmen wir uns ein Text-Widget und fügen da den Shortcode ein, und vergeben einen Titel nach Wunsch. Sollte das nicht klappen, muss man zuerst noch Shortcodes für das Text-Widget aktivieren, das geht mit einer Zeile in der functions.php:

add_filter('widget_text', 'do_shortcode');

Fertig sieht das so aus:

die_neuesten_kochbücher

die_neuesten_kochbücher

Wer mag, kann sich jetzt noch mit get_the_permalink() die Links zu den entsprechenden Kochbüchern basteln, die ID ist ja mit im Select. Das spare ich mir jetzt, da kann jeder selber kreativ werden.

Die Ausgabe der Custom Taxonomies in einem Widget: ein schickes kleines Plugin

Da mir die Tabellenstruktur der Taxonomies zu komplex für einen Select ist (join über 4 Tabellen), hab ich mal kurzen Prozeß gemacht und mir ein Plugin für diesen Zweck ausgesucht:

List Custom Taxonomy Widget

Es tut genau das, was es soll, und ist so gut wie selbsterklärend.

list_custom_taxonomy

list_custom_taxonomy

Die Ausgabe ist ganz wie erwartet:

aus_aller_welt

aus_aller_welt

Damit lass ich es gut sein, da muss man echt nichts mehr selber programmieren. Das Widget läßt sich natürlich auch für die Kochbuch-Stichworte verwenden, da brauchen wir also auch nix extra.

widget_stichworte

widget_stichworte

Für Bastler: es geht auch mit get_terms()

Wer sich die Ausgabe der Custom Taxonomies partout selber antun möchte, kann auf die WP_Funktion get_terms() zurückgreifen (siehe Codex). Den Link auf die enstprechenden Begriffe holt man sich dabei mit get_term_link(). Ich hab hier nur mal ein ganz kurzes Beispiel in einen Shortcode gepackt:

function get_land(){
 $terms = get_terms( 'land' );
if ( ! empty( $terms ) && ! is_wp_error( $terms ) ){
 
 foreach ( $terms as $term ) {
   
   echo "<a href = '".get_term_link($term)."'>".$term->name ."</a><br>";
     }
 
}
}
add_shortcode('land_ausgabe', 'get_land');

Das berücksichtigt jetzt nicht die geschachtelte Struktur, sondern gibt nur eine alphabetisch sortierte Liste der Terms der Taxonomie land mit ihren Links aus.

land_bastler

land_bastler

Man könnte jetzt noch den Namen der Taxonomie als Parameter in den Shortcode übergeben und sonst noch allerhand… aber wie gesagt, das ist was für Bastler. Ich verwende das oben vorgestellte Plugin, und gut ists.

Custom Post Type Kochbuch: das Feintuning, mit Custom Taxonomies

Verwendung des Excerpts/Auszugs

Zuallererst möchte ich einstellen, dass man bei den Kochbüchern in der Blog View nicht den ganzen Inhalt angezeigt bekommt, der ist nämlich im Zweifelsfall recht lang, und ausserdem mit mehreren großformatigen Bildern versehen. Dafür gibt es in WordPress die Funktion des Auszugs (Engl. Excerpt), damit kann man einen kurzen Einführungstext erstellen, der dann z.B. in der Liste der Suchergebnisse statt dem ganzen Beitrag angezeigt wird. Den Auszug hatten wir in unserer Post-Type-Definition aus dem vorigen Beitrag noch nicht mit drin, das ist aber schnell nachgeholt. Wir ergänzen in der functions.php unseres Childthemes die Post-Type-Definition wie folgt:

function post_type_kochbuch() {
    register_post_type(
                'kochbuch',
                array(
                    'label' => __('Kochbuch'),
                    'public' => true,
                    'show_ui' => true,
                    'supports' => array(
                    'title',
                    'editor',
                    'excerpt',
                    'post-thumbnails',
                    'custom-fields',
                    'revisions')
                )
        );
    
     
}

Damit wird im Beitragseditor unter dem Content-Feld jetzt das Feld Auszug mit angezeigt, und wir können einen Kurztext eingeben. Wie und wo überall der angezeigt wird ist vom Theme abhängig, ich arbeite hier mit einem Child von Twenty Twelve, da geht man es so an:

Dafür klemmt man sich die content.php und legt eine Kopie ins ChildTheme-Verzeichnis. Dann macht man sich auf die Suche nach der Codezeile:

<?php if ( is_search() ) : // Only display Excerpts for Search ?>

Die ändert man wie folgt:

<?php if ( is_search() || is_home() ) : // Display Excerpts for Search and Homepage ?>

Und schon tauchen auf der Kochbücher-Seite nur noch die Titel und die Auszüge auf. Kleiner Pferdefuß: das gilt jetzt auch für die Rezepte-Blogseite, auch dort werden nur noch Titel und Excerpts(falls vorhanden) angezeigt – ist mir aber ganz recht so, ich finde das wesentlich übersichtlicher. Ich schau aber mal, ob ich da noch eine genauere Steuerungsmöglichkeit finde.

Kategorien und Schlagwörter für die Kochbücher

Dafür legen wir uns zwei Custom Taxonomies an, die nur für den Post Type Kochbuch gelten. Das ist nicht weiter kompliziert, hier der Eintrag für die functions.php:

function kochbuch_create_my_taxonomy() {

    register_taxonomy(
        'land',
        'kochbuch',
        array(
            'label' => __( 'Land' ),
            'rewrite' => array( 'slug' => 'land' ),
            'query_var' => 'land',
            'show_ui' => true,
            'hierarchical' => true,
        )
    );
      register_taxonomy( 
      'kochbuch-stichwort', 
      'kochbuch',
        array(
             'hierarchical' => false,
             'label' => __('Kochbuch-Stichwort'),
             'query_var' => 'kochbuch-stichwort',
             'show_ui' => true,
             'rewrite' => array('slug' => 'kochbuch-stichwort' )
        )
    );
}
add_action( 'init', 'kochbuch_create_my_taxonomy' );

Rot markiert sind die Einträge für die Benennungen und die Slugs der jeweiligen Taxonomie. Die grün markierte Option ‚kochbuch‚ am oberen Ende der Taxonomie-Definition sorgt dafür, daß die Taxonomie auch nur für den Post Type Kochbuch herangezogen wird. Der einzige Unterschied zwischen den beiden Taxonomien ist, dass ich für die Land-Taxonomie ‚hierarchical’=>true eingestellt habe, das erlaubt eine Schachtelung der Länder. Für die Kochbuch-Stichworte steht hierarchical => false, das ergibt eine Ebene wie man es von den Stichworten in Worpress gewohnt ist.

Das sollte schon genügen, um unsere Custom Taxonomies funktional zu machen:

custom_taxonomies

custom_taxonomies

Ich hatte übrigens beim Testen am Anfang das Problem, dass neue Taxonomie-Einträge sich nicht abspeichern liessen. Die Ursache war ein Plugin-Konflikt! Ich hatte auf der Testumgebung noch einen Haufen experimentelle Plugins am Laufen, die hab ich deaktiviert, dann hat es ganz normal funktioniert. Die Wurzel des Problems war anscheinend eine Schlamperei meinerseits, ich hatte in einigen Plugins vor dem öffnenden <?php-Tag Whitespaces drin, das mag WordPress gar nicht, da gibt es die bekannte Meldung „Das Plugin verursachte X Zeichen unerwartete Ausgabe…“

Wie man die neuen Taxonomien ins Template einfügt

Das hängt wieder ziemlich vom Theme ab, da muss man ein bisschen rumprobieren. Die Taxonomie Land bekommt man mit folgender Codezeile:

<div class="entry-meta">
            <?php echo get_the_term_list( $post->ID, 'land', 'Rezepte aus aller Welt: ', ', ', '' ); ?>
            
        </div>

Ich hab da gleich mal die div class= „entry meta“ mitgenommen, damit die Formatierung wie bei den WordPress-Standardkategorien ausfällt. Die Codezeile kommt in die content.php ins Child-Theme, und zwar zwischen dem Block für den entry-content und dem footer:

</div><!-- .entry-content -->
        <?php endif; ?>
        <div class="entry-meta">
            <?php echo get_the_term_list( $post->ID, 'land', 'Rezepte aus aller Welt: ', ', ', '' ); ?>
            
        </div>
        <footer class="entry-meta">

In der Blogansicht sieht das dann so aus:

land_anzeige

land_anzeige

Und so sieht es aus, wenn man auch noch die Stichworte an der selben Position ausgibt:

<div class="entry-meta">
            <?php echo get_the_term_list( $post->ID, 'land', 'Rezepte aus aller Welt: ', ', ', '' ); ?><br>
            <?php echo get_the_term_list( $post->ID, 'kocbuch-stichwort', 'Stichworte: ', ', ', '' ); ?>
            
        </div>

(im kocbuch-Stichwort ist ein Schreibfehler, bitte ignorieren)

Nicht vergessen: Permalinks updaten!

Sonst kriegt man die 404-Meldung, wenn man auf einen der Taxonomy-Einträge klickt. Unser Endergebnis sieht jetzt in der Blog-Ansicht so aus:

blogview_kochbuch

blogview_kochbuch

Wir haben: den Titel, den Excerpt, die Länder und die Stichworte. Paßt!

Jetzt möchte ich noch gern meinen neuen Post Type Kochbuch in einem Widget „Die neuesten Kochbücher“ ausgeben, und die Kochbuch-Länder ebenfalls, aber dazu gibt es einen neuen Beitrag.

WordPress Custom Post Types – die Ehrenrettung als CMS?

Was in anderen CMS längst zur Standardausrüstung gehört, nämlich eine Logik zur Verwaltung und Präsentation unterschiedlicher Beitragstypen, ist in WordPress „out of the box“ erstmal nicht machbar, man hat Blog-Beiträge und statische Seiten, und das wars erstmal. In Joomla habe ich dafür die Kategorien mit einem ausgefeilten Verwaltungssystem, in Drupal die Inhaltstypen mit nicht minder komfortabler Steuerung über die Benutzeroberfläche.

Wozu braucht man überhaupt diese Unterscheidung nach unterschiedlichen Inhaltstypen?

Das ist für einen einfachen Quasselblog erstmal noch nicht notwendig, man kann ja seine Beiträge über die WordPress-Kategorien sehr feinkörnig und sogar hierarchisch logisch gruppieren. Das Kategoriensystem von WordPress ist sogar besonders ausgefeilt und komfortabel in der Bedienung, da haben sich die Core-Programmierer wirklich was einfallen lassen.

Es stellt sich aber bei den meisten Blogs mit der Zeit heraus, dass der ursprünglich vorgesehene Rahmen nach einiger Laufzeit zum zu engen Korsett wird. Einfaches Beispiel: dieser Blog hier, der vor anderthalb Jahren als reiner WordPress-Plauderblog angefangen hat. Mit der Zeit kamen dann noch andere Themen dazu, reine PHP- oder MySQL-Topics zum Beispiel, oder auch vor ein paar Monaten die Beitragsserie über Joomla. Wenn ich da gleich sauber gearbeitet hätte, hätte ich mir gleich einen neuen Beitragstyp für jedes neue Thema angelegt, da hab ich geschlampert und versucht, das über den Kategorienbaum zu steuern. Hat jetzt nicht gerade zur Übersichtlichkeit beigetragen, ich gebs ja zu. Ob ich das jetzt nachträglich noch umbauen möchte weiss ich noch nicht, aber schöner wärs schon man hätte für jedes Haupthema eine eigene Blogseite, und auch eine eigene Kategorisierung oder auch Stichwort-Verwaltung.

Wieso – ist denn WordPress MultiBlog-fähig?

Ein definitives „Im Prinzip ja“. Es geht halt nicht so ohne weiteres über die Benutzeroberfläche, man kommt nicht darum herum in die functions.php einzugreifen oder sich ein Plugin zu schreiben. Aber gehen tuts – mit Custom Post Types. Es ist noch nicht einmal besonders schwierig, und Tante Google liefert auch jede Menge Artikel zu dem Thema. Besonders informativ fand ich diesen Beitrag bei Elmastudio,  und auch der Beitrag hier von drweb bringt ordentlich Licht in die Sache. Mit den Custom Post Types in einem Atemzug werden häufig die Custom Taxonomies angesprochen, das klingt erstmal kompliziert, ist aber eigentlich auch nicht weiter schwierig. Man kann sich damit eigene Kategorie- und Stichwort-Logiken für die neuen Post Types anlegen, das ist sehr nützlich und absolut praxistauglich.

Wir gehens hier aber mal langsam und der Reihe nach an. Ich nehme als Beispiel wieder mein Inselfisch-Kochbuch, da haben wir gleich einen praktischen Einsatz.

Wozu jetzt einen neuen Beitragstyp?

Im Inselfisch-Kochbuch sind die Beiträge meine Rezepte, und das ist gut eingefahren und funktioniert auch prächtig. Die Anwender finden sich gut zurecht, das Kategoriensystem ist in der Praxis bewährt und sowohl übersichtlich als auch informativ. Welche Inhalte also habe ich, die einen neuen Beitragstyp sinnvoll machen würden? Na, die Kochbücher! Die habe ich auf statische Seiten gelegt, und das ist weder besonders übersichtlich für die Anwender (ellenlanges Aufklappmenü) noch für mich komfortabel zu pflegen. Ich hätte ja noch eine ganze Latte Kochbücher, die ich auch gern einstellen würde, aber da jedesmal das Menü wieder umzustricken ist mir echt zu aufwendig. Da wäre es doch viel schöner, ich könnte im Blog-Stil meine Kochbücher der Reihe nach reinklopfen und immer wieder dynamisch welche dazuschreiben… ja, auf gehts!

Wie soll der neue Post Type Kochbuch aussehen?

Eigentlich auch nicht anders als jeder andere WordPress-Beitrag. Titel, Beschreibung, gegebenenfalls ein Bild. Dazu noch Autor und Verlag, gegebenenfalls der Preis und  die Seitenzahl – aber das muss jetzt nicht in eine strikte Logik gepackt werden, das hat alles im Inhalt Platz. Interessanter ist es dann schon, die Kochbücher nach Herkunftsland (Bayern, USA, Asien…) zu gruppieren, dafür werde ich eine eigene Logik basteln. Und dann nehmen wir noch eine Stichwortverwaltung mit rein, in der könnte sowas stehen wie: Nachschlagewerk, Lesefutter, Grundrezepte, Spezialitäten, Für Anfänger, für Profis… das kommt dann beim Eintragen der Kochbücher, da wird sich noch einiges finden. Für die Herkunftsländer macht eine hierarchische Kategorien-Logik Sinn (Asien/Thailand, Asien/China…), für die Stichwörter (irgendwie logisch) die Stichwörter. Das legen wir uns jetzt mal der Reihe nach an.

Definition des neuen Post Types Kochbuch in der functions.php

Da können wir so gut wie alle WordPress-Beitragseigenschaften übernehmen, deswegen wird die Definition relativ kurz und knackig:

function post_type_kochbuch() {
    register_post_type(
                'kochbuch',
                array(
                    'label' => __('Kochbuch'),
                    'public' => true,
                    'show_ui' => true,
                    'supports' => array(
                    'title',
                    'editor',
                    'post-thumbnails',
                    'custom-fields',
                    'revisions')
                )
        );
}
add_action('init', 'post_type_kochbuch');

Damit ist der neue Post-Type auch schon angelegt und taucht bereits im Admin-Menü auf:

kochbuch_admin

kochbuch_admin

Man kann auch schon mal testweise einen neuen Eintrag vom Typ Kochbuch anlegen, aber wenn man ihn anschauen will, kommt wahrscheinlich die 404-Fehlermeldung. Wir machen auch erst mal noch was anderes:

Ein Template für den neuen Post Type anlegen

Dafür klemmt man sich die archive.php aus dem Parent-Theme und macht eine Kopie mit dem Namen archive-kochbuch, die legt man ins ChildTheme-Verzeichnis. Zuerst ändert man den Templatenamen:

/**
 * Template Name: Kochbuch Archive pages
 *
 */

Dann ergänzt man den Code unmittelbar vor dem Loop um eine Zeile, so daß WordPress auch den richtigen Post Type anzieht:

<?php query_posts(array('post_type'=>'kochbuch')); ?>
            <?php
            /* Start the Loop */
            while ( have_posts() ) : the_post();

Jetzt noch im Dashboard unter Einstellungen/Permalinks einmal die Permalink-Einstellungen speichern. Jetzt sollte man sich den eben erstellten ersten Kochbuch-Beitrag auch angucken können.

Eine eigene Seite für die Kochbücher erstellen

Neue Seite erstellen, ich nenn sie mal einfach Kochbücher. Wenn alles geklappt hat, kann man jetzt bei den Templates das soeben erstellte Kochbuch-Template anwählen:

kochbuch_template

kochbuch_template

Damit werden auf dieser Seite automatisch alle Beiträge vom neuen Post Type Kochbuch angezeigt. Diese Seite fügt man sich jetzt noch in sein Menü ein, und schon kann man loslegen.

Jetzt fehlt noch ein bisschen Feintuning, zum Beispiel möchte ich noch die Herkunftsländer und die Stichworte haben, aber dafür gibt es einen neuen Beitrag.

 

Ne kleine Fingerübung: Beitragshitparade mit AJAX-Refresh

Weil ich mich dabei erwischt habe, dass ich immer wieder F5 drücke, wenn ich meine Beitragshitparade anschaue, bin ich auf die Idee gekommen, den Refresh der Anzeige alle x Sekunden automatisch einzubauen. Das geht in WordPress ganz flott, hatten wir auch alles so ähnlich schonmal, aber weil man so etwas immer wieder mal brauchen kann, hier der Code.

Wir basteln uns dafür natürlich ein Plugin

In das kommt zuallererst ein sehr kurzer Shortcode, der macht eigentlich nichts anderes als eine benannte Div  für die Ausgabe bereitzustellen.

<?php
/*
Plugin Name: Ajax Hitparade
Plugin URI: http://localhost/wp_ajax/wp-content/plugins/wp-ajax
Description: Ausgabe der beliebtesten Beiträge mit Ajax Refresh
Version: 1.0
Author: Evi Leu
Author URI: http://www.evileu.de
*/


 function a_ausgabe(){
  return "Die 10 beliebtesten Rezepte<br><div id='ajax_ausgabe'>...</div>";
  
 }
 add_shortcode('ajax_ausgabe', 'a_ausgabe');

Dann geben wir WordPress bekannt, dass wir einen Ajax-Call ausführen wollen:

/**************ajax-action für wordpress definieren*/ 
add_action( 'wp_ajax_hitparade_action', 'hitparade_action' );
add_action( 'wp_ajax_nopriv_hitparade_action', 'hitparade_action' );


Das Javascript

Jetzt binden wir unsere js-Datei mit dem Script ein, und geben ihr mit dem wp_localize_script den Pfad zur Ajax-URL von WordPress mit:

/*********Externes Script einbinden und Pfad zur admin-ajax.php übergeben*/
function myhitparade_js() {
      
    wp_enqueue_script('myhitparade-js', plugins_url().'/ajax-hitparade/wp_ajax_hitparade.js', array('jquery'), false, false);
    
    wp_localize_script( 'myhitparade-js', 'my_ajaxurl', admin_url( 'admin-ajax.php' ) );
 
   }
add_action('wp_enqueue_scripts', 'myhitparade_js');

Die Script-Datei wp_ajax_hitparade.js liegt in unserem Plugin-Verzeichnis und sieht so aus:

$(document).ready(function() {
     setInterval(myFunction, 1000)  
       
    });
    
        
        function myFunction(){
                
        
        var data = {
            'action': 'hitparade_action',
            
            };

        // der volle Pfad zur admin-ajax.php liegt auf my_ajaxurl
        jQuery.post(my_ajaxurl, data, function(response) {
                    
            document.getElementById("ajax_ausgabe").innerHTML = response;
            
        });
        } //*********************End myFunction

Der Witz ist hier natürlich das setInterval(), das führt unsere Funktion alle X Millisekunden aus. Ansonsten geben wir der Funktion nur mit, dass sie die Callback-Funktion hitparade_action ausführen soll, es gibt keine zu übergebenden Parameter ausser der Ajax-URL. Das Ergebnis des Calls wird in die div ajax_ausgabe geschrieben.

Die Callback-Funktion

Kommt als Letztes in unser Plugin, sie ist sehr simpel und besteht nur aus einer Query auf die Tabelle Counter und einem foreach für die Ausgabe:

/********Callback-Funktion**************/
function hitparade_action() {
    global $wpdb; 
  
    $alleposts = $wpdb->get_results( "SELECT * from counter ORDER BY zaehler DESC limit 10");
    foreach($alleposts as $einpost){
        
        echo $einpost->titel." ".$einpost->zaehler."</br>";
}
    /**********************************************/
    
    
    wp_die(); // this is required to terminate immediately and return a proper response
} //**********End function hitparade_action

Das sollts gewesen sein! Das Script checkt alle 1000 Millisekunden die Datenbank neu ab und aktualisiert die Anzeige dementsprechend. Viel Spaß beim Nachbauen!

PHP 5.6 forever? Und kleine Auswertung des Rezeptecounters

Also, ich geb zu das hat mit WordPress nur am Rande was zu tun, aber ich denke mir dass andere Leute vor dem selben Dilemma stehen und werde deswegen ein paar Worte zu dem Thema verlieren.

Man ist ja mittlerweile bei PHP 7.x angelangt, und es hat sich seit den 5er Versionen einiges getan, besonders in Sachen Datenbankzugriff. PDO und mysqli hat mysql abgelöst, und wir sind nicht abwärtskompatibel. Das würde mir noch nicht mal viel ausmachen, weil ich auf meiner evileu.de kaum PHP-Skripte für den Datenbankzugriff benutze, das läuft eigentlich alles über WordPress. Aber an manchen Stellen kneifts dann doch, und besonders für meine kleinen SEO-Statistiken hätt ich dann doch das eine oder andere PHP-Script gebraucht. Lokal (XAMPP) arbeite ich schon lang mit PHP 7 und hab eigentlich gar nicht mehr darüber nachgedacht ob ich die 5er Version nochmal brauchen könnte.

Aber die Live-Seite evileu de läuft bei meinem Provider (Strato) noch auf PHP 5.6, und das wird wohl auch so bleiben. Ein Anruf bei der Hotline hat ergeben, daß von einer Umstellung auf PHP 7.x dringendst abgeraten wird, weil es keine Garantie dafür gibt, dass vorhandene Webseiten dann noch laufen. Der Hotliner meinte sogar, dass in den meisten Fällen die Webseiten neu aufgesetzt werden müssten… Vielleicht bin ich da auch nur übervorsichtig, WordPress sollte ja eigentlich mit den neuesten PHP-Versionen klarkommen, aber „der Teufel ist ein Oachkatzl“ – weiss man’s genau?

Jedenfalls rät Strato von einer Umstellung dringend ab, und ich bekam auch die Auskunft dass bei denen noch 99,9% aller Webseiten auf PHP 5.6 laufen. Tscha, da werde ich mich wohl der Mehrheit anschliessen, schon auch weil es bei Umstellungsproblemen der PHP-Version von Strato keinen Support gibt, jedenfalls nicht an der kostenfreien Hotline. Bin bloss gespannt wie lange WordPress die Grätsche noch mitmacht – irgendwann wird es eine Version geben, die nur noch auf PHP 7.x läuft, und dann wirds echt spannend.

Was mach ich bis dahin? Plugins und Shortcodes statt PHP-Scripte nutzen, wo immer es möglich ist, weil ich beim Programmieren Knoten in die Tippfinger kriege, wenn ich ständig zwischen PHP 5 und 7 wechseln muss. Gefallen tut mir das nicht, aber ich hab ja etwa ein Dutzend WordPress-Blogs am Laufen, und da will ich nicht das geringste Risiko eingehen. Also, PHP 5.6 forever – obs mir gefällt oder nicht.

PHP-5-Script für die Auswertung des Rezeptecounters

Für alle, die es auch nicht mehr parat haben, wie das mit dem mysql_connect damals so ging, hier ein kleines Script zur Auswertung der counter-Tabelle (siehe dieser Beitrag zum Rezeptecounter) Die Tabelle ist ja recht einfach aufgebaut:

tabelle_counter

tabelle_counter

Fehlte eigentlich nur noch die Aufsummierung der Gesamtzahl der Aufrufe, das erledigen wir hier gleich in einem Aufwasch:

$dbh = mysql_connect("[hostname]", "[db user]", "[password]");
$query = "[db name]";
if (!mysql_query($query, $dbh)) die("Fehler bei der Datenbankverbindung.");

//Gesamtaufrufe summieren***********************
$abfrage = "select sum(zaehler) as summe from counter";
$ergebnis = mysql_query($abfrage,$dbh);

while($row = mysql_fetch_assoc($ergebnis))
{
echo "<h2>Seitenaufrufe seit 20.6.2018: ".$row['summe']."</h2>";
}

//*********************

$sql = "SELECT * FROM counter ORDER BY zaehler DESC";

$result = mysql_query($sql);

while ($row = mysql_fetch_assoc($result)) {
    echo $row["cid"]." ";
    echo $row["rezeptid"]." ";
    echo $row["titel"]." ";
    echo "Z&auml;hler: ".$row["zaehler"]."<br>";
}

mysql_free_result($result);
?>

Das liefert einen ganz netten Überblick, hier die Zahlen von hier im Bistro seit gestern:

ausgabe_rezeptecounter

ausgabe_rezeptecounter

Ich gebe zu man könnte es schöner formatieren, aber mir langt das für einen groben Überblick. Ist echt eine Alternative zum Visitor Counter, der ja leider wegen der DSGVO weg musste.

Der Shortcode für die Rezepthitparade

… musste auch nur um zwei Zeilen ergänzt werden, damit er die Gesamtzahl der Aufrufe mit ausgibt:

function el_rezepthitparade(){
    global $wpdb;
    echo "<h2>Die 10 beliebtesten Rezepte</h2>";
    
    $gesamt = $wpdb->get_var("SELECT SUM(zaehler) FROM counter");
    echo $gesamt." Rezeptaufrufe seit Beginn der Zählung Juni 2018<br>";
    
    $alleposts = $wpdb->get_results( "SELECT * FROM counter 
    ORDER BY zaehler DESC LIMIT 10");
    foreach ($alleposts as $einpost){
        
        $pfad = get_the_permalink($einpost->rezeptid);
        echo "<a href = '".$pfad."'>".$einpost->titel."</a> (".$einpost->zaehler.")<br>";
    }
}
add_shortcode('hitparade','el_rezepthitparade');

Den get_var kann man hier einwandfrei nutzen, weil nur ein Wert von der Query zurückgegeben wird, den kann man dann auch gleich direkt mit echo ausgeben.

Nachtrag für Zählung der Seitenaufrufe

Mein Rezeptecounter ist schon fleissig im Einsatz, und ich bin mit den aussagekräftigen Ergebnissen sehr zufrieden. Nur noch eine kleine Ergänzung: in meinem Handarbeitsblog ist es für mich auch interessant zu wissen, welche statischen Seiten wie oft aufgerufen werden. Die kommen mit einer ganz kleinen Ergänzung der Zähler-Function mit in die counter-Tabelle. Statt nur if (is_single())… frage ich ab if(is:single() or is_page()), und schon sind die statischen Seiten auch mit in der Statistik.

Noch’n Nachschlag: Aufrufe pro Tag

Ich hab in meinem Archiv gekramt und eine Funktion aus dem Selfphp-Forum ausgebuddelt, mit der man die exakte Anzahl von Tagen zwischen zwei gegebenen Tagesdaten ermitteln kann. Die nutzen wir doch gleich mal um einen Tagesdurchschnitt auszurechnen. Das Startdatum der Zählung wird einfach fest eingegeben, das Enddatum (aktueller Tag) mit der date()-Funktion erzeugt, die Gesamtzahl der Aufrufe haben wir ja aus der Query, die liegt auf der Variablen $gesamt.

$gesamt = $row['summe'];
$timeA = '20.06.2018'; 
 $timeB = date("d.m.Y"); 

 $differenz = seDay($timeA,$timeB,"dmY","."); 
 
echo '<h3>In ' . $differenz . ' Tagen '.$gesamt.
" Aufrufe, das macht im Durchschnitt ".round(($gesamt/$differenz))." Aufrufe pro Tag</h3>";

Die Funktion seDay könnt ihr hier nachschlagen:  http://www.selfphp.de/kochbuch/kochbuch.php?code=11

Viel Spaß beim Nachbauen!