Shortcodes: echo vs. return

Ich arbeite ja gern mit Shortcodes und packe da auch oft komplexere Funktionalitäten rein, weil sie so praktisch sind. Wenn man allerdings Shortcodes in Beiträge einbinden will, die auch noch Text enthalten, muss man ein bisschen aufpassen mit den Ausgaben, wo man echo und wo man return verwendet, sonst kann es zu unerwünschten Effekten kommen. Ich mach mal ein einfaches Beispiel.

Simpler Shortcode mit return:

function el_harmlosertext(){
    return "<strong>Ich bin ein komplett harmloser ShortcodeText</strong>";
}
add_shortcode('harmlos','el_harmlosertext');

Den kann man im Fliesstext platzieren wo man will, er wird an der richtigen Stelle ausgeführt. Im Editor sieht das so aus:

editor

editor

Das erzeugt diese Bildschirmausgabe:

bildschirm

bildschirm

Ändert man jedoch den Shortcode und macht aus dem return ein echo, funktioniert das nicht mehr, die Ausgabe erfolgt vor dem Fliesstext des Artikels.

vor_fliesstext

vor_fliesstext

Das ist etwas irritierend, und komplett lästig wird es, wenn man zum Beispiel die Ergebnisse einer Datenbankabfrage ausgeben möchte, die nicht so ohne weiteres in ein return-Statement zu packen sind. Ich stricke mal eine kurze Liste aller bisher veröffentlichten Posts, und möchte diese am Ende meines Beitrags ausgeben. Der Shortcode sieht erstmal so aus:

function el_mit_datenbankabfrage(){
    
     global $wpdb;
            
      //Bisherige Anzahl posts holen
        $alleposts = $wpdb->get_results( "SELECT * from wp_posts where post_status like 'publish'");
        $anzahl = $wpdb->num_rows;
        echo $anzahl." Datensätze gefunden und mit echo ausgegeben<br>";
        $ausgabe = array();
        $i=0;
        foreach($alleposts as $einpost){
            echo $einpost->post_title."<br>";
            
        }
       
}
add_shortcode('db_abfrage','el_mit_datenbankabfrage');

Hier kann man das echo nicht einfach mit einem return ersetzen, weil sonst der foreach nach dem ersten Durchgang abbricht. So lassen kann man es aber auch nicht, weil die Liste so wie der Shortcode jetzt aussieht immer vor dem Fliesstext des Artikels ausgegeben wird:

echo_vor_text

echo_vor_text

Abhilfe: wir packen die Ausgaben des foreach in einen String und verketten den innerhalb der Schleife. Die Funktion des Shortcodes wird wie folgt geändert:

function el_mit_datenbankabfrage(){
    
     global $wpdb;
            
      //Bisherige Anzahl posts holen
        $alleposts = $wpdb->get_results( "SELECT * from wp_posts where post_status like 'publish'");
        $anzahl = $wpdb->num_rows;
        echo $anzahl." Datensätze gefunden und mit echo ausgegeben<br>";
        $ausgabe = "";
       
        foreach($alleposts as $einpost){
            $ausgabe=$ausgabe.$einpost->post_title."<br>";
            
        }
        
    return "Mit return ausgegeben:<br>".$ausgabe;
}

Diesen String gebe ich dann mit dem return der Shortcode-Funktion zurück, und meine Liste wird brav ans Ende des Beitrags gestellt, da wo ich sie auch haben will.

return

return

Ich könnte die Ausgabe auch mitten im Text platzieren, funktioniert auch. Man sieht hier auch noch, dass die mit echo ausgegebene Anzahl der Datensätze gnadenlos vor dem Beitragstext landet:

mitten_im_text

mitten_im_text

Das ist alles natürlich nur relevant, wenn man den Shortcode auf einer Seite oder auf einem Beitrag platzieren möchte, die sonst auch noch Text enthalten, bei sonst leeren Posts/Pages ist es egal. Wissen muss man halt, dass return und echo hier völlig unterschiedliche Effekte in der Ausgabe erzielen, dann kann man auch gegensteuern.