Einen Shortcode durch einen Block ersetzen, mit so wenig und so einfachem Code wie möglich

Mitte der Woche hatte Topher auf Twitter eine interessante Frage zum aktuellen Stand der Block-Entwicklung gestellt:

Click here to display content from Twitter.
Erfahre mehr in der Datenschutzerklärung von Twitter.

Übersetzung: Ich habe es mir schon lange nicht mehr angesehen, ist es schon so einfach einen Gutenberg Block zu schreiben wie einen Shortcode?

Das hat mich ein wenig zum Nachdenken gebracht, wie ich diese Frage übersetzen würde. Als ich meine ersten Blöcke geschrieben habe, waren es meisten „Server-Side-Rendered-Blocks“. Bei diesen Blöcken wird der Inhalt nicht direkt im Editor erzeugt, sondern von PHP-Code in einer Callback-Funktion gerendert, so wie man es von Shortcodes her kennt.

Der andere komplizierte Teil bei der Entwicklung von Blöcken ist die Notwendigkeit so viele neue Dinge zu lernen: React, JSX, Kompilierung von modernem JavaScript mit webpack und vieles mehr. Das alles zusammen macht es eben nicht „so einfach“ wie die Arbeit mit Shortcodes. Aber ich sollte dennoch einmal zeigen, wie man mit wenig Code einen Block entwickeln kann, der einen Shortcode ersetzt, ohne dabei all diese neuen Dinge lernen zu müssen.

Einen Server-Side-Rendered-Block entwickeln – der PHP Teil

Der einfachste Teil ist die Registrierung des Blocks und der Render-Callback-Funktion in PHP. Während man bei einem Shortcode die Funktion add_shortcode()für die Callback-Funktion verwenden würde, ist es ein Parameter bei der Registrierung eines Blocks in PHP:

function rpssrb_init() {
	register_block_type(
		'rpssrb/random-posts',
		[
			'render_callback' => 'rpssrb_render_callback',
		]
	);
}
add_action( 'init', 'rpssrb_init' );

Für diesen Blogbeitrag erstellen wir einen Block, der zufällig ein paar Beiträge rendert. Der Inhalt der Callback-Funktion ist hier sehr ähnlich zu der eines Shortcodes. Ihr könnt auch die gleichen Hilfsfunktionen wie bei einem Shortcode verwenden. Der Callback könnte wie folgt aussehen:

function rpssrb_render_callback( $atts ) {
	$atts = shortcode_atts(
		[
			'post_type'      => 'post',
			'orderby'        => 'rand',
			'posts_per_page' => 5,
		],
		$atts
	);

	$query = new WP_Query( $atts );

	$output = '';
	if ( $query->have_posts() ) {
		$output .= '<ul>';
		while ( $query->have_posts() ) {
			$query->the_post();
			$output .= sprintf(
				'<li><a href=%s>%s</a></li>',
				get_permalink(),
				get_the_title()
			);
		}
		$output .= '</ul>';
	}

	return $output;
}

Wir setzen ein paar Standard-Attribute und führen dann eine WP_Query aus, um 5 zufällige Beiträge zu bekommen. Diese geben wir dann in einer einfachen unsortierten Liste aus, wobei wir einfach den Titel ausgeben und auf den Beitrag verlinken.

Implementierung des Blocks in JavaScript – nur mit ES5 Code

Wie schon zuvor erwähnt ist das schwierigste bei der Block-Programmierung das Erlernen von React, JSX usw. und die Kompilierung davon. Wenn ihr euch damit noch nicht auskennt, kann es wirklich kompliziert werden. Daher zeige ich euch hier, wie ich mit etwas ES5 („altem JavaScript“) einen Block schreiben könnt. Das sieht im einfachsten Fall wie folgt aus:

wp.blocks.registerBlockType(
	'rpssrb/random-posts',
	{
		title: 'Random Posts',
		edit: function () {
			return wp.element.createElement(
				wp.serverSideRender,
				{
					block: 'rpssrb/random-posts'
				}
			);
		}
	}
);

Wir verwenden die wp.blocks.registerBlockType Funktion im ES5-Stil und geben ansonsten nur einen title und eine edit Funktion an. In dieser Funktion erstellen wir dann ein React-Element mit der wp.serverSideRender Komponente.

Die edit Funktion wird verwendet, um den Inhalt des Blocks im Editor anzuzeigen (in unserem Fall also das Ergebnis des PHP-Callback-Funktion). Wir brauchen diese Funktion nicht einmal zwingen, würden dann aber nichts im Block-Editor sehen (der Block würde aber auch keinen Raum einnehmen, da er leer ist), im Frontend würden wir aber die Ausgabe sehen.

Laden der JavaScript-Datei

Dieser JavaScript-Code muss nun geladen werden, wenn der Block-Editor verwendet wird. Falls ihr schon eine Datei habt, die im Block-Editor geladen wird, könnt ihr den Code in diese Datei speichern. Ansonsten ladet ihr die Datei einfach wie jede andere, verwendet dabei aber einen anderen Hook:

function rpssrb_register_scripts() {
	wp_enqueue_script(
		'random-posts-server-side-render-block',
		plugin_dir_url( __FILE__ ) . 'index.js',
		[ 'wp-blocks', 'wp-server-side-render' ],
		filemtime( plugin_dir_path( __FILE__ ) . 'index.js' ),
		true
	);
}
add_action( 'enqueue_block_editor_assets', 'rpssrb_register_scripts' );

In den Abhängigkeiten fügen wir noch wp-blocks und wp-server-side-render, wobei diese eigentlich normalerweise ohnehin geladen werden, wenn der Block-Editor verwendet wird.

Bonus: auch einen Shortcode verwenden

Da wir schon eine Callback-Funktion geschrieben, die genau so auch bei einem Shortcode genutzt werden kann, können wir mit einer einzelnen weiteren Zeile diese auch als Shortcode nutzbar machen (z.B. mit dem Shortcode-Block):

add_shortcode( 'rpssrb_random_posts', 'rpssrb_render_callback' );

Einschränkung: die Verwendung von Attributen ist kompliziert!

Der Block, den wir gebaut haben, kann keine Attribute verwenden. Diese zum Bock hinzuzufügen wäre einfach, dafür dann aber Kontroll-Elemente für eine einfache Verwendung zu implementieren ist nicht so einfach. Es wäre zwar mit ES5 möglich, aber ich würde dies nicht empfehlen.

Konsequenz: Learn JavaScript, deeply.

Wie uns Matt beim WCUS 1015 als Hausaufgabe mitgegeben hat, würde auch ich sehr empfehlen, mit dem Lernen von modernem JavaScript anzufangen. Der schwierigste Teil ist am Anfang dabei die Kompilierung mit webpack. Falls ihr gar keine Idee habt, wie ihr starten sollt, dann würde ich der Antwort von Birgit auf den Tweet zustimmen: verwendet das create-block Paket.

Mit dem create-block Paket könnt ihr nicht nur einen funktionierenden Block innerhalb eines WordPress Plugins erstellen, es installiert euch auch all die JavaScript-Pakete, die ihr für die Kompilierung von modernem JavaScript benötigt. Dazu verwendet es das @wordpress/scripts Paket und da Haupt-Skript, das ihr hiervon verwenden würdet, ist das start Skript. Versucht es einfach mal selbst aus und lest ein wenig in der Dokumentation, wie man Attribute hinzufügt, um euren Block noch einfacher nutzbar zu machen.

Fazit: einen Block zu erstellen ist einfach, aber es reicht eventuell nicht aus

Während ihr also einen Block schreiben könnt, der nur eine PHP-Datei und eine JavaScript-Datei mit ES5-Syntax benötigt, würde ich es auch nicht unbedingt empfehlen. Sobald ihr euch einmal mit den Grundlagen der Block-Erstellung vertraut gemacht habt, könnt ihr die Nutzbarkeit erheblich verbessern. Es klingt sicher am Anfang etwas einschüchternd und ihr werdet sicher in alle möglichen Fehler laufen, aber es ist es wert.

Falls ihr den vollständigen Code zu diesem Beitrag sehen wollt, dann findet ihr ihn auf GitHub als Plugin.

Veröffentlicht von

Bernhard ist fest angestellter Webentwickler, entwickelt in seiner Freizeit Plugin, schreibt in seinem Blog über WordPress und andere Themen, treibt sich gerne bei den WP Meetups in Berlin und Potsdam herum und läuft nach Feierabend den ein oder anderen Halbmarathon.

2 Kommentare » Schreibe einen Kommentar

  1. Hallo Bernhard,
    ja leider ist es mit ein wenig PHP nicht mehr getan.
    Ich habe mir über die Jahre auch einige Shotcodes geschrieben, die ich gerne in Blöcke umwandeln würde. Ich bin aber Blogger und kein Programmierer, deshalb lohnt sich der Lernaufwand nicht.
    Schade. Ein Block zum Block-Erstellen wäre praktisch 🙂

    lg
    Jochen

    • Hallo Jochen,

      für eine Shortcodes ohne Attribute reicht PHP und ein wenig JavaScript aus. Für umfangreiche Shortcodes aber wie beschrieben leider nicht.

      Die meisten, die nur Bloggen, werden aber auch sicher keine eigenen Shortcodes verwenden, denn auch dafür muss man zumindest PHP programmieren können.

      Glücklicherweise gibt es ja schon sehr viele frei nutzbare Blöcke für alle möglichen Anwendungsfälle. Oder aber man verwendet die diversen Tools/Pluigns, um Blöcke nur mit PHP zu entwickeln. Damit verliert man dann aber viele Funktionen, die native Blöcke mit React bieten und man macht sich abhängig von einem Tool/Plugin. Daher meine Empfehlung sich in die Grundlagen der Block-Entwicklung einzuarbeiten.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.