Bist du immer noch verwirrt von Gutenberg? Oder gehörst du zu denjenigen, die fest an das Potenzial des Blockeditors glauben und herausfinden wollen, wie weit sie ihre Kreativität mit dem Blockeditor treiben können?

Egal, zu welcher Kategorie du gehörst, Gutenberg ist da und dieser Beitrag gibt dir einen detaillierten Überblick darüber, was hinter den Kulissen des WordPress-Blockeditors vor sich geht. Aber das ist noch nicht alles!

Nach unserem letzten Tutorial, in dem wir eine allgemeine Einführung in die Entwicklung von Gutenberg-Blöcken gegeben haben, geht dieser Artikel über die Grundlagen hinaus und stellt fortgeschrittenere Blocktypen vor. Diese Blöcke werden als dynamische Blöcke bezeichnet.

Heute erfährst du, was dynamische Blöcke sind, wie sie funktionieren und was du wissen musst, um dynamische Blöcke von Grund auf zu erstellen.

Was sind also dynamische Blöcke in Gutenberg und was sind die wichtigsten Unterschiede zwischen statischen und dynamischen Blöcken?

Was sind dynamische Blöcke? Ein Beispiel

Während bei statischen Blöcken der Inhalt manuell vom Nutzer hinzugefügt wird, während er einen Beitrag oder eine Seite bearbeitet, wird der Inhalt bei dynamischen Blöcken beim Laden der Seite geladen und verarbeitet. Bei dynamischen Blöcken wird der Inhalt des Blocks aus der Datenbank geholt und so angezeigt, wie er ist oder wie er sich aus einer beliebigen Datenmanipulation ergibt.

Lass uns das anhand eines Beispiels erklären. Angenommen, du möchtest eine Gruppe von verschachtelten Blöcken erstellen, die Details zum Autor des Beitrags und eine Auswahl der letzten Beiträge desselben Autors anzeigen.

Ein Gruppenblock mit Beitragsautor und neuesten Beiträgen
Ein Gruppenblock mit Beitragsautor und neuesten Beiträgen

Als Gutenberg-Nutzer kannst du die folgenden Blöcke verwenden:

  • Der Überschrift-Kernblock
  • Der Beitragsautor-Kernblock
  • Der Neueste Beiträge-Kernblock

Du könntest auch eine Gruppe erstellen, die diese Blöcke enthält, und die Gruppe zu wiederverwendbaren Blöcken für die zukünftige Verwendung hinzufügen.

Hinzufügen eines Gruppenblocks zu wiederverwendbaren Blöcken
Hinzufügen eines Gruppenblocks zu wiederverwendbaren Blöcken

Das ist doch ganz einfach, oder? Du kannst einen dynamischen Block erstellen und ihn im Handumdrehen zu deinen Beiträgen und Seiten hinzufügen.

Seit WordPress 5.9 bietet der Block-Editor mehr als 90 verschiedene Blöcke, und die Chancen stehen gut, dass du den richtigen Block für dich findest. Und wenn du noch mehr brauchst, kannst du im WordPress-Plugin-Verzeichnis nach weiteren Blöcken suchen, die es kostenlos gibt.

Aber was ist, wenn du ein WordPress-Entwickler bist – oder eine Karriere als WordPress-Entwickler planst? Vielleicht hast du ganz spezielle Bedürfnisse und kannst den Block, den du suchst, nicht finden, oder du möchtest einfach neue berufliche Fähigkeiten erwerben. In solchen Situationen möchtest du vielleicht lernen, wie du deine dynamischen Blöcke erstellst.

Dynamische Blöcke in Gutenberg aus der Sicht eines Entwicklers

Dynamische Blöcke haben zwei Hauptanwendungsfälle.

Der erste Anwendungsfall ist, wenn du den Inhalt eines Blocks aktualisieren musst, obwohl die Seite, die den Block enthält, noch nicht aktualisiert wurde. Das ist z. B. der Fall, wenn der Block eine Liste der neuesten Beiträge oder Kommentare enthält und generell immer dann, wenn der Inhalt des Blocks dynamisch mit Hilfe von Daten aus der Datenbank erstellt wird.

Hinzufügen eines Query Loop Blocks
Hinzufügen eines Query Loop Blocks

Der zweite Anwendungsfall ist, wenn eine Aktualisierung des Blockcodes sofort auf dem Frontend angezeigt werden soll. Wenn du einen dynamischen Block anstelle eines statischen Blocks verwendest, werden die Änderungen sofort auf alle Vorkommen des Blocks angewendet.

Wenn du dagegen den HTML-Code eines statischen Blocks änderst, wird dem Nutzer ein Ungültigkeitsdialog angezeigt, bis alle Instanzen der vorherigen Version des Blocks entfernt und durch die neue Version ersetzt wurden oder du die alte Version als veraltet markierst (siehe auch Veraltete Version und Blockvalidierung, Veraltete Version und Migrationserfahrung).

Unerwarteter oder ungültiger Inhalt.
Unerwarteter oder ungültiger Inhalt.

Bevor du mit der Erstellung von dynamischen Blöcken beginnen kannst, musst du jedoch einige Konzepte verstehen.

Anwendungsstatus und Datenspeicher

Gutenberg ist eine React SPA-Anwendung, und alles in Gutenberg ist eine React-Komponente. Beitragstitel, Überschriften, Absätze, Bilder und alle HTML-Inhaltsblöcke im Editor sind React-Komponenten, ebenso wie die Steuerelemente für die Seitenleiste und die Blocksymbolleiste.

In unserem letzten Artikel haben wir nur Eigenschaften verwendet, um Daten zu speichern. In diesem Artikel gehen wir einen Schritt weiter und führen das Konzept des Zustands ein.

Vereinfacht gesagt, ist das state Objekt ein einfaches JavaScript-Objekt, das Informationen über eine Komponente enthält. Die state der Komponente kann sich im Laufe der Zeit ändern, und jedes Mal, wenn sie sich ändert, wird die Komponente neu dargestellt.

Ähnlich wie das state Objekt sind auch die Properties einfache JavaScript-Objekte, die Informationen über die Komponente enthalten. Es gibt jedoch einen entscheidenden Unterschied zwischen props und state:

props werden an die Komponente weitergegeben (ähnlich wie Funktionsparameter), während state innerhalb der Komponente verwaltet wird (ähnlich wie Variablen, die in einer Funktion deklariert werden).

Du kannst dir den Status als eine Momentaufnahme von Daten zu einem bestimmten Zeitpunkt vorstellen, die eine Anwendung speichert, um das Verhalten einer Komponente zu steuern. Wenn zum Beispiel die Seitenleiste für die Einstellungen des Blockeditors geöffnet ist, wird eine Information irgendwo im state Objekt gespeichert.

Wenn die Informationen innerhalb einer einzelnen Komponente geteilt werden, nennen wir sie lokalen Zustand. Wenn die Informationen von mehreren Komponenten innerhalb einer Anwendung gemeinsam genutzt werden, nennen wir sie Anwendungsstatus.

Der Anwendungsstatus ist eng mit dem Konzept des Speichers verbunden. In den Redux-Dokumenten heißt es:

Ein Store enthält den gesamten Zustandsbaum deiner Anwendung. Die einzige Möglichkeit, den Zustand darin zu ändern, besteht darin, eine Aktion darauf auszuführen.

Redux speichert also den Zustand einer Anwendung in einem einzigen unveränderlichen Objektbaum (einem Store). Der Objektbaum kann nur geändert werden, indem ein neues Objekt mit Hilfe von Actions und Reducern erstellt wird.

In WordPress werden die Stores durch das WordPress-Datenmodul verwaltet.

Modularität, Pakete und Datenspeicher in Gutenberg

Das Gutenberg-Repository basiert von Grund auf auf mehreren wiederverwendbaren und unabhängigen Modulen, die zusammen die Bearbeitungsoberfläche bilden. Diese Module werden auch Pakete genannt.

In der offiziellen Dokumentation werden zwei verschiedene Arten von Paketen aufgeführt:

  • Produktionspakete bilden den Produktionscode, der im Browser ausgeführt wird. In WordPress gibt es zwei Arten von Produktionspaketen:
    • Pakete mit Stylesheets stellen Stylesheets bereit, damit sie richtig funktionieren.
    • Pakete mit Datenspeichern definieren Datenspeicher, um ihren Status zu verwalten. Pakete mit Datenspeichern können von Plugins und Themes von Drittanbietern verwendet werden, um Daten abzurufen und zu manipulieren.
  • Entwicklungspakete werden im Entwicklungsmodus verwendet. Diese Pakete enthalten Werkzeuge zum Linting, Testen, Bauen usw.

Hier sind wir vor allem an Paketen mit Datenspeichern interessiert, die zum Abrufen und Verarbeiten von Daten verwendet werden.

Der WordPress-Datenspeicher

Das WordPress-Datenmodul baut auf Redux auf und teilt die drei Redux-Kernprinzipien, allerdings mit einigen wichtigen Unterschieden.

Die offizielle Dokumentation enthält die folgende Definition:

Das Datenmodul von WordPress dient als Drehscheibe für die Verwaltung des Anwendungsstatus sowohl für Plugins als auch für WordPress selbst und bietet Werkzeuge zur Verwaltung von Daten innerhalb und zwischen verschiedenen Modulen. Es ist als modulares Muster für die Organisation und den Austausch von Daten konzipiert: einfach genug, um die Anforderungen eines kleinen Plugins zu erfüllen, und skalierbar, um die Anforderungen einer komplexen Single-Page-Anwendung zu erfüllen.

Gutenberg registriert standardmäßig mehrere Datenspeicher im Anwendungsstatus. Jeder dieser Speicher hat einen bestimmten Namen und Zweck:

Über diese Stores kannst du auf eine ganze Reihe von Daten zugreifen:

  1. Daten, die sich auf den aktuellen Beitrag beziehen, z. B. Beitragstitel, Auszug, Kategorien und Tags, Blöcke usw.
  2. Daten, die sich auf die Benutzeroberfläche beziehen, z. B. ob ein Toggle ein- oder ausgeschaltet ist.
  3. Daten, die sich auf die gesamte WordPress-Installation beziehen, z. B. registrierte Taxonomien, Beitragstypen, Blogtitel, Autoren usw.

Diese Stores befinden sich im globalen wp Objekt. Um auf den Status eines Stores zuzugreifen, verwendest du die Funktion select.

Um zu sehen, wie sie funktioniert, erstelle einen neuen Beitrag oder eine neue Seite und rufe den Inspektor deines Browsers auf. Suche die Konsole und gib die folgende Codezeile ein:

wp.data.select("core")

Das Ergebnis ist ein Objekt mit einer Liste von Funktionen, die du verwenden kannst, um Daten aus dem core Datenspeicher abzurufen. Diese Funktionen werden Selektoren genannt und dienen als Schnittstellen für den Zugriff auf Statuswerte.

Das Core WordPress Data Store Objekt
Das Core WordPress Data Store Objekt

Der WordPress-Datenspeicher enthält Informationen über WordPress im Allgemeinen und die Selektoren sind der Weg, wie du diese Informationen erhältst. Zum Beispiel liefert getCurrentUser() Informationen über den aktuellen Benutzer:

wp.data.select("core").getCurrentUser()
Untersuchen der getCurrentUser Antwort
Untersuchen der getCurrentUser Antwort

Ein weiterer Selektor, den du verwenden kannst, um Benutzerdetails aus dem Datenspeicher abzurufen, ist getUsers() :

wp.data.select("core").getUsers()

Das folgende Bild zeigt das Antwortobjekt:

Untersuchen der getCurrentUser Antwort
Untersuchen der getUsers Antwort

Um Details für einen einzelnen Benutzer zu erhalten, kannst du einfach die folgende Zeile eingeben:

wp.data.select("core").getUsers()[0]

Mit demselben Selektor kannst du auch Benutzer mit der Rolle author abrufen:

wp.data.select( 'core' ).getUsers({ who: 'authors' })

Du kannst auch registrierte Taxonomien abrufen:

wp.data.select("core").getTaxonomies()
Untersuchen der getTaxonomies Antwort.
Untersuchen der getTaxonomies Antwort.

Eine Liste der registrierten Beitragstypen:

wp.data.select("core").getPostTypes()

Oder eine Liste der Plugins:

wp.data.select("core").getPlugins()

Versuchen wir nun, auf einen anderen Datenspeicher zuzugreifen. Dazu verwendest du immer noch die Funktion select, gibst aber einen anderen Namespace an. Versuchen wir das Folgende:

wp.data.select("core/edit-post")

Jetzt erhältst du das folgende Antwortobjekt.

Zugriff auf die UI-Daten des Editors
Zugriff auf die UI-Daten des Editors

Wenn du wissen willst, ob die Seitenleiste für die Einstellungen geöffnet ist oder nicht, verwendest du den Selektor isEditorSidebarOpened:

wp.data.select("core/edit-post").isEditorSidebarOpened()

Diese Funktion gibt true zurück, wenn die Seitenleiste geöffnet ist:

Die Seitenleiste ist geöffnet.
Die Seitenleiste ist geöffnet.

Wie man auf Postdaten zugreift

Du solltest jetzt ein grundlegendes Verständnis dafür haben, wie du auf Daten zugreifen kannst. Jetzt sehen wir uns einen bestimmten Selektor genauer an, die FunktiongetEntityRecords, die den Zugriff auf die Beitragsdaten ermöglicht.

Klicke im Blockeditor mit der rechten Maustaste und wähle Inspizieren. Kopiere auf der Registerkarte Konsole die folgende Zeile und füge sie ein:

wp.data.select("core").getEntityRecords('postType', 'post')

Dies sendet eine Anfrage an die Rest-API und gibt ein Array von Datensätzen zurück, die den zuletzt veröffentlichten Blogbeiträgen entsprechen.

getEntityRecords gibt eine Liste der Beiträge zurück.
getEntityRecords gibt eine Liste der Beiträge zurück.

getEntityRecords nimmt drei Parameter entgegen:

  • kind string: Art der Entität (z. B. postType).
  • name string: Name der Entität (z. B. post).
  • query ?Objekt: Optionale Begriffsabfrage (z. B. {author: 0}).

Du kannst spezifischere Anfragen erstellen, indem du ein Objekt mit Argumenten verwendest.

Du kannst zum Beispiel festlegen, dass die Antwort nur Beiträge einer bestimmten Kategorie enthalten soll:

wp.data.select("core").getEntityRecords('postType', 'post', {categories: 3})

Du kannst auch nur Artikel von einem bestimmten Autor anfordern:

wp.data.select("core").getEntityRecords('postType', 'post', {author: 2})

Wenn du auf einen der von getEntityRecords zurückgegebenen Datensätze klickst, erhältst du eine Liste der Eigenschaften des ausgewählten Datensatzes:

Eine beispielhafte API-Anfrage mit getEntityRecords.
Eine beispielhafte API-Anfrage mit getEntityRecords.

Wenn du möchtest, dass die Antwort auch das Bild enthält, musst du ein zusätzliches Argument zu deiner vorherigen Anfrage hinzufügen:

wp.data.select("core").getEntityRecords('postType', 'post', {author: 2, _embed: true})
Details zum Featured Image in der getEntityRecords-Antwort.
Details zum Featured Image in der getEntityRecords-Antwort.

Jetzt solltest du besser verstehen, wie du auf den WordPress-Datenspeicher zugreifen und Beitragsdetails abrufen kannst. Einen genaueren Blick auf den getEntityRecords Selektor wirfst du unter Datenabfrage in Gutenberg mit getEntityRecords.

Wie man einen dynamischen Block erstellt: Ein Beispielprojekt

Nach unserer langen theoretischen Einführung können wir nun zur Praxis übergehen und einen dynamischen Block mit den Werkzeugen erstellen, die wir in unserem vorherigen Tutorial zur Blockentwicklung vorgestellt haben.

In diesem Artikel haben wir besprochen:

  1. Wie man eine WordPress-Entwicklungsumgebung einrichtet
  2. Was ist ein Block Scaffolding
  3. Wie man einen statischen Gutenberg-Block erstellt

Deshalb werden wir in diesem Artikel nicht näher auf diese Themen eingehen. Du kannst aber gerne in unserem vorherigen Leitfaden nachschlagen, wenn du zusätzliche Informationen benötigst oder einfach nur auffrischen möchtest.

Eine JavaScript-Entwicklungsumgebung einrichten

Beginnen wir damit, eine JavaScript-Entwicklungsumgebung einzurichten.

Node.js installieren oder aktualisieren

Installiere oder aktualisiere zunächst Node.js. Starte danach dein Kommandozeilentool und führe den folgenden Befehl aus:

node -v

Du solltest deine Node-Version sehen.

Richte deine Entwicklungsumgebung ein

Als nächstes brauchst du eine Entwicklungsumgebung für WordPress. Für unsere Beispiele haben wir DevKinsta verwendet, unser kostenloses WordPress-Entwicklungstool, mit dem du im Handumdrehen eine lokale WordPress-Website erstellen kannst.

Erstellen einer eigenen Website in DevKinsta
Erstellen einer eigenen Website in DevKinsta

Es steht dir aber immer noch frei, eine beliebige lokale WordPress-Entwicklungsumgebung wie MAMP oder XAMPP oder sogar die offizielle wp-env-Lösung zu wählen.

Wenn du DevKinsta verwendest, klicke auf Neue WordPress-Seite oder auf Benutzerdefinierte Seite, fülle die Formularfelder aus und klicke auf Seite erstellen.

Der Installationsprozess dauert ein oder zwei Minuten. Wenn er abgeschlossen ist, starte deine lokale WordPress-Entwicklungswebsite.

Seiten Info Bildschirm in DevKinsta.
Seiten Info Bildschirm in DevKinsta.

Richte dein Block-Plugin ein

Was du jetzt brauchst, ist ein Block-Plugin für den Anfang. Damit du dir die mühsame manuelle Konfiguration ersparen kannst, hat das WordPress-Entwicklerteam das Tool @wordpress/create-block veröffentlicht, das offizielle Null-Konfigurations-Tool zur Erstellung von Gutenberg-Blöcken ist.

In unserem vorherigen Artikel haben wir @wordpress/create-block ausführlich behandelt, so dass wir hier gleich mit der Einrichtung beginnen können.

Navigiere in deinem Kommandozeilentool zum Ordner /wp-content/plugins:

Neues Terminal im Ordner in Mac OS.
Neues Terminal im Ordner in Mac OS.

Wenn du dort bist, führe den folgenden Befehl aus:

npx @wordpress/create-block

Jetzt kannst du das Paket @wordpress/create-block installieren:

Installation des Pakets @wordpress/create-block.
Installation des Pakets @wordpress/create-block.

Zur Bestätigung gibst du y ein und drückst die Eingabetaste.

Dadurch werden die PHP-, SCSS- und JS-Dateien des Plugins im interaktiven Modus generiert.

Nachfolgend findest du die Angaben, die wir in unserem Beispiel verwenden werden. Du kannst diese Angaben nach Belieben ändern:


Sobald du die Eingabetaste gedrückt hast, wird das Plugin heruntergeladen und konfiguriert.

Installation des Block-Plugins.
Installation des Block-Plugins.

Dieser Vorgang kann ein paar Minuten dauern. Wenn er abgeschlossen ist, solltest du den folgenden Bildschirm sehen:

Block bootstrapped im Plugin-Ordner.
Block bootstrapped im Plugin-Ordner.

Du siehst eine Liste mit den Befehlen, die du im Plugin-Verzeichnis ausführen kannst:

  • $ npm start – Starte den Build für die Entwicklung.
  • $ npm run build – Baue den Code für die Produktion.
  • $ npm run format – Formatiere Dateien.
  • $ npm run lint:css – Lint CSS-Dateien.
  • $ npm run lint:js – Lint JavaScript-Dateien.
  • $ npm run packages-update – Aktualisiere die WordPress-Pakete auf die neueste Version.

Okay, wechsle jetzt mit dem folgenden Befehl in das Plugin-Verzeichnis:

cd author-plugin

Und starte deinen Entwicklungs-Build:

npm start

Als Nächstes navigierst du zum Bildschirm Plugins in deinem WordPress-Dashboard und aktivierst das Plugin Author box:

Das Block-Plugin wird im Plugins-Bildschirm aufgeführt.
Das Block-Plugin wird im Plugins-Bildschirm aufgeführt.

Jetzt kannst du überprüfen, ob das Plugin richtig funktioniert. Erstelle einen neuen Beitrag und beginne mit der Eingabe von /, um den Quick-Inserter zu starten:

Das Blockelement im Quick Inserter.
Das Blockelement im Quick Inserter.

Du findest den Autorenkasten-Block auch im Block-Inserter, unter der Kategorie Widgets. Wähle den Block aus, um ihn zum Editor-Canvas hinzuzufügen:

Der WordPress Block Inserter
Der WordPress Block Inserter

Das war’s. Jetzt speicherst du den Beitrag und siehst dir die Seite in der Vorschau an, um zu prüfen, ob der Block richtig angezeigt wird.

Das Block-Gerüst

Wir haben das Blockgerüst in unserem vorherigen Beitrag behandelt. Deshalb geben wir hier nur einen kurzen Überblick über die Dateien, die wir für unsere Beispiele ändern werden.

Der Root-Ordner
Im Root-Ordner findest du die Haupt-PHP-Datei und mehrere Unterordner.

author-plugin.php
Das Paket @wordpress/create-block enthält standardmäßig die folgende PHP-Datei:

/**
 * Plugin Name:       Author box
 * Description:       An example block for Kinsta readers
 * Requires at least: 5.8
 * Requires PHP:      7.0
 * Version:           0.1.0
 * Author:            Carlo
 * License:           GPL-2.0-or-later
 * License URI:       https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain:       author-plugin
 *
 * @package           author-box
 */

/**
 * Registers the block using the metadata loaded from the `block.json` file.
 * Behind the scenes, it registers also all assets so they can be enqueued
 * through the block editor in the corresponding context.
 *
 * @see https://developer.wordpress.org/reference/functions/register_block_type/
 */
function author_box_author_plugin_block_init() {
	register_block_type( __DIR__ . '/build' );
}
add_action( 'init', 'author_box_author_plugin_block_init' );

In der Überschrift siehst du die Angaben, die wir bei der Einrichtung gemacht haben.

Bei statischen Blöcken wirst du die meiste Zeit an den JavaScript-Dateien arbeiten, die sich im Ordner src befinden. Bei dynamischen Blöcken schreibst du PHP-Code, um den Inhalt des Blocks auf dem Frontend anzuzeigen.

Der src-Ordner
Der Ordner src ist dein Entwicklungsordner. Hier findest du die folgenden Dateien:

  • block.json
  • index.js
  • edit.js
  • save.js
  • editor.scss
  • style.scss

block.json
Die block.json ist deine Metadaten-Datei. @wordpress/create-block erzeugt die folgende block.json-Datei:

{
	"$schema": "https://schemas.wp.org/trunk/block.json",
	"apiVersion": 2,
	"name": "author-box/author-plugin",
	"version": "0.1.0",
	"title": "Author box",
	"category": "widgets",
	"icon": "businessperson",
	"description": "An example block for Kinsta readers",
	"supports": {
		"html": false
	},
	"textdomain": "author-plugin",
	"editorScript": "file:./index.js",
	"editorStyle": "file:./index.css",
	"style": "file:./style-index.css"
}

Einen genaueren Blick auf die block.json-Datei im Allgemeinen wirfst du in unserem vorherigen Blogbeitrag.

index.js
In der Datei index.js registrierst du den Blocktyp auf dem Client:

import { registerBlockType } from '@wordpress/blocks';

import './style.scss';

import Edit from './edit';
import save from './save';

registerBlockType('author-box/author-plugin', {
	edit: Edit,
	save,
});

edit.js
In der Datei edit.js baust du die Oberfläche des Blocks auf, die im Editor angezeigt wird:

import { __ } from '@wordpress/i18n';

import { useBlockProps } from '@wordpress/block-editor';

import './editor.scss';

export default function Edit() {
	return (
		<p {...useBlockProps()}>
			{__('Author box – hello from the editor!', 'author-plugin')}
		</p>
	);
}

save.js
Die Datei save.js enthält das Skript, das den Inhalt des Blocks erstellt, der in der Datenbank gespeichert wird. Wir werden diese Datei in diesem Lernprogramm nicht verwenden:

import { __ } from '@wordpress/i18n';

import { useBlockProps } from '@wordpress/block-editor';

export default function save() {
	return (
		<p {...useBlockProps.save()}>
			{__('Author box – hello from the saved content!', 'author-plugin')}
		</p>
	);
}

Erstellen des Blocks zum Rendern im Editor

Öffne dein Projekt in Visual Studio Code oder einem anderen Code-Editor deiner Wahl.

Wenn du Visual Studio Code verwendest, gehe auf Terminal -> Neues Terminal. Dadurch wird ein Terminalfenster im Stammordner deines Projekts geöffnet.

Gib im Terminal (oder in deinem bevorzugten Kommandozeilenprogramm) den folgenden Befehl ein:

npm start

Du führst die Node-Umgebung jetzt im Entwicklungsmodus aus.

Das Block-Plugin-Projekt in Visual Studio Code.
Das Block-Plugin-Projekt in Visual Studio Code.

Von hier an gehst du auf zwei verschiedenen Wegen vor. Um den Block im Editor darzustellen, arbeitest du in der Datei edit.js. Um den Block auf dem Frontend darzustellen, musst du PHP-Code in die Hauptdatei des Plugins schreiben.

Jetzt kremple deine Ärmel hoch, denn die Programmierung beginnt:

Den Block auf dem Server registrieren

Zuerst musst du den Block auf dem Server registrieren und den PHP-Code schreiben, um die Daten aus der Datenbank abzurufen.

In der Datei author-plugin.php musst du ein zweites Argument an die Funktionregister_block_type übergeben:

function author_box_author_plugin_block_init() {
	register_block_type( __DIR__ . '/build', array(
		'render_callback' => 'author_box_author_plugin_render_author_content'
	) );
}
add_action( 'init', 'author_box_author_plugin_block_init' );

Das zweite Argument ist ein Array von Argumenten für die Registrierung eines Blocktyps (die vollständige Liste der verfügbaren Argumente findest du hier). Im obigen Code haben wir nur render_callback angegeben, das die Callback-Funktion bestimmt, die den Block auf dem Bildschirm rendert.

Als Nächstes wirst du die Funktion deklarieren:

function author_box_author_plugin_render_author_content() {
	return 'Hello World!';
}

Speichere die Datei, erstelle einen neuen Beitrag oder eine neue Seite und füge den Author Box-Block in die Arbeitsfläche des Editors ein.

Der WordPress Block Inserter.
Der WordPress Block Inserter.

Der Block-Editor zeigt immer noch den Starter-Block an, da wir die Datei edit.js noch nicht geändert haben.

Aber wenn du dir den Beitrag im Frontend ansiehst, siehst du, dass der ursprüngliche Blockinhalt jetzt durch den String „Hello World“ ersetzt wurde.

Da der im Frontend angezeigte HTML-Code von der PHP-Datei generiert wird, muss die Funktion save nichts mehr zurückgeben. Gehen wir also direkt in die Datei save.js und ändern den Code wie unten gezeigt:

export default function save() {
	return null;
}

Blockattribute definieren

Jetzt brauchst du einen Ort, an dem du die Benutzereinstellungen speichern kannst. Zum Beispiel die Anzahl der Beiträge, die aus der Datenbank abgerufen werden sollen, ob ein bestimmtes Feld angezeigt werden soll oder nicht, usw. Dazu definierst du eine Reihe von attributes in der Datei block.json.

Du könntest dem Nutzer zum Beispiel die Möglichkeit geben, die Anzahl der Beiträge zu bestimmen, die in den Block aufgenommen werden sollen, die Option, ein Bild, ein Datum oder einen Auszug anzuzeigen und/oder das Profilbild des Autors auszublenden/anzuzeigen.

Hier ist die vollständige Liste der Attribute, die wir für die Erstellung unseres Beispielblocks verwenden werden:

{
	...
	"attributes": {
		"numberOfItems": {
			"type": "number",
			"default": 3
		},
		"columns": {
			"type": "number",
			"default": 1
		},
		"displayDate": {
			"type": "boolean",
			"default": true
		},
		"displayExcerpt": {
			"type": "boolean",
			"default": true
		},
		"displayThumbnail": {
			"type": "boolean",
			"default": true
		},
		"displayAuthorInfo": {
			"type": "boolean",
			"default": true
		},
		"showAvatar": {
			"type": "boolean",
			"default": true
		}, 
		"avatarSize": {
			"type": "number",
			"default": 48
		},
		"showBio": {
			"type": "boolean",
			"default": true
		}
	}
}

Erstellen des Blocks, der im Editor angezeigt werden soll

Der Selektor getEntityRecords ist im Paket @wordpress/data enthalten. Um ihn zu verwenden, musst du den useSelect Hook aus diesem Paket in deine edit.js Datei importieren:

import { useSelect } from '@wordpress/data';

Als Nächstes fügst du den folgenden Code in die Funktion Edit() ein:

const posts = useSelect( ( select ) => {
	return select( 'core' ).getEntityRecords( 'postType', 'post', {
		'per_page': 3
	});
});

Im obigen Code haben wir die Anzahl der Beiträge fest programmiert. Du möchtest den Nutzern aber vielleicht die Möglichkeit geben, eine andere Anzahl von Beiträgen festzulegen. Dafür kannst du ein Attribut verwenden.

In deiner block.json solltest du ein numberOfItems Attribut definiert haben. Du kannst es in deiner Edit Funktion verwenden, wie unten gezeigt:

export default function Edit( { attributes } ) {

	const { numberOfItems } = attributes;

	const posts = useSelect( ( select ) => {
		return select( 'core' ).getEntityRecords( 'postType', 'post', {
			'per_page': numberOfItems
		});
	});

	console.log( posts );

	return (
		...
	);
}

Du wirst die Beiträge noch nicht auf dem Bildschirm sehen, aber führe eine console.log aus und sieh dir an, was in der Konsole deines Browserinspektors passiert:

Das Ergebnis in der Konsole deines Browsers.
Das Ergebnis in der Konsole deines Browsers.

useSelect kann zwei Argumente annehmen: einen Inline-Callback und ein Array mit Abhängigkeiten. Beide geben eine memoisierte Version des Callbacks zurück, die sich nur ändert, wenn sich eine der Abhängigkeiten ändert.

Wenn du also bei jeder Änderung des Attributs numberOfItems einen neuen Beitrag abrufen willst, musst du die Funktion Edit wie folgt ändern:

export default function Edit( { attributes } ) {

	const { numberOfItems } = attributes;

	const posts = useSelect(
		( select ) => {
			return select( 'core' ).getEntityRecords( 'postType', 'post', {
				'per_page': numberOfItems
			});
		}, 
		[ numberOfItems ]
	);

	console.log(posts);

	return (
		...
	);
}

Als Nächstes musst du die Liste der Beiträge rendern. Dazu kannst du die integrierte JavaScript-Methode map verwenden:

export default function Edit( { attributes } ) {

	const { numberOfItems } = attributes;

	const posts = useSelect(
		( select ) => {
			return select( 'core' ).getEntityRecords( 'postType', 'post', {
				'per_page': numberOfItems
			});
		},
		[ numberOfItems ]
	);

	console.log(posts);
	
	return (
		<div { ...useBlockProps() }>
			<ul>
				{ posts && posts.map( ( post ) => {
					return (
						<li key={ post.id }>
							<h5>
								<a href={ post.link }>
									{ 
										post.title.rendered ? 
										post.title.rendered :
										__( 'Default title', 'author-plugin' )
									}
								</a>
							</h5>
						</li>
					)
				})}
			</ul>
		</div>
	);
}

Sie prüft zunächst, ob du mindestens einen Beitrag im Array hast, und führt dann die Schleife aus.

Da wir die Methode map mit einer React-Komponente verwenden, benutzen wir auch ein key -Attribut, um die Post-ID dem aktuellen Listenelement zuzuweisen.

post.link und post.title.rendered geben die URL bzw. den Titel des Beitrags wieder.

Die Abbildung unten zeigt die vollständige Liste der Eigenschaften des post Objekts.

Das Post-Objekt.
Das Post-Objekt.

Der obige Code ist nur ein grundlegendes Beispiel für die Verwendung von getEntityRecords. Jetzt ist es an der Zeit, unser Wissen in die Praxis umzusetzen.

Nehmen wir an, du möchtest verhindern, dass dein Block HTML-Tags wiedergibt, die der Benutzer dem Beitragstitel hinzugefügt hat. WordPress bietet dafür eine RawHTML Komponente.

Zuerst importierst du die Komponente aus dem Paket @wordpress/element:

import { RawHTML } from '@wordpress/element';

Als Nächstes verpackst du den Beitragstitel in ein RawHTML Element:

<div { ...useBlockProps() }>
	<ul>
		{ posts && posts.map((post) => {
			return (
				<li key={ post.id }>
					<h5>
						<a href={ post.link }>
							{ post.title.rendered ? (
								<RawHTML>
									{ post.title.rendered }
								</RawHTML>
							) : (
								__( 'Default title', 'author-plugin' )
							)}
						</a>
					</h5>
				</li>
			)
		})}
	</ul>
</div>

Und das war’s. Füge nun einen HTML-Tag zu deinem Beitragstitel hinzu und speichere den Beitrag. Teste dann deinen Code mit und ohne RawHTML und sieh, wie sich der Inhalt deines Blocks auf dem Bildschirm verändert.

Hinzufügen des Datums

WordPress bietet eine Reihe von JavaScript-Funktionen zur Verwaltung und Formatierung von Datumsangaben. Um diese Funktionen zu nutzen, musst du sie zunächst aus dem Paket@wordpress/date in deine edit.js-Datei importieren:

import { dateI18n, format, __experimentalGetSettings } from '@wordpress/date';
  • dateI18n: Formatiere ein Datum und übersetze es in das Gebietsschema der Website.
  • format: Formatiere ein Datum.
  • __experimentalGetSettings: Zeigt das Datum in dem Format an, das in den allgemeinen Einstellungen von WordPress festgelegt wurde.

Diese Funktionen sind nicht dokumentiert, aber du findest nützliche Beispiele im Quellcode verschiedener Blöcke. Siehe zum Beispiel die Dateien latest-posts und post-date edit.js.

Füge nun das Attribut displayDate hinzu:

const { numberOfItems, displayDate } = attributes;

Füge dann den folgenden Code in das Element <li> ein:

{ 
	displayDate && (
		<time
			className='wp-block-author-box-author-plugin__post-date'
			dateTime={ format( 'c', post.date_gmt ) }
		>
			{ dateI18n(
				__experimentalGetSettings().formats.date, 
				post.date_gmt
			)}
		</time>
	) 
}

Was passiert hier?

  • Wenn displayDate true ist, wird das Datum mit einem time Element angezeigt.
  • Das Attribut dateTime gibt die Uhrzeit und/oder das Datum des Elements in einem der zulässigen Formate an.
  • dateI18n ruft das Datum im lokalisierten Format ab. Diese Funktion funktioniert ähnlich wie die PHP date_i18n WordPress-Funktion.

Den Auszug hinzufügen

Jetzt sollte es einfach sein, den Auszug des Beitrags hinzuzufügen. Sieh dir zunächst die Eigenschaft excerpt im Inspektor des Browsers an. Du wirst sehen, dass der eigentliche Inhalt in excerpt.rendered gespeichert ist.

Inspektion des Beitragsauszugs in Chrome DevTools.
Inspektion des Beitragsauszugs in Chrome DevTools.

Als Nächstes fügst du das Attribut displayExcerpt zum Objekt attributes hinzu:

const { numberOfItems, displayDate, displayExcerpt } = attributes;

Füge dann den folgenden Code vor dem </li> schließenden Tag in die Edit Funktion ein:

{
	displayExcerpt &&
	post.excerpt.rendered && (
		<p>
			<RawHTML>
				{ post.excerpt.rendered }
			</RawHTML>
		</p>
	)
}

Falls du dich mit JavaScript nicht auskennst, haben wir hier und oben die Kurzschlussauswertung verwendet, bei der, wenn alle Bedingungen wahr sind, der Wert des letzten Operanden zurückgegeben wird (lies mehr in Inline If mit logischem && Operator und logischem AND (&&)).

Zum Schluss kannst du deinen Code noch einmal testen. Ändere den Wert des Attributs in der Datei block.json und schau, was im Editor passiert.

Füge das Featured Image hinzu

Jetzt musst du den Code hinzufügen, mit dem die Featured Images gerendert werden. Beginne damit, das Attribut displayThumbnail zu attributes hinzuzufügen:

const { 
	numberOfItems, 
	displayDate, 
	displayExcerpt, 
	displayThumbnail 
} = attributes;

Jetzt musst du herausfinden, wo das Featured Image gespeichert ist. Wie wir bereits erwähnt haben, musst du ein neues Argument _embed zu deiner Abfrage hinzufügen, um das Featured Image zu erhalten. Geh zurück zu deinem Code und ändere die Abfrageargumente wie folgt:

const posts = useSelect(
	( select ) => {
		return select( 'core' ).getEntityRecords( 'postType', 'post', {
			'per_page': numberOfItems,
			'_embed': true
		});
	},
	[ numberOfItems ]
);

Hier haben wir einfach '_embed': true zu dem Array der Argumente hinzugefügt. Dadurch erhältst du ein post Objekt, das die Eigenschaft _embedded enthält, die dir die Bilddetails liefert, die du für die Anzeige der vorgestellten Bilder benötigst.

Jetzt solltest du wissen, wo du die Bilddetails findest.

Details zum Featured Image in der getEntityRecords-Antwort.
Details zum Featured Image in der getEntityRecords-Antwort.

Du musst nur den Code hinzufügen, der das Bild auf dem Bildschirm anzeigt:

{
	displayThumbnail && 
	post._embedded && 
	post._embedded['wp:featuredmedia'] &&
	post._embedded['wp:featuredmedia'][0] &&
	<img 
	className='wp-block-author-box-author-plugin__post-thumbnail'
		src={ post._embedded['wp:featuredmedia'][0].media_details.sizes.medium.source_url }
		alt={ post._embedded['wp:featuredmedia'][0].alt_text }
	/>
}

Speichere die Datei, wechsle in den Block-Editor und überprüfe, ob das Bild korrekt angezeigt wird, wenn das Attribut displayThumbnail auf true gesetzt ist.

Eine Liste von Beiträgen mit Bild, Datum und Auszug.
Eine Liste von Beiträgen mit Bild, Datum und Auszug.

Sidebar-Steuerelemente hinzufügen

Bis jetzt haben wir die Standardwerte der Attribute in der block.json verwendet. Aus unserem vorherigen Artikel wissen wir jedoch, dass wir Event-Handler definieren können, um den Benutzern die Möglichkeit zu geben, jedem Attribut eigene Werte zuzuweisen.

Dazu fügst du eine Reihe von Steuerelementen in die Seitenleiste der Blockeinstellungen ein. In edit.js importierst du die folgenden Komponenten aus den entsprechenden Paketen:

import { 
	useBlockProps,
	InspectorControls
} from '@wordpress/block-editor';

import {
	PanelBody,
	PanelRow,
	QueryControls,
	ToggleControl,
	RangeControl
} from '@wordpress/components';
  • InspectorControls: Enthält Einstellungen für die Seitenleiste, die den gesamten Block betreffen (siehe auf GitHub)
  • PanelBody: Fügt der Einstellungen-Seitenleiste einen zusammenklappbaren Container hinzu (siehe aif GitHub)
  • PanelRow: Erzeugt einen generischen Container für die Steuerelemente der Seitenleiste (siehe auf GitHub)
  • QueryControls: Stellt Steuerelemente für Einstellungen zur Verfügung, um eine Abfrage zu erstellen (siehe auf GitHub)
  • ToggleControl: Bietet einen Toggle-Button, mit dem Nutzer eine bestimmte Option aktivieren/deaktivieren können (siehe auf GitHub)
  • RangeControl: Wird verwendet, um eine Auswahl aus einer Reihe von inkrementellen Werten zu treffen (siehe auf GitHub)

Als Nächstes musst du die Funktion Edit aktualisieren, um die jetzt verfügbaren Steuerelemente zu verwenden. Ändere zunächst die Funktion Edit wie folgt:

export default function Edit( { attributes, setAttributes } ) {

	const { 
		numberOfItems, 
		columns, 
		displayExcerpt, 
		displayDate, 
		displayThumbnail
	} = attributes;

	const posts = useSelect(
		( select ) => {
			return select( 'core' ).getEntityRecords( 'postType', 'post', {
				'per_page': numberOfItems,
				'_embed': true
			});
		},
		[ numberOfItems ]
	);
	...
}

Beachte die Eigenschaft setAttributes, die an die Funktion Edit übergeben wird.

Jetzt kannst du die entsprechenden Elemente zu deinem JSX-Code hinzufügen:

return (
	<>
		<InspectorControls>
			<PanelBody title={ __( 'Content Settings', 'author-plugin' ) }>
				<PanelRow>
					<QueryControls 
						numberOfItems={ numberOfItems }
						onNumberOfItemsChange={ ( value ) =>
							setAttributes( { numberOfItems: value } )
						}
						minItems={ 1 }
						maxItems={ 10 }
					/>
				</PanelRow>
				<PanelRow>
					<RangeControl
						label={ __( 'Number of Columns', 'author-plugin' ) }
						value={ columns }
						onChange={ ( value ) =>
							setAttributes( { columns: value } )
						}
						min={ 1 }
						max={ 4 }
						required
					/>
				</PanelRow>
				<PanelRow>
					<ToggleControl
						label={ __( 'Show Featured Image', 'author-plugin' ) }
						checked={ displayThumbnail }
						onChange={ () =>
							setAttributes( { displayThumbnail: ! displayThumbnail } )
						}
					/>
				</PanelRow>
				<PanelRow>
					<ToggleControl
						label={ __( 'Show Date', 'author-plugin' ) }
						checked={ displayDate }
						onChange={ () =>
							setAttributes( { displayDate: ! displayDate } )
						}
					/>
				</PanelRow>
				<PanelRow>
					<ToggleControl
						label={ __( 'Display Excerpt', 'author-plugin' ) }
						checked={ displayExcerpt }
						onChange={ () =>
							setAttributes( { displayExcerpt: ! displayExcerpt } )
						}
					/>
				</PanelRow>
			</PanelBody>
		</InspectorControls>
		<div { ...useBlockProps() }>
			...
		</div>
	</>
);

Wow, das ist ganz schön viel Code, oder? Aber es ist ziemlich einfach zu verstehen.

Die Elementattribute, die deine Aufmerksamkeit am meisten verdienen, sind onNumberOfItemsChange in QueryControls und onChange in RangeControl und ToggleControl. Diese Attribute legen die Ereignishandler fest, mit denen der Benutzer das Aussehen und/oder das Verhalten eines Blocks anpassen kann.

Du wirst außerdem feststellen, dass wir die Tags <> und </> verwendet haben, die die kurze Syntax für die Deklaration von React-Fragmenten sind.

Speichere jetzt deine Datei, gehe in den Editor und aktualisiere die Seite:

Blockeinstellungen.
Blockeinstellungen.

Ist alles da? Dann lass uns weitermachen und die Details des Beitragsautors hinzufügen.

Den Autor des Beitrags finden

Wie bereits erwähnt, zeigt unser Block eine Liste von Artikeln an, die von demselben Autor wie der aktuelle Beitrag geschrieben wurden.

Um die ID des Verfassers des Beitrags zu erhalten, importierst du den getCurrentPostAttribute Selektor aus dem core/editor Datenspeicher:

wp.data.select( 'core/editor' ).getCurrentPostAttribute( 'author' )

getCurrentPostAttribute gibt einen Attributwert für den gespeicherten Beitrag zurück.

Sobald du die Autoren-ID hast, kannst du die Abfrage wie folgt ändern:

const posts = useSelect(
	( select ) => {

		const _authorId = select( 'core/editor' ).getCurrentPostAttribute( 'author' );
	
		return select( 'core' ).getEntityRecords( 'postType', 'post', {
			'author': _authorId,
			'per_page': numberOfItems,
			'_embed': true
		});
	},
	[ numberOfItems ]
);

Mit diesem Code erhältst du eine Liste der n Artikel des selben Autors wie der aktuelle Beitrag.

Jetzt, wo du die Autoren-ID hast, kannst du sie auch verwenden, um weitere Daten aus der Datenbank abzurufen.

Autorendetails anzeigen

Da wir keine Dokumentation zur Verfügung haben, haben wir den Code aus dem Hauptblock Post Author als Referenz verwendet.

Um die Autorendetails anzuzeigen, musst du zunächst eine neue Abhängigkeit importieren:

import { forEach } from 'lodash';

Dann aktualisierst du in der Funktion Edit das Objekt attributes wie folgt:

const { 
	numberOfItems, 
	columns, 
	displayExcerpt, 
	displayDate, 
	displayThumbnail, 
	displayAuthorInfo, 
	showAvatar, 
	avatarSize, 
	showBio 
} = attributes;

Anschließend bearbeitest du den Code aus dem vorherigen Abschnitt, um die Autorendaten abzurufen:

const { authorDetails, posts } = useSelect(
	( select ) => {

		const _authorId = select( 'core/editor' ).getCurrentPostAttribute( 'author' );

		const authorDetails = _authorId ? select( 'core' ).getUser( _authorId ) : null;
	
		const posts = select( 'core' ).getEntityRecords( 'postType', 'post', {
			'author': _authorId,
			'per_page': numberOfItems,
			'_embed': true
		});

		return { 
			authorDetails: authorDetails,
			posts: posts
		};
	},
	[ numberOfItems ]
);

Beachte, dass wir den getUser Selektor verwendet haben, um die Autorendetails zu erhalten.

Als Nächstes möchtest du vielleicht den Avatar des Autors abrufen. Der folgende Code erstellt ein Array mit den URLs und Größen der Avatare:

const avatarSizes = [];
if ( authorDetails ) {
	forEach( authorDetails.avatar_urls, ( url, size ) => {
		avatarSizes.push( {
			value: size,
			label: `${ size } x ${ size }`,
		} );
	} );
}

Dann fügst du die Seitenleisten und Steuerelemente hinzu, damit die Benutzer den Autorenbereich im Block anpassen können:

return (
	<>
		<InspectorControls>
			<PanelBody title={ __( 'Author Info', 'author-plugin' ) }>
				<PanelRow>
					<ToggleControl
						label={ __( 'Display Author Info', 'author-plugin' ) }
						checked={ displayAuthorInfo }
						onChange={ () =>
							setAttributes( { displayAuthorInfo: ! displayAuthorInfo } )
						}
					/>
				</PanelRow>
				{ displayAuthorInfo && (
					<>
						<PanelRow>
							<ToggleControl
								label={ __( 'Show avatar' ) }
								checked={ showAvatar }
								onChange={ () =>
									setAttributes( { showAvatar: ! showAvatar } )
								}
							/>
							{ showAvatar && (
								<SelectControl
									label={ __( 'Avatar size' ) }
									value={ avatarSize }
									options={ avatarSizes }
									onChange={ ( size ) => {
										setAttributes( {
											avatarSize: Number( size ),
										} );
									} }
								/>
							) }
						</PanelRow>
						<PanelRow>
							<ToggleControl
								label={ __( 'Show Bio', 'author-plugin' ) }
								checked={ showBio }
								onChange={ () =>
									setAttributes( { showBio: ! showBio } )
								}
							/>
						</PanelRow>
					</>
				) }
			</PanelBody>
			...
		</InspectorControls>
		...
	</>
);

Das Bild unten zeigt die aktualisierte Einstellungs-Seitenleiste:

Die Autoreninfo-Einstellungsleiste.
Die Autoreninfo-Einstellungsleiste.

Schließlich kannst du den Abschnitt für den Autor zu deinem Block hinzufügen:

return (
	<>
		<InspectorControls>
		...
		</InspectorControls>

		<div { ...useBlockProps() }>
			{ displayAuthorInfo  && authorDetails && (
				<div className="wp-block-author-box-author-plugin__author">
					{ showAvatar && (
						<div className="wp-block-author-box-author-plugin__avatar">
							<img
								width={ avatarSize }
								src={
									authorDetails.avatar_urls[
										avatarSize
									]
								}
								alt={ authorDetails.name }
							/>
						</div>
					) }
					<div className='wp-block-author-box-author-plugin__author-content'>
						<p className='wp-block-author-box-author-plugin__name'>
							{ authorDetails.name }
						</p>
						{ showBio &&
							// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining
							authorDetails?.description &&
							authorDetails.description.length > 0 && (
							<p className='wp-block-author-box-author-plugin__description'>{ authorDetails.description }</p>
						) }
					</div>
				</div>
			)}
			<ul>
			...
			</ul>
		</div>
	</>
);

Das folgende Bild zeigt, wie er auf dem Bildschirm dargestellt wird.

Abschnitt Autorendetails und Info-Einstellungen.
Abschnitt Autorendetails und Info-Einstellungen.

Speichere nun deine edit.js Datei und führe deine Tests durch. Dein Block sollte je nach Blockeinstellungen unterschiedliche Elemente enthalten.

Autorendetails zeigen nicht die Biografie des Autors an.
Autorendetails zeigen nicht die Biografie des Autors an.

Eine letzte Sache fehlt noch: die Anzahl der Spalten für die Anzeige der Artikel.

Ändere die Anzahl der Kolumnen

Um dem Benutzer die Möglichkeit zu geben, Artikelvorschauen in Spalten anzuzeigen, haben wir das Attribut columns in der Datei block.json definiert. Außerdem haben wir ein columns -Attribut in das Skript eingefügt und ein Einstellungselement erstellt, mit dem die Benutzer die Anzahl der Spalten ändern können.

Im JSX-Code oben hast du sicher bemerkt, dass wir mehreren Elementen CSS-Klassen hinzugefügt haben:

Klassen, die den Elementen im Abschnitt Autor zugewiesen wurden:

  • wp-block-author-box-author-plugin__author
  • wp-block-author-box-author-plugin__avatar
  • wp-block-author-box-author-plugin__author-content
  • wp-block-author-box-author-plugin__name
  • wp-block-author-box-author-plugin__description

Klassen, die den Elementen im Abschnitt „Inhalt“ zugewiesen wurden:

  • wp-block-author-box-author-plugin__post-items
  • wp-block-author-box-author-plugin__post-thumbnail
  • wp-block-author-box-author-plugin__post-title
  • wp-block-author-box-author-plugin__post-date
  • wp-block-author-box-author-plugin__post-excerpt

Eine Klasse fehlt noch. Der Name dieser Klasse wird dynamisch generiert, um die Anzahl der vom Benutzer festgelegten Spalten widerzuspiegeln.

Gehe zurück zur Datei Edit.js und ändere das Element ul wie folgt:

<ul className={ `wp-block-author-box-author-plugin__post-items columns-${ columns }` }>
	...
</ul>

Wir haben eine neue Klasse columns-${ columns } hinzugefügt, die der Syntax für Vorlagenliterale entspricht, um einen Ausdruck in einen String einzufügen. Auf diese Weise hängt das Attribut, das an das Element ul angehängt wird, von den Benutzereinstellungen ab (z. B. columns-1, columns-2, usw.).

Öffne nun die Datei style.scss und ersetze den bestehenden Code durch den folgenden:

.wp-block-author-box-author-plugin {
	background-color: #21759b;
	color: #fff;
	padding: .6em;
	ul.wp-block-author-box-author-plugin__post-items {
		padding: 0;
		list-style-type: none;
		display: grid;
		gap: .5em;
		@for $i from 2 through 4 {
			&.columns-#{ $i } {
				grid-template-columns: repeat(#{ $i }, 1fr);
			}
		}
		li {
			list-style: none;
			img.wp-block-author-box-author-plugin__post-thumbnail {
				height: auto;
				max-width: 100%;
			}
		}
		
	}
}
.wp-block-author-box-author-plugin__author {
	display: flex;
    flex-wrap: wrap;
}

.wp-block-author-box-author-plugin__avatar {
	margin-right: 1em;
}

.wp-block-author-box-author-plugin__author-content {
	flex-basis: 0;
    flex-grow: 1;
}

Wir werden nicht tiefer in den Code eindringen, da dies den Rahmen dieses Artikels sprengen würde. Aber wenn du tiefer einsteigen möchtest, kannst du die folgenden Ressourcen nutzen:

Der Autorenblock im Editor.
Der Autorenblock im Editor.

Das war’s mit dem Rendering des Blocks im Editor.

Den Block zum Rendern auf der Seite erstellen

Jetzt, da der Code für die Darstellung des Blocks im Editor fertig ist, können wir den Block für die Darstellung im Frontend erstellen.

Wie wir bereits erwähnt haben, ist bei dynamischen Blöcken die Plugin-Datei dafür verantwortlich, den HTML-Code zu erzeugen, der im Frontend gerendert wird.

Öffne also die Hauptdatei deines Plugins (in unserem Beispiel author-plugin.php).

Als Erstes musst du die Blockattribute für die WordPress-PHP-Funktion verfügbar machen. Ändere die Funktionsdefinition in deiner PHP-Datei wie folgt:

function author_box_author_plugin_render_author_content( $attr ) {
	...
}

Jetzt kannst du die WordPress-Funktionen verwenden, um Daten abzurufen und zu manipulieren. Du kannst zum Beispiel get_posts verwenden, um die neuesten Blogbeiträge abzurufen (mehr dazu in unserem ausführlichen Artikel über die Funktionget_posts):

function author_box_author_plugin_render_author_content( $attr ) {
	$args = array(
		'numberposts'	=> $attr['numberOfItems'],
	);
	$my_posts = get_posts( $args );
	
	if( ! empty( $my_posts ) ){
		$output = '<ul>';
		foreach ( $my_posts as $p ){
			$output .= '<li><a href="' . esc_url( get_permalink( $p->ID ) ) . '">' 
			. $p->post_title . '</a></li>';
		}
		$output .= '</ul>';
	}
	return $output ?? '<strong>Sorry. No posts matching your criteria!</strong>';
}

Die obige Funktion ruft die neuesten numberOfItems Blogbeiträge aus deiner WordPress-Datenbank ab (standardmäßig ist post_type auf post eingestellt) und gibt ein Array von $post Objekten zurück. Dann durchläuft sie das Array, um die Listenelemente zu erstellen.

Wenn du dir die HTML-Ausgabe ansiehst, wirst du feststellen, dass es sich um eine einfache Liste von Beiträgen handelt, wie in der folgenden Abbildung zu sehen ist:

Eine einfache Liste von Beiträgen.
Eine einfache Liste von Beiträgen.

In unserem vorherigen Artikel haben wir erwähnt, dass du den useBlockProps React-Hook verwenden wirst, um das Wrapper-Element des Blocks in deinem JSX-Code zu markieren. Das Gleiche musst du in deiner PHP-Funktion tun.

WordPress stellt dafür die Funktionget_block_wrapper_attributes zur Verfügung.

Ändere also deinen PHP-Code wie folgt:

function author_box_author_plugin_render_author_content( $attr ) {
	$args = array(
		'numberposts'	=> $attr['numberOfItems']
	);
	$my_posts = get_posts( $args );
	
	if( ! empty( $my_posts ) ){
		$output = '<div ' . get_block_wrapper_attributes() . '>';
		$output .= '<ul>';
		foreach ( $my_posts as $p ){
			
			$title = $p->post_title ? $p->post_title : 'Default title';
			$url = esc_url( get_permalink( $p->ID ) );

			$output .= '<li>';
			$output .= '<a href="' . $url . '">' . $title . '</a>';
			$output .= '</li>';
		}
		$output .= '</ul>';
		$output .= '</div>';
	}
	return $output ?? '<strong>Sorry. No posts matching your criteria!</strong>';
}

Jetzt wurde dem Container-Element eine wp-block-author-box-author-plugin Klasse zugewiesen und der Block hat eine andere Hintergrundfarbe.

Dann erhält die Funktion get_posts die Daten von WP_Posts und der Zyklus foreach baut die Listenelemente auf (siehe auch Wie man die von get_posts zurückgegebenen Daten anzeigt).

Eine Liste von Beiträgen, denen eine CSS-Klasse zugewiesen wurde.
Eine Liste von Beiträgen, denen eine CSS-Klasse zugewiesen wurde.

Featured Image, Datum und Auszug hinzufügen

Als Nächstes musst du Beitragsvorschaubilder, Datum und Auszüge hinzufügen. Ändere deinen PHP-Code in derselben Datei wie folgt:

function author_box_author_plugin_render_author_content( $attr ) {
	$args = array(
		'numberposts'	=> $attr['numberOfItems']
	);
	$my_posts = get_posts( $args );
	
	if( ! empty( $my_posts ) ){
		$output = '<div ' . get_block_wrapper_attributes() . '>';
		$output .= '<ul class="wp-block-author-box-author-plugin__post-items columns-">';

		foreach ( $my_posts as $p ){
			
			$title = $p->post_title ? $p->post_title : 'Default title';
			$url = esc_url( get_permalink( $p->ID ) );
			$thumbnail = has_post_thumbnail( $p->ID ) ? get_the_post_thumbnail( $p->ID, 'medium' ) : '';

			$output .= '<li>';
			if( ! empty( $thumbnail ) && $attr['displayThumbnail'] ){
				$output .= $thumbnail;
			}
			$output .= '<h5><a href="' . $url . '">' . $title . '</a></h5>';
			if( $attr['displayDate'] ){
				$output .= '<time datetime="' . esc_attr( get_the_date( 'c', $p ) ) . '">' . esc_html( get_the_date( '', $p ) ) . '</time>';
			}
			if( get_the_excerpt( $p ) && $attr['displayExcerpt'] ){
				$output .= '<p>' . get_the_excerpt( $p ) . '</p>';
			}
			$output .= '</li>';
		}
		$output .= '</ul>';
		$output .= '</div>';
	}
	return $output ?? '<strong>Sorry. No posts matching your criteria!</strong>';
}

Die Schleife foreach durchläuft das Array $my_posts. Bei jeder Iteration werden mehrere Bedingungen geprüft, die die Attributwerte überprüfen und die Ausgabe entsprechend aufbauen.

Sieh dir jetzt die Ausgabe auf dem Bildschirm an:

Eine Liste von Beiträgen mit Bildern, Datum und Auszügen.
Eine Liste von Beiträgen mit Bildern, Datum und Auszügen.

Jetzt kannst du deine Tests durchführen. Ändere die Einstellungen für Datum, Auszug und Vorschaubilder und prüfe, wie sich der Inhalt des Blocks im Frontend verändert.

Beiträge in Spalten anzeigen

In unserem JavaScript-Code haben wir eine columns-${ columns } Klasse verwendet, um die Beitragsvorschauen in Spalten anzuzeigen. Jetzt müssen wir das Gleiche in PHP machen.

Dazu musst du einfach diese beiden Codezeilen einfügen:

$num_cols = $attr['columns'] > 1 ? strval( $attr['columns'] ) : '1';

$output .= '<ul class="wp-block-author-box-author-plugin__post-items columns-' . $num_cols . '">';

Dadurch wird eine columns-n Klasse an das ul Element angehängt, das die Beitragsvorschauen enthält. Jetzt sollte die Anzahl der Spalten, die auf der Seite angezeigt werden, mit der Anzahl der Spalten übereinstimmen, die in den Blockeinstellungen festgelegt wurde.

Erstelle die Autorenbox

Zuletzt musst du die Box mit den Angaben zum Autor erstellen, einschließlich Avatar, Name und Beschreibung.

In der Callback-Funktion musst du eine Reihe von Bedingungen hinzufügen, um den aktuellen Wert der einzelnen Attribute zu überprüfen:

if( $attr['displayAuthorInfo'] ){
	$output .= '<div class="wp-block-author-box-author-plugin__author">';
	
	if( $attr['showAvatar'] ){
		$output .= '<div class="wp-block-author-box-author-plugin__avatar">' 
			. get_avatar( get_the_author_meta( 'ID' ), $attr['avatarSize'] ) 
			. '</div>';
	}

	$output .= '<div class="wp-block-author-box-author-plugin__author-content">';
	
	$output .= '<div class="wp-block-author-box-author-plugin__name">' 
		. get_the_author_meta( 'display_name' ) 
		. '</div>';

	if( $attr['showBio'] ){
		$output .= '<div class="wp-block-author-box-author-plugin__description">' 
			. get_the_author_meta( 'description' ) 
			. '</div>';
	}

	$output .= '</div>';
	$output .= '</div>';
}

Der Code ist ganz einfach. Er prüft den aktuellen Wert jedes Attributs und wenn er true ist, erzeugt er den erforderlichen HTML-Code.

Speichere nun deine PHP-Datei und vergleiche den Block im Editor mit dem gleichen Block im Frontend.

Unser benutzerdefinierter Block im Block-Editor.
Unser benutzerdefinierter Block im Block-Editor.

Den vollständigen Code des Beispielblocks findest du in dieser öffentlichen Gist.

Empfohlene Ressourcen für die Entwicklung dynamischer Blöcke

Wenn du beim Lesen dieses Artikels hellhörig geworden bist und dir bewusst geworden ist, dass du dich mit der Erstellung von Gutenberg-Blöcken beruflich weiterentwickeln kannst, raten wir dir, die Technologien, die hinter der Blockentwicklung stehen, weiter zu erforschen und dir neue Kenntnisse anzueignen.

Auch wenn es immer noch keine verlässliche offizielle Dokumentation gibt, so gibt es doch hervorragende kostenlose und kostenpflichtige Ressourcen, die wir beim Schreiben dieses Artikels konsultiert haben. Unter den vielen verfügbaren Ressourcen empfehlen wir die folgenden:

Offizielle Ressourcen

Empfohlene Tutorials von WordPress Core-Mitarbeitern

JavaScript, React und Redux Ressourcen

Verwandte Ressourcen von Kinsta

Zusammenfassung

Wir haben das Ende dieser (zweiten) langen Reise durch die Gutenberg-Blockentwicklung erreicht.

In diesem Artikel haben wir einige fortgeschrittene Themen behandelt, z. B. Application State und Redux-Stores. Hoffentlich hast du jetzt ein besseres Verständnis für die Blockentwicklung im Allgemeinen.

Node.js-, Webpack-, Babel-, React- und Redux-Kenntnisse sind unerlässlich, wenn es darum geht, fortgeschrittene Gutenberg-Blöcke zu entwickeln, aber du musst kein React-Ninja sein, um loszulegen. Die Entwicklung von Gutenberg-Blöcken zu lernen, muss nicht unbedingt kompliziert sein. Du musst nur die richtige Motivation mitbringen und den richtigen Lernweg einschlagen.

Wir hoffen, dass dieser Artikel – und der vorherige – dir den richtigen Weg zeigt, damit du mit der Gutenberg-Entwicklung sofort loslegen kannst.

Jetzt liegt es an dir! Hast du schon dynamische Blöcke erstellt? Hast du irgendwelche Beispiele, die du mit uns teilen möchtest? Und was waren die größten Hürden, die du überwinden musstest? Schreib uns unten einen Kommentar.

Carlo Daniele Kinsta

Carlo is a passionate lover of webdesign and front-end development. He has been playing with WordPress for more than 20 years, also in collaboration with Italian and European universities and educational institutions. He has written hundreds of articles and guides about WordPress, published both on Italian and international websites, as well as on printed magazines. You can find him on LinkedIn.