WordPress: „get_post_meta()“ – der Sonderfall 0

Alexander Trust, den 14. Januar 2016
Wordpress - Logo
Wordpress – Logo

WordPress speichert alle zusätzlichen Metadatenfelder in der Datenbank als Daten des Typs longtext, egal ob man Zahlen oder Text speichert. Trotzdem gibt es den merkwürdigen Sonderfall „0“, der Funktionen ohne eine angepasste Gelingensbedingung lahmlegen kann.

Aus Schaden wird man klug, heißt es. Da ich die gesamte letzte Nacht damit verbracht habe, herauszufinden, warum ein eigens angefertigtes Sidebarwidget keine Werte ausgibt, möchte ich an dieser Stelle anderen diesen Zeitaufwand ersparen und den komischen Sonderfall vorstellen.

get_post_meta()

Wenn man in WordPress mit Metadaten arbeitet, dann erreicht man diese mit Hilfe der get_post_meta()-Funktion. Im WordPress-Codex heißt es, dass ein einfaches

if(get_post_meta($post->ID, 'ng_game_cover', true)) {
...
}

ausreicht, um festzustellen, ob ein Metafeld verfügbar ist, oder nicht. Das ist, wie ich letzte Nacht feststellen musste, leider nicht ganz richtig.

Warum ist „0“ denn leer?

Ich bastle derzeit eine neue Webseite, die einen Mix aus Magazin und Lexikon darstellen soll. Deshalb gibt es darin stink normale Beiträge, aber auch solche, die ein bisschen der Wikipedia nachempfunden sind.
In der Seitenleiste meiner Lexikon-Beiträge wird es Tabellen mit Informationen geben, zu Firmen, Personen, etc. Spätestens als ich die dritte Tabellenzeile tippte, dachte ich bereits – eine Funktion muss her. Und also fügte ich eine zu meiner functions.php hinzu. Im Template selbst rufe ich die Funktion auf, die mir dann eine fertige Tabellenzeile zurückgibt.

Meine Funktion sah anfangs so aus:

function singleMetaOutput($meta,$label,$type = 'normal') {
    if(!empty(get_post_meta(get_the_ID(), $meta, true)) {
        $output  = '<tr>';
        $output .= '<td>'.$label.'</td>';
        switch ($type) {
            case "normal":
                $output .= '<td>'.get_post_meta(get_the_ID(), $meta, true).'</td>';
                break;  
            case "twitter":
                $output .= '<td><a href="https://twitter.com/'.get_post_meta(get_the_ID(), $meta, true).'" target="_blank">@'.get_post_meta(get_the_ID(), $meta, true).'</a></td>';
                break;
            case "url":
                $output .= '<td><a href="'.get_post_meta(get_the_ID(), $meta, true).'" target="_blank">'.get_post_meta(get_the_ID(), $meta, true).'</a></td>';
                break;
        }
        $output .= '</tr>';
        return $output;
    } else {
        return;
    }
}

Der Aufruf zum Beispiel für das Feld mit den Werten für die USK-Altersangabe erfolgt dann über:

<?php echo singleMetaOutput('ng_game_usk','USK'); ?>

Da es sich bei meiner Webseite um eine über Videospiele handelt, liegt es nahe, Alterseinstufungen auszugeben. Über spezielle Metaboxen im Adminbereich von WordPress füge ich dutzende Metainformationen zu meinen Custom Post Types hinzu. Ich staunte allerdings nicht schlecht, als Spiele, bei denen die USK-Einstufung mit „0“ ausgewählt war, diesen Wert nicht in der Tabelle ausgaben.

Infotabelle mit USK-Altersangabe

Dummerweise ist mir das erst aufgefallen, nachdem ich meine Funktion fertiggestellt habe. Tests mit anderen Custom Post Types für Firmen bspw. verliefen positiv, also wunderte ich mich, warum denn bei den Spielen das USK-Feld nicht ausgegeben wird. Die Testdaten, die ich verwendete, hatten häufig USK 0 ausgewählt, und so kam eines zum anderen: Natürlich untersuchte ich die Funktion, schrieb sie um, fügte sie direkt in das Template ein, änderte Zeile für Zeile, gab Hilfsvariablen auf dem Bildschirm aus und den Inhalt von Arrays, nur um am Ende festzustellen, dass WordPress den Wert „0“ wohlgemerkt als Zeichenkette als Sonderfall behandelt. Hatte ich bei Spielen USK 6, 12 oder 18 eingestellt, wurde der Wert angezeigt. Doch darauf kam ich erst später. Wenn man mit einem Textfeld hantiert, hat man nicht spontan die Vermutung, dass eine 0 mit einem „leeren“ Ergebnis gleichgesetzt würde. Doch genau dies tut WordPress. Leider. Also musste ich den Spezialfall in meiner Gelingensbedingung für die Funktion berücksichtigen und sie wie folgt umschreiben:

function singleMetaOutput($meta,$label,$type = 'normal') {
    if(get_post_meta(get_the_ID(), $meta, true) == '0' || !empty(get_post_meta(get_the_ID(), $meta, true))) {
        $output  = '<tr>';
        $output .= '<td>'.$label.'</td>';
        switch ($type) {
            case "normal":
                $output .= '<td>'.get_post_meta(get_the_ID(), $meta, true).'</td>';
                break;  
            case "twitter":
                $output .= '<td><a href="https://twitter.com/'.get_post_meta(get_the_ID(), $meta, true).'" target="_blank">@'.get_post_meta(get_the_ID(), $meta, true).'</a></td>';
                break;
            case "url":
                $output .= '<td><a href="'.get_post_meta(get_the_ID(), $meta, true).'" target="_blank">'.get_post_meta(get_the_ID(), $meta, true).'</a></td>';
                break;
        }
        $output .= '</tr>';
        return $output;
    } else {
        return;
    }
}

Vorher hat meine Funktion den Wert „0“ im Feld USK wegen WordPress‘ Eigenart als leer interpretiert. Nun frage ich mit get_post_meta(get_the_ID(), $meta, true) == '0' explizit ab, ob der Wert „0“ ist und lasse die Funktion auch in diesem Fall weiterarbeiten.

Wer hätte gedacht, dass WordPress die Zeichenkette 0 dermaßen falsch interpretiert…


Ähnliche Nachrichten